summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Sliwa <dominik.sliwa@toradex.com>2017-10-03 17:22:39 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2017-10-06 16:59:08 +0200
commite9636255d1a151de8903e952f64ed779e832f613 (patch)
treec466a17cdc371e9045d47de8d86c4c227b8b4f6e
parent795eccdb989221b0d9ff32a34cd0f7127db89860 (diff)
mfd: apalis-tk1-k20: clean-up and fix support for 0.10 k20 fwApalis-TK1_LXDE-Image_2.7b4-20171007
Signed-off-by: Dominik Sliwa <dominik.sliwa@toradex.com> Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
-rw-r--r--drivers/base/regmap/regmap.c4
-rw-r--r--drivers/gpio/gpio-apalis-tk1-k20.c27
-rw-r--r--drivers/iio/adc/apalis-tk1-k20_adc.c2
-rw-r--r--drivers/input/touchscreen/apalis-tk1-k20_ts.c8
-rw-r--r--drivers/mfd/apalis-tk1-k20-ezp.h5
-rw-r--r--drivers/mfd/apalis-tk1-k20.c95
-rw-r--r--drivers/net/can/apalis-tk1-k20-can.c197
-rw-r--r--include/linux/mfd/apalis-tk1-k20.h12
8 files changed, 202 insertions, 148 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 0b43b26..4d45a42 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 0061625..f914cf0 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 <dominik.sliwa@toradex.com>
*
* 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 b08f091..d87cf61 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 <dominik.sliwa@toradex.com>
*
* 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 38e4a30..55aaa6f 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 <dominik.sliwa@toradex.com>
*
* 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 <linux/platform_device.h>
#include <linux/mfd/apalis-tk1-k20.h>
#include <linux/kernel.h>
@@ -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 <dominik.sliwa@toradex.com>");
diff --git a/drivers/mfd/apalis-tk1-k20-ezp.h b/drivers/mfd/apalis-tk1-k20-ezp.h
index b2c65e4b..c8b0c51 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 <dominik.sliwa@toradex.com>
*
* 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 2727365..a71a452 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 <dominik.sliwa@toradex.com>
*
* based on an driver for MC13xxx by:
@@ -26,7 +26,7 @@
#include <linux/delay.h>
#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 f701210..1df9fae 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 <dominik.sliwa@toradex.com>
+ *
* 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 <linux/can/core.h>
@@ -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 <dominik.sliwa@toradex.com>");
diff --git a/include/linux/mfd/apalis-tk1-k20.h b/include/linux/mfd/apalis-tk1-k20.h
index 2ef2896..47b906e 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 <dominik.sliwa@toradex.com>
*
* 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;