From e9636255d1a151de8903e952f64ed779e832f613 Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Tue, 3 Oct 2017 17:22:39 +0200 Subject: mfd: apalis-tk1-k20: clean-up and fix support for 0.10 k20 fw Signed-off-by: Dominik Sliwa Acked-by: Marcel Ziswiler --- drivers/base/regmap/regmap.c | 4 +- drivers/gpio/gpio-apalis-tk1-k20.c | 27 ++-- drivers/iio/adc/apalis-tk1-k20_adc.c | 2 +- drivers/input/touchscreen/apalis-tk1-k20_ts.c | 8 +- drivers/mfd/apalis-tk1-k20-ezp.h | 5 +- drivers/mfd/apalis-tk1-k20.c | 95 ++++++++----- drivers/net/can/apalis-tk1-k20-can.c | 197 ++++++++++++++------------ include/linux/mfd/apalis-tk1-k20.h | 12 +- 8 files changed, 202 insertions(+), 148 deletions(-) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 0b43b260390b..4d45a42f1d00 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1300,10 +1300,10 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, */ if (map->use_single_rw) { for (i = 0; i < val_count; i++) { - ret = regmap_raw_write(map, + ret = _regmap_raw_write(map, reg + (i * map->reg_stride), val + (i * val_bytes), - val_bytes); + val_bytes, false); if (ret != 0) return ret; } diff --git a/drivers/gpio/gpio-apalis-tk1-k20.c b/drivers/gpio/gpio-apalis-tk1-k20.c index 0061625ac0f4..f914cf0d8ded 100644 --- a/drivers/gpio/gpio-apalis-tk1-k20.c +++ b/drivers/gpio/gpio-apalis-tk1-k20.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Toradex AG + * Copyright 2016-2017 Toradex AG * Dominik Sliwa * * This program is free software; you can redistribute it and/or modify it under @@ -19,7 +19,8 @@ struct apalis_tk1_k20_gpio { struct apalis_tk1_k20_regmap *apalis_tk1_k20; }; -static int apalis_tk1_k20_gpio_input(struct gpio_chip *chip, unsigned offset) +static int apalis_tk1_k20_gpio_input(struct gpio_chip *chip, + unsigned int offset) { struct apalis_tk1_k20_gpio *gpio = container_of(chip, struct apalis_tk1_k20_gpio, chip); @@ -36,8 +37,9 @@ static int apalis_tk1_k20_gpio_input(struct gpio_chip *chip, unsigned offset) return 0; } -static int apalis_tk1_k20_gpio_output(struct gpio_chip *chip, unsigned offset, - int value) +static int apalis_tk1_k20_gpio_output(struct gpio_chip *chip, + unsigned int offset, + int value) { struct apalis_tk1_k20_gpio *gpio = container_of(chip, struct apalis_tk1_k20_gpio, chip); @@ -57,7 +59,7 @@ static int apalis_tk1_k20_gpio_output(struct gpio_chip *chip, unsigned offset, return 0; } -static int apalis_tk1_k20_gpio_get(struct gpio_chip *chip, unsigned offset) +static int apalis_tk1_k20_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct apalis_tk1_k20_gpio *gpio = container_of(chip, struct apalis_tk1_k20_gpio, chip); @@ -79,13 +81,15 @@ static int apalis_tk1_k20_gpio_get(struct gpio_chip *chip, unsigned offset) return value ? 1 : 0; } -static int apalis_tk1_k20_gpio_request(struct gpio_chip *chip, unsigned offset) +static int apalis_tk1_k20_gpio_request(struct gpio_chip *chip, + unsigned int offset) { struct apalis_tk1_k20_gpio *gpio = container_of(chip, struct apalis_tk1_k20_gpio, chip); int status = 0; - dev_dbg(gpio->apalis_tk1_k20->dev, "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); @@ -102,10 +106,11 @@ static int apalis_tk1_k20_gpio_request(struct gpio_chip *chip, unsigned offset) return status; } -static void apalis_tk1_k20_gpio_free(struct gpio_chip *chip, unsigned offset) +static void apalis_tk1_k20_gpio_free(struct gpio_chip *chip, + unsigned int offset) { - struct apalis_tk1_k20_gpio *gpio = container_of(chip, - struct apalis_tk1_k20_gpio, chip); + struct apalis_tk1_k20_gpio *gpio = + container_of(chip, struct apalis_tk1_k20_gpio, chip); apalis_tk1_k20_lock(gpio->apalis_tk1_k20); @@ -118,7 +123,7 @@ static void apalis_tk1_k20_gpio_free(struct gpio_chip *chip, unsigned offset) } -static void apalis_tk1_k20_gpio_set(struct gpio_chip *chip, unsigned offset, +static void apalis_tk1_k20_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct apalis_tk1_k20_gpio *gpio = container_of(chip, diff --git a/drivers/iio/adc/apalis-tk1-k20_adc.c b/drivers/iio/adc/apalis-tk1-k20_adc.c index b08f09141cdc..d87cf61059cc 100644 --- a/drivers/iio/adc/apalis-tk1-k20_adc.c +++ b/drivers/iio/adc/apalis-tk1-k20_adc.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Toradex AG + * Copyright 2016-2017 Toradex AG * Dominik Sliwa * * This program is free software; you can redistribute it and/or modify it under diff --git a/drivers/input/touchscreen/apalis-tk1-k20_ts.c b/drivers/input/touchscreen/apalis-tk1-k20_ts.c index 38e4a3003c8d..55aaa6f07fb9 100644 --- a/drivers/input/touchscreen/apalis-tk1-k20_ts.c +++ b/drivers/input/touchscreen/apalis-tk1-k20_ts.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Toradex AG + * Copyright 2016-2017 Toradex AG * Dominik Sliwa * * Based on driver for the Freescale Semiconductor MC13783 touchscreen by: @@ -10,6 +10,7 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */ + #include #include #include @@ -59,7 +60,7 @@ static void apalis_tk1_k20_ts_report_sample(struct apalis_tk1_k20_ts *priv) y = (yp + ym) / 2; press = (abs(yp - ym) + abs(xp - xm)) / 2; - if ((yp != 0) && ( xp != 0 )) { + if ((yp != 0) && (xp != 0)) { btn = 1; input_report_abs(idev, ABS_X, x); input_report_abs(idev, ABS_Y, y); @@ -226,7 +227,8 @@ static struct platform_driver apalis_tk1_k20_ts_driver = { }, }; -module_platform_driver_probe(apalis_tk1_k20_ts_driver, &apalis_tk1_k20_ts_probe); +module_platform_driver_probe(apalis_tk1_k20_ts_driver, + &apalis_tk1_k20_ts_probe); MODULE_DESCRIPTION("K20 touchscreen controller on Apalis TK1"); MODULE_AUTHOR("Dominik Sliwa "); diff --git a/drivers/mfd/apalis-tk1-k20-ezp.h b/drivers/mfd/apalis-tk1-k20-ezp.h index b2c65e4b60fd..c8b0c518980a 100644 --- a/drivers/mfd/apalis-tk1-k20-ezp.h +++ b/drivers/mfd/apalis-tk1-k20-ezp.h @@ -1,11 +1,12 @@ /* - * Copyright 2016 Toradex AG + * Copyright 2016-2017 Toradex AG * Dominik Sliwa * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ + #ifndef __DRIVERS_MFD_APALIS_TK1_K20_H #define __DRIVERS_MFD_APALIS_TK1_K20_H @@ -29,7 +30,7 @@ #define APALIS_TK1_K20_EZP_WRFCCOB 0xBA #define APALIS_TK1_K20_EZP_FRDFCOOB 0xBB -/* Bits of EZ Port Status register */ +/* Bits of EZ Port status register */ #define APALIS_TK1_K20_EZP_STA_WIP BIT(0) #define APALIS_TK1_K20_EZP_STA_WEN BIT(1) #define APALIS_TK1_K20_EZP_STA_BEDIS BIT(2) diff --git a/drivers/mfd/apalis-tk1-k20.c b/drivers/mfd/apalis-tk1-k20.c index 2727365b0d0f..a71a4520827d 100644 --- a/drivers/mfd/apalis-tk1-k20.c +++ b/drivers/mfd/apalis-tk1-k20.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Toradex AG + * Copyright 2016-2017 Toradex AG * Dominik Sliwa * * based on an driver for MC13xxx by: @@ -26,7 +26,7 @@ #include #include "apalis-tk1-k20-ezp.h" -#define CONFIG_EXPERIMENTAL_K20_HSMODE +#undef CONFIG_EXPERIMENTAL_K20_HSMODE #define APALIS_TK1_K20_MAX_MSG 4 static const struct spi_device_id apalis_tk1_k20_device_ids[] = { { @@ -79,11 +79,14 @@ static int apalis_tk1_k20_spi_read(void *context, const void *reg, .delay_usecs = 0, }; #ifdef CONFIG_EXPERIMENTAL_K20_HSMODE - 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]; int i = 0; + int transfer_count; #endif struct spi_message m; int ret; + spi->mode = SPI_MODE_1; if (reg_size != 1) @@ -108,16 +111,31 @@ static int apalis_tk1_k20_spi_read(void *context, const void *reg, if (val_size == 2) { ret = spi_sync(spi, &m); } else { - spi_message_init(&m); - for (i = 0; (4 * i) < (val_size - 2); i++) { + transfer_count = val_size; + spi_message_init(&m); + ts[0].tx_buf = NULL; + ts[0].rx_buf = r; + ts[0].len = (transfer_count >= 4) ? 4 : transfer_count; + ts[0].cs_change = 0; + ts[0].delay_usecs = 2; + + spi_message_add_tail(&ts[i], &m); + /* + * decrease count but remember about an extra character + * at the transfer beginning + */ + transfer_count = transfer_count - ts[0].len + 1; + + for (i = 1; transfer_count > 0; i++) { ts[i].tx_buf = NULL; - ts[i].rx_buf = &r[2 + (4 * i)]; - ts[i].len = (val_size - 2 - (4 * i) >= 4) ? - 4 : (val_size - 2 - (4 * i)); + /* first entry in r is the status */ + ts[i].rx_buf = &r[(4 * i) - 1]; + ts[i].len = (transfer_count >= 4) ? + 4 : transfer_count; ts[i].cs_change = 0; ts[i].delay_usecs = 2; - spi_message_add_tail(&ts[i], &m); + transfer_count = transfer_count - ts[i].len; } ret = spi_sync(spi, &m); } @@ -162,9 +180,9 @@ 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 + uint8_t in_data[APALIS_TK1_K20_MAX_BULK]; struct spi_message m; struct spi_transfer t = { .tx_buf = out_data, @@ -185,31 +203,33 @@ 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 ) && (count < APALIS_TK1_K20_MAX_BULK)) { + } else if ((count > 2) && (count < APALIS_TK1_K20_MAX_BULK)) { spi_message_init(&m); out_data[0] = APALIS_TK1_K20_BULK_WRITE_INST; - out_data[1] = count -1; + out_data[1] = count - 1; memcpy(&out_data[2], data, count); t.tx_buf = out_data; t.len = 4; spi_message_add_tail(&t, &m); ret = spi_sync(spi, &m); + /* reg. addr + 2 data bytes */ + count = count - 3; spi_message_init(&m); - for (i = 1; (4 * i) < (count - 2); i++) { - ts[i].tx_buf = &out_data[i * 4]; - ts[i].len = (count - 2 - (4 * i) >= 4) ? - 4 : (count - 2 - (4 * i)); - ts[i].cs_change = 0; - ts[i].delay_usecs = 0; - - spi_message_add_tail(&ts[i], &m); - } + for (i = 0; count > 0; i++) { + ts[i].tx_buf = &out_data[(i + 1) * 4]; + ts[i].len = (count >= 4) ? 4 : count; + ts[i].cs_change = 0; + ts[i].delay_usecs = 0; + + spi_message_add_tail(&ts[i], &m); + count = count - ts[i].len; + } ret = spi_sync(spi, &m); #endif } else { - dev_err(dev, "Apalis TK1 K20 MFD Invalid write count = %d\n", + dev_err(dev, "Apalis TK1 K20 MFD invalid write count = %d\n", count); return -ENOTSUPP; } @@ -291,7 +311,6 @@ int apalis_tk1_k20_reg_write_bulk(struct apalis_tk1_k20_regmap *apalis_tk1_k20, if (size > APALIS_TK1_K20_MAX_BULK) return -EINVAL; - return regmap_bulk_write(apalis_tk1_k20->regmap, offset, buf, size); } EXPORT_SYMBOL(apalis_tk1_k20_reg_write_bulk); @@ -567,6 +586,7 @@ static int apalis_tk1_k20_enter_ezport( { uint8_t status = 0x00; uint8_t buffer; + gpio_set_value(apalis_tk1_k20->ezpcs_gpio, 0); msleep(10); apalis_tk1_k20_reset_chip(apalis_tk1_k20); @@ -595,6 +615,7 @@ static int apalis_tk1_k20_erase_chip_ezport( { uint8_t buffer[16]; int i; + if (apalis_tk1_k20_set_wren_ezport(apalis_tk1_k20)) goto bad; if (apalis_tk1_k20_write_ezport(apalis_tk1_k20, APALIS_TK1_K20_EZP_BE, @@ -777,19 +798,19 @@ int apalis_tk1_k20_dev_init(struct device *dev) #ifdef CONFIG_APALIS_TK1_K20_EZP if ((request_firmware(&fw_entry, "apalis-tk1-k20.bin", dev) < 0) - && (revision != APALIS_TK1_K20_FW_VER)) { - dev_err(apalis_tk1_k20->dev, - "Unsupported firmware version %d.%d and no local" - " firmware file available.\n", - (revision & 0xF0 >> 8), - (revision & 0x0F)); - ret = -ENOTSUPP; - goto bad; + && (revision != APALIS_TK1_K20_FW_VER)) { + dev_err(apalis_tk1_k20->dev, + "Unsupported firmware version %d.%d and no local" \ + " firmware file available.\n", + (revision & 0xF0 >> 8), + (revision & 0x0F)); + ret = -ENOTSUPP; + goto bad; } if ((fw_entry == NULL) && (revision != APALIS_TK1_K20_FW_VER)) { dev_err(apalis_tk1_k20->dev, - "Unsupported firmware version %d.%d and no local" + "Unsupported firmware version %d.%d and no local" \ " firmware file available.\n", (revision & 0xF0 >> 8), (revision & 0x0F)); @@ -806,8 +827,8 @@ int apalis_tk1_k20_dev_init(struct device *dev) (revision != APALIS_TK1_K20_FW_VER) && !erase_only && (fw_entry != NULL)) { dev_err(apalis_tk1_k20->dev, - "Unsupported firmware version in both the device as well" - " as the local firmware file.\n"); + "Unsupported firmware version in both the device " \ + "as well as the local firmware file.\n"); release_firmware(fw_entry); ret = -ENOTSUPP; goto bad; @@ -817,7 +838,7 @@ int apalis_tk1_k20_dev_init(struct device *dev) (!apalis_tk1_k20_fw_ezport_status()) && (fw_entry != NULL)) { dev_err(apalis_tk1_k20->dev, - "Unsupported firmware version in the device and the " + "Unsupported firmware version in the device and the " \ "local firmware file disables the EZ Port.\n"); release_firmware(fw_entry); ret = -ENOTSUPP; @@ -995,8 +1016,8 @@ static int apalis_tk1_k20_spi_probe(struct spi_device *spi) apalis_tk1_k20->irq = spi->irq; - spi->max_speed_hz = (spi->max_speed_hz >= APALIS_TK1_K20_MAX_SPI_SPEED) ? - APALIS_TK1_K20_MAX_SPI_SPEED : spi->max_speed_hz; + spi->max_speed_hz = (spi->max_speed_hz >= APALIS_TK1_K20_MAX_SPI_SPEED) + ? APALIS_TK1_K20_MAX_SPI_SPEED : spi->max_speed_hz; ret = spi_setup(spi); if (ret) diff --git a/drivers/net/can/apalis-tk1-k20-can.c b/drivers/net/can/apalis-tk1-k20-can.c index f7012105b7ba..1df9fae96cc3 100644 --- a/drivers/net/can/apalis-tk1-k20-can.c +++ b/drivers/net/can/apalis-tk1-k20-can.c @@ -1,6 +1,13 @@ /* + * Copyright 2016-2017 Toradex AG + * Dominik Sliwa + * * CAN bus driver for Apalis TK1 K20 CAN Controller over MFD device * based on MCP251x CAN driver + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. */ #include @@ -28,7 +35,7 @@ #define CAN_HEADER_MAX_LEN 5 #define CAN_TRANSFER_BUF_LEN (CAN_HEADER_MAX_LEN + CAN_FRAME_MAX_LEN) #define CAN_FRAME_MAX_BITS 128 -#define CAN_MAX_CONTINOUS_READ 8 +#define CAN_MAX_CONTINUOUS_READ 8 #define MB_DLC_OFF 0 #define MB_EID_OFF 1 @@ -107,20 +114,21 @@ static void apalis_tk1_k20_can_clean(struct net_device *net) } static void apalis_tk1_k20_can_hw_tx_frame(struct net_device *net, u8 *buf, - int len, int tx_buf_idx) + int len, int tx_buf_idx) { /* 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, - len); + APALIS_TK1_K20_CAN_OUT_BUF + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), buf, len); apalis_tk1_k20_unlock(priv->apalis_tk1_k20); } static void apalis_tk1_k20_can_hw_tx(struct net_device *net, - struct can_frame *frame, int tx_buf_idx) + struct can_frame *frame, int tx_buf_idx) { u8 buf[CAN_TRANSFER_BUF_LEN]; @@ -130,35 +138,37 @@ static void apalis_tk1_k20_can_hw_tx(struct net_device *net, 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) + int buf_idx) { struct apalis_tk1_k20_priv *priv = netdev_priv(net); apalis_tk1_k20_lock(priv->apalis_tk1_k20); apalis_tk1_k20_reg_read_bulk(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN_OUT_BUF - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), buf, - CAN_TRANSFER_BUF_LEN); + APALIS_TK1_K20_CAN_OUT_BUF + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), buf, + CAN_TRANSFER_BUF_LEN); apalis_tk1_k20_unlock(priv->apalis_tk1_k20); } -static u32 apalis_tk1_k20_can_available_rx_frames (struct net_device *net) +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_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; } @@ -197,7 +207,7 @@ static void apalis_tk1_k20_can_hw_rx(struct net_device *net, int buf_idx) } static netdev_tx_t apalis_tk1_k20_can_hard_start_xmit(struct sk_buff *skb, - struct net_device *net) + struct net_device *net) { struct apalis_tk1_k20_priv *priv = netdev_priv(net); @@ -217,7 +227,7 @@ static netdev_tx_t apalis_tk1_k20_can_hard_start_xmit(struct sk_buff *skb, } static int apalis_tk1_k20_can_do_set_mode(struct net_device *net, - enum can_mode mode) + enum can_mode mode) { struct apalis_tk1_k20_priv *priv = netdev_priv(net); @@ -245,27 +255,31 @@ static int apalis_tk1_k20_can_set_normal_mode(struct net_device *net) apalis_tk1_k20_lock(priv->apalis_tk1_k20); /* Enable interrupts */ apalis_tk1_k20_reg_rmw(priv->apalis_tk1_k20, APALIS_TK1_K20_CANREG - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - CANCTRL_INTEN, CANCTRL_INTEN); + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), + CANCTRL_INTEN, CANCTRL_INTEN); if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { /* Put device into loopback mode */ apalis_tk1_k20_reg_rmw(priv->apalis_tk1_k20, - APALIS_TK1_K20_CANREG - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - CANCTRL_MODMASK, CAN_CTRLMODE_LOOPBACK); + APALIS_TK1_K20_CANREG + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), CANCTRL_MODMASK, + CAN_CTRLMODE_LOOPBACK); } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { /* Put device into listen-only mode */ apalis_tk1_k20_reg_rmw(priv->apalis_tk1_k20, - APALIS_TK1_K20_CANREG - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - CANCTRL_MODMASK, CAN_CTRLMODE_LISTENONLY); + APALIS_TK1_K20_CANREG + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), CANCTRL_MODMASK, + CAN_CTRLMODE_LISTENONLY); } else { /* Put device into normal mode */ apalis_tk1_k20_reg_rmw(priv->apalis_tk1_k20, - APALIS_TK1_K20_CANREG - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - CANCTRL_MODMASK, 0x00); + APALIS_TK1_K20_CANREG + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), CANCTRL_MODMASK, + 0x00); } apalis_tk1_k20_unlock(priv->apalis_tk1_k20); priv->can.state = CAN_STATE_ERROR_ACTIVE; @@ -282,31 +296,38 @@ static int apalis_tk1_k20_can_do_set_bittiming(struct net_device *net) 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 / APALIS_TK1_CAN_CLK_UNIT) && 0xFF); + APALIS_TK1_K20_CAN_BAUD_REG + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), (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_seg1 & 0x7)); + 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_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), - (bt->prop_seg & 0x7)); + APALIS_TK1_K20_CAN_BIT_2 + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), + (bt->prop_seg & 0x7)); apalis_tk1_k20_unlock(priv->apalis_tk1_k20); - dev_vdbg(priv->apalis_tk1_k20->dev, "Setting CAN%d bit timing" - "RJW = %d, PSEG1 = %d, PSEG2 = %d, PROPSEG = %d \n", - priv->pdata->id, bt->sjw, bt->phase_seg1, - bt->phase_seg2, bt->prop_seg); - dev_vdbg(priv->apalis_tk1_k20->dev, "Setting CAN%d bit timing" - "bitrate = %d \n", priv->pdata->id, bt->bitrate); + dev_dbg(priv->apalis_tk1_k20->dev, "Setting CAN%d bitrate " \ + "to %d (0x%X * 6.25kHz)\n", priv->pdata->id, bt->bitrate, + (bt->bitrate / APALIS_TK1_CAN_CLK_UNIT) & 0xFF); + dev_dbg(priv->apalis_tk1_k20->dev, "Setting CAN%d bit timing " \ + "RJW = %d, PSEG1 = %d, PSEG2 = %d, PROPSEG = %d\n", + priv->pdata->id, bt->sjw, bt->phase_seg1, + bt->phase_seg2, bt->prop_seg); + dev_dbg(priv->apalis_tk1_k20->dev, "Setting CAN%d bit timing " \ + "bitrate = %d\n", priv->pdata->id, bt->bitrate); return 0; } static int apalis_tk1_k20_can_setup(struct net_device *net, - struct apalis_tk1_k20_priv *priv) + struct apalis_tk1_k20_priv *priv) { apalis_tk1_k20_can_do_set_bittiming(net); @@ -325,10 +346,10 @@ static void apalis_tk1_k20_can_open_clean(struct net_device *net) if (pdata->id == 0) apalis_tk1_k20_irq_free(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN0_IRQ, priv); + APALIS_TK1_K20_CAN0_IRQ, priv); if (pdata->id == 1) apalis_tk1_k20_irq_free(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN1_IRQ, priv); + APALIS_TK1_K20_CAN1_IRQ, priv); close_candev(net); } @@ -342,10 +363,10 @@ static int apalis_tk1_k20_can_stop(struct net_device *net) priv->force_quit = 1; if (pdata->id == 0) apalis_tk1_k20_irq_free(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN0_IRQ, priv); + APALIS_TK1_K20_CAN0_IRQ, priv); if (pdata->id == 1) apalis_tk1_k20_irq_free(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN1_IRQ, priv); + APALIS_TK1_K20_CAN1_IRQ, priv); destroy_workqueue(priv->wq); priv->wq = NULL; @@ -353,10 +374,10 @@ static int apalis_tk1_k20_can_stop(struct net_device *net) 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); + APALIS_TK1_K20_CAN0_IRQ); if (pdata->id == 1) apalis_tk1_k20_irq_mask(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN1_IRQ); + APALIS_TK1_K20_CAN1_IRQ); /* Disable and clear pending interrupts */ priv->can.state = CAN_STATE_STOPPED; apalis_tk1_k20_unlock(priv->apalis_tk1_k20); @@ -368,7 +389,7 @@ static int apalis_tk1_k20_can_stop(struct net_device *net) } static void apalis_tk1_k20_can_error_skb(struct net_device *net, int can_id, - int data1) + int data1) { struct sk_buff *skb; struct can_frame *frame; @@ -421,15 +442,14 @@ static int apalis_tk1_k20_can_suspend(struct device *dev) 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); + APALIS_TK1_K20_CAN0_IRQ); if (pdata->id == 1) apalis_tk1_k20_irq_mask(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN1_IRQ); + 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. + /* Note: at this point neither IST nor workqueues are running. * open/stop cannot be called anyway so locking is not needed */ if (netif_running(priv->net)) { @@ -458,10 +478,10 @@ static int apalis_tk1_k20_can_resume(struct device *dev) 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); + APALIS_TK1_K20_CAN0_IRQ); if (pdata->id == 1) apalis_tk1_k20_irq_unmask(priv->apalis_tk1_k20, - APALIS_TK1_K20_CAN1_IRQ); + APALIS_TK1_K20_CAN1_IRQ); /* Enable interrupts */ priv->can.state = CAN_STATE_STOPPED; apalis_tk1_k20_unlock(priv->apalis_tk1_k20); @@ -471,6 +491,7 @@ static int apalis_tk1_k20_can_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(apalis_tk1_k20_can_pm_ops, apalis_tk1_k20_can_suspend, apalis_tk1_k20_can_resume); + #endif static void apalis_tk1_k20_can_restart_work_handler(struct work_struct *ws) @@ -509,20 +530,21 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id) { struct apalis_tk1_k20_priv *priv = dev_id; struct net_device *net = priv->net; - int max_continous_read = CAN_MAX_CONTINOUS_READ; + int max_continuous_read = CAN_MAX_CONTINUOUS_READ; mutex_lock(&priv->apalis_tk1_k20_can_lock); - while (!priv->force_quit && max_continous_read) { + while (!priv->force_quit && max_continuous_read) { enum can_state new_state; int ret; u32 intf, eflag; u8 clear_intf = 0; int can_id = 0, data1 = 0; + apalis_tk1_k20_lock(priv->apalis_tk1_k20); ret = apalis_tk1_k20_reg_read(priv->apalis_tk1_k20, - APALIS_TK1_K20_CANREG - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - &intf); + APALIS_TK1_K20_CANREG + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), &intf); apalis_tk1_k20_unlock(priv->apalis_tk1_k20); if (ret) { @@ -530,33 +552,32 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id) break; } - max_continous_read--; + max_continuous_read--; intf &= CANCTRL_INTMASK; /* receive */ if (intf & CANINTF_RX) apalis_tk1_k20_can_hw_rx(net, 0); - /* any error or TX interrupt we need to clear? */ if (intf & (CANINTF_ERR | CANINTF_TX)) clear_intf |= intf & (CANINTF_ERR | CANINTF_TX); apalis_tk1_k20_lock(priv->apalis_tk1_k20); if (clear_intf) ret = apalis_tk1_k20_reg_rmw(priv->apalis_tk1_k20, - APALIS_TK1_K20_CANREG - + APALIS_TK1_K20_CAN_DEV_OFFSET( - priv->pdata->id), - CANCTRL_INTMASK, 0x00); + APALIS_TK1_K20_CANREG + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), + CANCTRL_INTMASK, 0x00); if (ret) { apalis_tk1_k20_unlock(priv->apalis_tk1_k20); dev_err(&net->dev, "Communication error\n"); break; } ret = apalis_tk1_k20_reg_read(priv->apalis_tk1_k20, - APALIS_TK1_K20_CANERR - + APALIS_TK1_K20_CAN_DEV_OFFSET(priv->pdata->id), - &eflag); + APALIS_TK1_K20_CANERR + + APALIS_TK1_K20_CAN_DEV_OFFSET( + priv->pdata->id), &eflag); apalis_tk1_k20_unlock(priv->apalis_tk1_k20); if (ret) { dev_err(&net->dev, "Communication error\n"); @@ -591,12 +612,12 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id) /* Update can state statistics */ switch (priv->can.state) { case CAN_STATE_ERROR_ACTIVE: - if (new_state >= CAN_STATE_ERROR_WARNING - && new_state <= CAN_STATE_BUS_OFF) + if (new_state >= CAN_STATE_ERROR_WARNING && + new_state <= CAN_STATE_BUS_OFF) priv->can.can_stats.error_warning++; case CAN_STATE_ERROR_WARNING: /* fallthrough */ - if (new_state >= CAN_STATE_ERROR_PASSIVE - && new_state <= CAN_STATE_BUS_OFF) + if (new_state >= CAN_STATE_ERROR_PASSIVE && + new_state <= CAN_STATE_BUS_OFF) priv->can.can_stats.error_passive++; break; default: @@ -617,8 +638,8 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id) apalis_tk1_k20_can_error_skb(net, can_id, data1); } - if (priv->can.state == CAN_STATE_BUS_OFF - && priv->can.restart_ms == 0) { + if (priv->can.state == CAN_STATE_BUS_OFF && + priv->can.restart_ms == 0) { priv->force_quit = 1; can_bus_off(net); break; @@ -637,7 +658,6 @@ static irqreturn_t apalis_tk1_k20_can_ist(int irq, void *dev_id) } netif_wake_queue(net); } - } mutex_unlock(&priv->apalis_tk1_k20_can_lock); return IRQ_HANDLED; @@ -663,12 +683,14 @@ static int apalis_tk1_k20_can_open(struct net_device *net) 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, - DEVICE_NAME, priv); + APALIS_TK1_K20_CAN0_IRQ, + apalis_tk1_k20_can_ist, + DEVICE_NAME, priv); if (pdata->id == 1) 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_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"); @@ -717,14 +739,15 @@ static int apalis_tk1_k20_can_probe(struct platform_device *pdev) { struct net_device *net; struct apalis_tk1_k20_priv *priv; - struct apalis_tk1_k20_can_platform_data *pdata = pdev->dev.platform_data; + struct apalis_tk1_k20_can_platform_data *pdata = + pdev->dev.platform_data; int ret = -ENODEV; if (!pdata) { pdata = kmalloc(sizeof(struct apalis_tk1_k20_can_platform_data), GFP_KERNEL); if (pdev->id == -1) - pdata->id = 0 ; + pdata->id = 0; if (pdev->id >= 0 && pdev->id <= K20_CAN_MAX_ID) pdata->id = pdev->id; else @@ -787,7 +810,7 @@ static int apalis_tk1_k20_can_remove(struct platform_device *pdev) } static const struct platform_device_id apalis_tk1_k20_can_idtable[] = { - {.name ="apalis-tk1-k20-can", }, + {.name = "apalis-tk1-k20-can", }, { /* sentinel */} }; @@ -806,7 +829,7 @@ static struct platform_driver apalis_tk1_k20_can_driver = { }; module_platform_driver_probe(apalis_tk1_k20_can_driver, - &apalis_tk1_k20_can_probe); + &apalis_tk1_k20_can_probe); MODULE_DESCRIPTION("CAN driver for K20 MCU on Apalis TK1"); MODULE_AUTHOR("Dominik Sliwa "); diff --git a/include/linux/mfd/apalis-tk1-k20.h b/include/linux/mfd/apalis-tk1-k20.h index 2ef2896f5d6d..47b906e181e1 100644 --- a/include/linux/mfd/apalis-tk1-k20.h +++ b/include/linux/mfd/apalis-tk1-k20.h @@ -1,11 +1,12 @@ /* - * Copyright 2016 Toradex AG + * Copyright 2016-2017 Toradex AG * Dominik Sliwa * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2 as published by the * Free Software Foundation. */ + #ifndef __LINUX_MFD_APALIS_TK1_K20_H #define __LINUX_MFD_APALIS_TK1_K20_H @@ -62,9 +63,10 @@ #define APALIS_TK1_K20_ADC_CH2H 0x76 /* ADC Channel 2 MSB RO */ #define APALIS_TK1_K20_ADC_CH3L 0x77 /* ADC Channel 3 LSB RO */ #define APALIS_TK1_K20_ADC_CH3H 0x78 /* ADC Channel 3 MSB RO */ -/* Bulk read of LSB register can be use to read entire 16-bit in one command */ -/* Bulk read of APALIS_TK1_K20_ADC_CH0L register can be use to read all - * ADC channels in one command */ +/* Bulk read of LSB register can be use to read entire 16-bit in one command + * Bulk read of APALIS_TK1_K20_ADC_CH0L register can be use to read all + * ADC channels in one command + */ /* 0x79-0x7F reserved */ @@ -118,7 +120,7 @@ #define APALIS_TK1_CAN_CLK_UNIT 6250 -#define APALIS_TK1_K20_MAX_SPI_SPEED 12000000 +#define APALIS_TK1_K20_MAX_SPI_SPEED 6000000 struct apalis_tk1_k20_regmap { struct regmap *regmap; -- cgit v1.2.3