aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.14
diff options
context:
space:
mode:
authorMartin Schiller <ms@dev.tdt.de>2018-08-29 15:06:21 +0200
committerJohn Crispin <john@phrozen.org>2018-09-10 09:28:55 +0200
commit628eb271dc5868d3c5bd6a643c213783cce4fd0a (patch)
tree7905d8224c5ccc6efa52726b409c1c5b70d4181f /target/linux/generic/backport-4.14
parentbc24f0ad2b3cc7ca7b74ecef8051c1bbff9d4277 (diff)
downloadupstream-628eb271dc5868d3c5bd6a643c213783cce4fd0a.tar.gz
upstream-628eb271dc5868d3c5bd6a643c213783cce4fd0a.tar.bz2
upstream-628eb271dc5868d3c5bd6a643c213783cce4fd0a.zip
kernel: backport i2c-gpio working over slow can_sleep GPIOs
Signed-off-by: Martin Schiller <ms@dev.tdt.de>
Diffstat (limited to 'target/linux/generic/backport-4.14')
-rw-r--r--target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch84
1 files changed, 84 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch b/target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch
new file mode 100644
index 0000000000..ead6675e0b
--- /dev/null
+++ b/target/linux/generic/backport-4.14/085-v4.16-0001-i2c-gpio-Enable-working-over-slow-can_sleep-GPIOs.patch
@@ -0,0 +1,84 @@
+From f11a04464ae57e8db1bb7634547842b43e36a898 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= <jan.kundrat@cesnet.cz>
+Date: Fri, 22 Dec 2017 22:47:16 +0100
+Subject: i2c: gpio: Enable working over slow can_sleep GPIOs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+"Slow" GPIOs (usually those connected over an SPI or an I2C bus) are,
+well, slow in their operation. It is generally a good idea to avoid
+using them for time-critical operation, but sometimes the hardware just
+sucks, and the software has to cope. In addition to that, the I2C bus
+itself does not actually define any strict timing limits; the bus is
+free to go all the way down to DC. The timeouts (and therefore the
+slowest acceptable frequency) are present only in SMBus.
+
+The `can_sleep` is IMHO a wrong concept to use here. My SPI-to-quad-UART
+chip (MAX14830) is connected via a 26MHz SPI bus, and it happily drives
+SCL at 200kHz (5µs pulses) during my benchmarks. That's faster than the
+maximal allowed speed of the traditional I2C.
+
+The previous version of this code did not really block operation over
+slow GPIO pins, anyway. Instead, it just resorted to printing a warning
+with a backtrace each time a GPIO pin was accessed, thereby slowing
+things down even more.
+
+Finally, it's not just me. A similar patch was originally submitted in
+2015 [1].
+
+[1] https://patchwork.ozlabs.org/patch/450956/
+
+Signed-off-by: Jan Kundrát <jan.kundrat@cesnet.cz>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-gpio.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-gpio.c
++++ b/drivers/i2c/busses/i2c-gpio.c
+@@ -44,7 +44,7 @@ static void i2c_gpio_setsda_val(void *da
+ {
+ struct i2c_gpio_platform_data *pdata = data;
+
+- gpio_set_value(pdata->sda_pin, state);
++ gpio_set_value_cansleep(pdata->sda_pin, state);
+ }
+
+ /* Toggle SCL by changing the direction of the pin. */
+@@ -68,21 +68,21 @@ static void i2c_gpio_setscl_val(void *da
+ {
+ struct i2c_gpio_platform_data *pdata = data;
+
+- gpio_set_value(pdata->scl_pin, state);
++ gpio_set_value_cansleep(pdata->scl_pin, state);
+ }
+
+ static int i2c_gpio_getsda(void *data)
+ {
+ struct i2c_gpio_platform_data *pdata = data;
+
+- return gpio_get_value(pdata->sda_pin);
++ return gpio_get_value_cansleep(pdata->sda_pin);
+ }
+
+ static int i2c_gpio_getscl(void *data)
+ {
+ struct i2c_gpio_platform_data *pdata = data;
+
+- return gpio_get_value(pdata->scl_pin);
++ return gpio_get_value_cansleep(pdata->scl_pin);
+ }
+
+ static int of_i2c_gpio_get_pins(struct device_node *np,
+@@ -175,6 +175,9 @@ static int i2c_gpio_probe(struct platfor
+ memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));
+ }
+
++ if (gpiod_cansleep(gpio_to_desc(pdata->sda_pin)) || gpiod_cansleep(gpio_to_desc(pdata->scl_pin)))
++ dev_warn(&pdev->dev, "Slow GPIO pins might wreak havoc into I2C/SMBus bus timing");
++
+ if (pdata->sda_is_open_drain) {
+ gpio_direction_output(pdata->sda_pin, 1);
+ bit_data->setsda = i2c_gpio_setsda_val;