mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 07:46:48 +00:00
kernel: backport i2c-gpio working over slow can_sleep GPIOs
Signed-off-by: Martin Schiller <ms@dev.tdt.de>
This commit is contained in:
parent
bc24f0ad2b
commit
628eb271dc
@ -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;
|
@ -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;
|
Loading…
Reference in New Issue
Block a user