mfd: apalis-tk1-k20: support for 0.10 k20 fw
authorDominik Sliwa <dominik.sliwa@toradex.com>
Tue, 3 Oct 2017 15:22:39 +0000 (17:22 +0200)
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>
Wed, 4 Oct 2017 23:11:17 +0000 (01:11 +0200)
Signed-off-by: Dominik Sliwa <dominik.sliwa@toradex.com>
Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
drivers/gpio/gpio-apalis-tk1-k20.c
drivers/mfd/apalis-tk1-k20.c
drivers/net/can/apalis-tk1-k20-can.c
include/linux/mfd/apalis-tk1-k20.h

index ddad0153b88b4652fe85655d6ef0b68890131597..0061625ac0f4c31e82c69df5bdc73e56191e925c 100644 (file)
@@ -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);
 
index e2d59462530aecc05162b3b6543ddee91e89dcfd..2727365b0d0fb92feb0a6dcb1fbda13612b49870 100644 (file)
@@ -26,7 +26,8 @@
 #include <linux/delay.h>
 
 #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",
index cff3dca7bf20bf04f7e278ac2533c7609c7e0b0d..f7012105b7ba2823bd1d634b3067b7a834749fe1 100644 (file)
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
-#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);
 
index 48ae8030c8f5b2fbb83b681a871d4476ec8e5636..2ef2896f5d6d8b511f491ff26dc9c73c9da3e7be 100644 (file)
@@ -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 */
 #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)
 #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;