aboutsummaryrefslogtreecommitdiffstats
path: root/patches/1625-i2c-recovery-add-get_bus_free-callback.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/1625-i2c-recovery-add-get_bus_free-callback.patch')
-rw-r--r--patches/1625-i2c-recovery-add-get_bus_free-callback.patch100
1 files changed, 100 insertions, 0 deletions
diff --git a/patches/1625-i2c-recovery-add-get_bus_free-callback.patch b/patches/1625-i2c-recovery-add-get_bus_free-callback.patch
new file mode 100644
index 00000000000000..4cb4110e22df2c
--- /dev/null
+++ b/patches/1625-i2c-recovery-add-get_bus_free-callback.patch
@@ -0,0 +1,100 @@
+From 4dbf3c9b62c97f070a17ee45c6006ebf79747979 Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Date: Wed, 11 Jul 2018 00:24:22 +0200
+Subject: [PATCH 1625/1795] i2c: recovery: add get_bus_free callback
+
+Some IP cores have an internal 'bus free' logic which may be more
+advanced than just checking if SDA is high. Add a separate callback to
+get this status. Filling it is optional.
+
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+(cherry picked from commit 7ca5f6be7900ca753ed01c0202dc5f998a41f4ee)
+Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+---
+ drivers/i2c/i2c-core-base.c | 27 +++++++++++++++++++++++----
+ include/linux/i2c.h | 3 +++
+ 2 files changed, 26 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
+index 7f768c99464f..e48dae0dea7d 100644
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -192,6 +192,22 @@ static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
+ gpiod_set_value_cansleep(adap->bus_recovery_info->sda_gpiod, val);
+ }
+
++static int i2c_generic_bus_free(struct i2c_adapter *adap)
++{
++ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
++ int ret = -EOPNOTSUPP;
++
++ if (bri->get_bus_free)
++ ret = bri->get_bus_free(adap);
++ else if (bri->get_sda)
++ ret = bri->get_sda(adap);
++
++ if (ret < 0)
++ return ret;
++
++ return ret ? 0 : -EBUSY;
++}
++
+ /*
+ * We are generating clock pulses. ndelay() determines durating of clk pulses.
+ * We will generate clock with rate 100 KHz and so duration of both clock levels
+@@ -203,7 +219,7 @@ static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
+ static int i2c_generic_recovery(struct i2c_adapter *adap)
+ {
+ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+- int i = 0, val = 1, ret = 0;
++ int i = 0, val = 1, ret;
+
+ if (bri->prepare_recovery)
+ bri->prepare_recovery(adap);
+@@ -241,14 +257,17 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
+ bri->set_sda(adap, val);
+ ndelay(RECOVERY_NDELAY / 2);
+
+- /* Break if SDA is high */
+- if (val && bri->get_sda) {
+- ret = bri->get_sda(adap) ? 0 : -EBUSY;
++ if (val) {
++ ret = i2c_generic_bus_free(adap);
+ if (ret == 0)
+ break;
+ }
+ }
+
++ /* If we can't check bus status, assume recovery worked */
++ if (ret == -EOPNOTSUPP)
++ ret = 0;
++
+ if (bri->unprepare_recovery)
+ bri->unprepare_recovery(adap);
+
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index 6bc0ddb850c8..c3387435e55f 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -494,6 +494,8 @@ struct i2c_timings {
+ * @set_sda: This sets/clears the SDA line. This or get_sda() is mandatory for
+ * generic SCL recovery. Populated internally, if sda_gpio is a valid GPIO,
+ * for generic GPIO recovery.
++ * @get_bus_free: Returns the bus free state as seen from the IP core in case it
++ * has a more complex internal logic than just reading SDA. Optional.
+ * @prepare_recovery: This will be called before starting recovery. Platform may
+ * configure padmux here for SDA/SCL line or something else they want.
+ * @unprepare_recovery: This will be called after completing recovery. Platform
+@@ -510,6 +512,7 @@ struct i2c_bus_recovery_info {
+ void (*set_scl)(struct i2c_adapter *adap, int val);
+ int (*get_sda)(struct i2c_adapter *adap);
+ void (*set_sda)(struct i2c_adapter *adap, int val);
++ int (*get_bus_free)(struct i2c_adapter *adap);
+
+ void (*prepare_recovery)(struct i2c_adapter *adap);
+ void (*unprepare_recovery)(struct i2c_adapter *adap);
+--
+2.19.0
+