From 4213685bf8731c17a1faa6fe75cace0fd337e353 Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Tue, 3 Oct 2017 17:22:39 +0200 Subject: mfd: apalis-tk1-k20: support for 0.10 k20 fw Signed-off-by: Dominik Sliwa Acked-by: Marcel Ziswiler --- drivers/gpio/gpio-apalis-tk1-k20.c | 2 +- drivers/mfd/apalis-tk1-k20.c | 21 +++++----- drivers/net/can/apalis-tk1-k20-can.c | 75 +++++++++++++++++++++++------------- include/linux/mfd/apalis-tk1-k20.h | 8 ++-- 4 files changed, 63 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/gpio-apalis-tk1-k20.c b/drivers/gpio/gpio-apalis-tk1-k20.c index ddad0153b88b..0061625ac0f4 100644 --- a/drivers/gpio/gpio-apalis-tk1-k20.c +++ b/drivers/gpio/gpio-apalis-tk1-k20.c @@ -85,7 +85,7 @@ static int apalis_tk1_k20_gpio_request(struct gpio_chip *chip, unsigned offset) struct apalis_tk1_k20_gpio, chip); int status = 0; - pr_debug("APALIS TK1 K20 GPIO %s\n", __func__); + dev_dbg(gpio->apalis_tk1_k20->dev, "APALIS TK1 K20 GPIO %s\n",__func__); apalis_tk1_k20_lock(gpio->apalis_tk1_k20); diff --git a/drivers/mfd/apalis-tk1-k20.c b/drivers/mfd/apalis-tk1-k20.c index e2d59462530a..2727365b0d0f 100644 --- a/drivers/mfd/apalis-tk1-k20.c +++ b/drivers/mfd/apalis-tk1-k20.c @@ -26,7 +26,8 @@ #include #include "apalis-tk1-k20-ezp.h" - +#define CONFIG_EXPERIMENTAL_K20_HSMODE +#define APALIS_TK1_K20_MAX_MSG 4 static const struct spi_device_id apalis_tk1_k20_device_ids[] = { { .name = "apalis-tk1-k20", @@ -161,16 +162,18 @@ static int apalis_tk1_k20_spi_write(void *context, const void *data, struct device *dev = context; struct spi_device *spi = to_spi_device(dev); uint8_t out_data[APALIS_TK1_K20_MAX_BULK]; + uint8_t in_data[APALIS_TK1_K20_MAX_BULK]; int ret; #ifdef CONFIG_EXPERIMENTAL_K20_HSMODE - struct spi_device *spi = to_spi_device(dev); + struct spi_message m; struct spi_transfer t = { .tx_buf = out_data, - .rx_buf = NULL, + .rx_buf = in_data, .cs_change = 0, - .delay_usecs = 2, + .delay_usecs = 0, }; - struct spi_transfer ts[APALIS_TK1_K20_MAX_BULK / APALIS_TK1_K20_MAX_MSG]; + struct spi_transfer ts[(APALIS_TK1_K20_MAX_BULK / + APALIS_TK1_K20_MAX_MSG) + 1]; int i = 0; #endif @@ -182,11 +185,6 @@ static int apalis_tk1_k20_spi_write(void *context, const void *data, out_data[2] = ((uint8_t *)data)[1]; ret = spi_write(spi, out_data, 3); #ifdef CONFIG_EXPERIMENTAL_K20_HSMODE - } else if (count == 2) { - out_data[0] = APALIS_TK1_K20_BULK_WRITE_INST; - out_data[1] = count - 1; - memcpy(&out_data[2], data, count); - ret = spi_write(spi, out_data, 4); } else if ( (count > 2 ) && (count < APALIS_TK1_K20_MAX_BULK)) { spi_message_init(&m); @@ -204,12 +202,11 @@ static int apalis_tk1_k20_spi_write(void *context, const void *data, ts[i].len = (count - 2 - (4 * i) >= 4) ? 4 : (count - 2 - (4 * i)); ts[i].cs_change = 0; - ts[i].delay_usecs = 2; + ts[i].delay_usecs = 0; spi_message_add_tail(&ts[i], &m); } ret = spi_sync(spi, &m); - } #endif } else { dev_err(dev, "Apalis TK1 K20 MFD Invalid write count = %d\n", diff --git a/drivers/net/can/apalis-tk1-k20-can.c b/drivers/net/can/apalis-tk1-k20-can.c index cff3dca7bf20..f7012105b7ba 100644 --- a/drivers/net/can/apalis-tk1-k20-can.c +++ b/drivers/net/can/apalis-tk1-k20-can.c @@ -21,11 +21,6 @@ #include #include -#define GET_BYTE(val, byte) \ - (((val) >> ((byte) * 8)) & 0xff) -#define SET_BYTE(val, byte) \ - (((val) & 0xff) << ((byte) * 8)) - /* Buffer size required for the largest transfer (i.e., reading a * frame) */ @@ -116,9 +111,7 @@ static void apalis_tk1_k20_can_hw_tx_frame(struct net_device *net, u8 *buf, { /* TODO: Implement multiple TX buffer handling */ struct apalis_tk1_k20_priv *priv = netdev_priv(net); - apalis_tk1_k20_lock(priv->apalis_tk1_k20); - apalis_tk1_k20_reg_write_bulk(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN_OUT_BUF + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), buf, @@ -135,14 +128,14 @@ static void apalis_tk1_k20_can_hw_tx(struct net_device *net, memcpy(buf + MB_EID_OFF, &frame->can_id, MB_EID_LEN); memcpy(buf + CAN_HEADER_MAX_LEN, frame->data, frame->can_dlc); - apalis_tk1_k20_can_hw_tx_frame(net, buf, frame->can_dlc, tx_buf_idx); + apalis_tk1_k20_can_hw_tx_frame(net, buf, frame->can_dlc + + CAN_HEADER_MAX_LEN, tx_buf_idx); } static void apalis_tk1_k20_can_hw_rx_frame(struct net_device *net, u8 *buf, int buf_idx) { - /* TODO: Implement multiple RX buffer handling */ struct apalis_tk1_k20_priv *priv = netdev_priv(net); apalis_tk1_k20_lock(priv->apalis_tk1_k20); @@ -154,11 +147,27 @@ static void apalis_tk1_k20_can_hw_rx_frame(struct net_device *net, u8 *buf, apalis_tk1_k20_unlock(priv->apalis_tk1_k20); } +static u32 apalis_tk1_k20_can_available_rx_frames (struct net_device *net) +{ + u32 frame_cnt = 0; + struct apalis_tk1_k20_priv *priv = netdev_priv(net); + int ret; + apalis_tk1_k20_lock(priv->apalis_tk1_k20); + + ret = apalis_tk1_k20_reg_read(priv->apalis_tk1_k20, + APALIS_TK1_K20_CAN_IN_BUF_CNT + + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), + frame_cnt); + apalis_tk1_k20_unlock(priv->apalis_tk1_k20); + return (ret == 0) ? frame_cnt : 0; +} + static void apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx) { struct apalis_tk1_k20_priv *priv = netdev_priv(net); struct sk_buff *skb; struct can_frame *frame; + u32 available_frames = 0; u8 buf[CAN_TRANSFER_BUF_LEN]; skb = alloc_can_skb(priv->net, &frame); @@ -168,18 +177,23 @@ static void apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx) return; } - apalis_tk1_k20_can_hw_rx_frame(net, buf, buf_idx); - memcpy(&frame->can_id, buf + MB_EID_OFF, MB_EID_LEN); - /* Data length */ - frame->can_dlc = get_can_dlc(buf[MB_DLC_OFF]); - memcpy(frame->data, buf + CAN_HEADER_MAX_LEN, frame->can_dlc); + available_frames = apalis_tk1_k20_can_available_rx_frames(net); - priv->net->stats.rx_packets++; - priv->net->stats.rx_bytes += frame->can_dlc; + while ((available_frames > 0)) { + apalis_tk1_k20_can_hw_rx_frame(net, buf, buf_idx); + memcpy(&frame->can_id, buf + MB_EID_OFF, MB_EID_LEN); + /* Data length */ + frame->can_dlc = get_can_dlc(buf[MB_DLC_OFF]); + memcpy(frame->data, buf + CAN_HEADER_MAX_LEN, frame->can_dlc); - can_led_event(priv->net, CAN_LED_EVENT_RX); + priv->net->stats.rx_packets++; + priv->net->stats.rx_bytes += frame->can_dlc; - netif_rx_ni(skb); + can_led_event(priv->net, CAN_LED_EVENT_RX); + + netif_rx_ni(skb); + available_frames--; + } } static netdev_tx_t apalis_tk1_k20_can_hard_start_xmit(struct sk_buff *skb, @@ -263,16 +277,19 @@ static int apalis_tk1_k20_can_do_set_bittiming(struct net_device *net) struct apalis_tk1_k20_priv *priv = netdev_priv(net); struct can_bittiming *bt = &priv->can.bittiming; + if ((bt->bitrate / APALIS_TK1_CAN_CLK_UNIT) > 0xFF) + return -EINVAL; + apalis_tk1_k20_lock(priv->apalis_tk1_k20); apalis_tk1_k20_reg_write(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN_BAUD_REG + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - bt->bitrate); + (bt->bitrate / APALIS_TK1_CAN_CLK_UNIT) && 0xFF); apalis_tk1_k20_reg_write(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN_BIT_1 + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), ((bt->sjw & 0x3) << 6) | ((bt->phase_seg2 & 0x7) << 3) - | (bt->phase_seg2 & 0x7)); + | (bt->phase_seg1 & 0x7)); apalis_tk1_k20_reg_write(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN_BIT_2 + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), @@ -333,6 +350,7 @@ static int apalis_tk1_k20_can_stop(struct net_device *net) priv->wq = NULL; mutex_lock(&priv->apalis_tk1_k20_can_lock); + apalis_tk1_k20_lock(priv->apalis_tk1_k20); if (pdata->id == 0) apalis_tk1_k20_irq_mask(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN0_IRQ); @@ -341,7 +359,7 @@ static int apalis_tk1_k20_can_stop(struct net_device *net) APALIS_TK1_K20_CAN1_IRQ); /* Disable and clear pending interrupts */ priv->can.state = CAN_STATE_STOPPED; - + apalis_tk1_k20_unlock(priv->apalis_tk1_k20); mutex_unlock(&priv->apalis_tk1_k20_can_lock); can_led_event(net, CAN_LED_EVENT_STOP); @@ -400,6 +418,7 @@ static int apalis_tk1_k20_can_suspend(struct device *dev) priv->force_quit = 1; mutex_lock(&priv->apalis_tk1_k20_can_lock); + apalis_tk1_k20_lock(priv->apalis_tk1_k20); if (pdata->id == 0) apalis_tk1_k20_irq_mask(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN0_IRQ); @@ -407,7 +426,7 @@ static int apalis_tk1_k20_can_suspend(struct device *dev) apalis_tk1_k20_irq_mask(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN1_IRQ); /* Disable interrupts */ - + apalis_tk1_k20_unlock(priv->apalis_tk1_k20); mutex_unlock(&priv->apalis_tk1_k20_can_lock); /* * Note: at this point neither IST nor workqueues are running. @@ -436,6 +455,7 @@ static int apalis_tk1_k20_can_resume(struct device *dev) priv->force_quit = 0; mutex_lock(&priv->apalis_tk1_k20_can_lock); + apalis_tk1_k20_lock(priv->apalis_tk1_k20); if (pdata->id == 0) apalis_tk1_k20_irq_unmask(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN0_IRQ); @@ -444,7 +464,7 @@ static int apalis_tk1_k20_can_resume(struct device *dev) APALIS_TK1_K20_CAN1_IRQ); /* Enable interrupts */ priv->can.state = CAN_STATE_STOPPED; - + apalis_tk1_k20_unlock(priv->apalis_tk1_k20); mutex_unlock(&priv->apalis_tk1_k20_can_lock); return 0; } @@ -640,9 +660,7 @@ static int apalis_tk1_k20_can_open(struct net_device *net) priv->force_quit = 0; priv->tx_skb = NULL; priv->tx_len = 0; - apalis_tk1_k20_lock(priv->apalis_tk1_k20); - if (pdata->id == 0) ret = apalis_tk1_k20_irq_request(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN0_IRQ, apalis_tk1_k20_can_ist, @@ -651,7 +669,7 @@ static int apalis_tk1_k20_can_open(struct net_device *net) ret = apalis_tk1_k20_irq_request(priv->apalis_tk1_k20, APALIS_TK1_K20_CAN1_IRQ, apalis_tk1_k20_can_ist, DEVICE_NAME, priv); - + apalis_tk1_k20_unlock(priv->apalis_tk1_k20); if (ret) { dev_err(&net->dev, "failed to acquire IRQ\n"); close_candev(net); @@ -667,11 +685,13 @@ static int apalis_tk1_k20_can_open(struct net_device *net) apalis_tk1_k20_can_open_clean(net); goto open_unlock; } + ret = apalis_tk1_k20_can_setup(net, priv); if (ret) { apalis_tk1_k20_can_open_clean(net); goto open_unlock; } + ret = apalis_tk1_k20_can_set_normal_mode(net); if (ret) { apalis_tk1_k20_can_open_clean(net); @@ -683,7 +703,6 @@ static int apalis_tk1_k20_can_open(struct net_device *net) netif_wake_queue(net); open_unlock: - apalis_tk1_k20_unlock(priv->apalis_tk1_k20); mutex_unlock(&priv->apalis_tk1_k20_can_lock); return ret; } @@ -727,10 +746,12 @@ static int apalis_tk1_k20_can_probe(struct platform_device *pdev) priv = netdev_priv(net); priv->can.bittiming_const = &apalis_tk1_k20_can_bittiming_const; priv->can.do_set_mode = apalis_tk1_k20_can_do_set_mode; + priv->can.clock.freq = 8000000; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; priv->net = net; priv->pdata = pdata; + priv->apalis_tk1_k20 = dev_get_drvdata(pdev->dev.parent); mutex_init(&priv->apalis_tk1_k20_can_lock); diff --git a/include/linux/mfd/apalis-tk1-k20.h b/include/linux/mfd/apalis-tk1-k20.h index 48ae8030c8f5..2ef2896f5d6d 100644 --- a/include/linux/mfd/apalis-tk1-k20.h +++ b/include/linux/mfd/apalis-tk1-k20.h @@ -21,7 +21,7 @@ #define APALIS_TK1_K20_BULK_WRITE_INST 0x3C #define APALIS_TK1_K20_BULK_READ_INST 0xC3 -#define APALIS_TK1_K20_MAX_BULK (64) +#define APALIS_TK1_K20_MAX_BULK (32) /* General registers*/ #define APALIS_TK1_K20_STAREG 0x00 /* general status register RO */ @@ -104,7 +104,7 @@ #define APALIS_TK1_K20_TSC_IRQ 4 #define APALIS_TK1_K20_GPIO_IRQ 5 -#define APALIS_TK1_K20_FW_VER 0x09 +#define APALIS_TK1_K20_FW_VER 0x0A #define FW_MINOR (APALIS_TK1_K20_FW_VER & 0x0F) #define FW_MAJOR ((APALIS_TK1_K20_FW_VER & 0xF0) >> 4) @@ -116,7 +116,9 @@ #define APALIS_TK1_K20_IRQ_REG_CNT 1 #define APALIS_TK1_K20_IRQ_PER_REG 8 -#define APALIS_TK1_K20_MAX_SPI_SPEED 6000000 +#define APALIS_TK1_CAN_CLK_UNIT 6250 + +#define APALIS_TK1_K20_MAX_SPI_SPEED 12000000 struct apalis_tk1_k20_regmap { struct regmap *regmap; -- cgit v1.2.3