From: Dinh Nguyen <dingu...@kernel.org>

commit 73b66146e5a976b1c4b3fe3a14b950b54fb080eb from
https://github.com/altera-opensource/linux-socfpga.git

[upstream commit b2f670af1feab3325cce5a251128f30711148771]

The I2C pins on the SoCFPGA platforms do not go through a GPIO module,
thus cannot be recovered by the default method of by doing a GPIO access.
Only a reset of the I2C IP block can a recovery be successful, so this
change effectively resets the I2C controller, NOT any attached clients.

Reviewed-by: Andy Shevchenko <andriy.shevche...@linux.intel.com>
Signed-off-by: Dinh Nguyen <dingu...@kernel.org>
Signed-off-by: Wenlin Kang <wenlin.k...@windriver.com>
---
 drivers/i2c/busses/i2c-designware-core.h    |  1 +
 drivers/i2c/busses/i2c-designware-master.c  | 49 ++++++++++++++++++---
 drivers/i2c/busses/i2c-designware-platdrv.c |  1 +
 3 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index eb5ef4d0f463..4758a438b4d5 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -293,6 +293,7 @@ struct dw_i2c_dev {
 
 #define MODEL_MSCC_OCELOT      0x00000100
 #define MODEL_BAIKAL_BT1       0x00000200
+#define MODEL_SOCFPGA          0x00000400
 #define MODEL_MASK             0x00000f00
 
 int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-master.c 
b/drivers/i2c/busses/i2c-designware-master.c
index 2871cf2ee8b4..f961a1c263fa 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -711,10 +711,26 @@ static void i2c_dw_unprepare_recovery(struct i2c_adapter 
*adap)
        i2c_dw_init_master(dev);
 }
 
-static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
+static int i2c_socfpga_scl_recovery(struct i2c_adapter *adap)
+{
+       struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+
+       bri->prepare_recovery(adap);
+       bri->unprepare_recovery(adap);
+
+       return 0;
+}
+
+static int i2c_dw_init_socfpga_recovery_info(struct dw_i2c_dev *dev,
+                                            struct i2c_bus_recovery_info 
*rinfo)
+{
+       rinfo->recover_bus = i2c_socfpga_scl_recovery;
+       return 1;
+}
+
+static int i2c_dw_init_generic_recovery_info(struct dw_i2c_dev *dev,
+                                            struct i2c_bus_recovery_info 
*rinfo)
 {
-       struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
-       struct i2c_adapter *adap = &dev->adapter;
        struct gpio_desc *gpio;
 
        gpio = devm_gpiod_get_optional(dev->dev, "scl", GPIOD_OUT_HIGH);
@@ -729,13 +745,34 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev 
*dev)
        rinfo->sda_gpiod = gpio;
 
        rinfo->recover_bus = i2c_generic_scl_recovery;
-       rinfo->prepare_recovery = i2c_dw_prepare_recovery;
-       rinfo->unprepare_recovery = i2c_dw_unprepare_recovery;
-       adap->bus_recovery_info = rinfo;
 
        dev_info(dev->dev, "running with gpio recovery mode! scl%s",
                 rinfo->sda_gpiod ? ",sda" : "");
 
+       return 1;
+}
+
+static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
+{
+       struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
+       struct i2c_adapter *adap = &dev->adapter;
+       int ret;
+
+       switch (dev->flags & MODEL_MASK) {
+       case MODEL_SOCFPGA:
+               ret = i2c_dw_init_socfpga_recovery_info(dev, rinfo);
+               break;
+       default:
+               ret = i2c_dw_init_generic_recovery_info(dev, rinfo);
+               break;
+       }
+       if (ret <= 0)
+               return ret;
+
+       rinfo->prepare_recovery = i2c_dw_prepare_recovery;
+       rinfo->unprepare_recovery = i2c_dw_unprepare_recovery;
+       adap->bus_recovery_info = rinfo;
+
        return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index 474754151725..385ac3f7d465 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -153,6 +153,7 @@ static const struct of_device_id dw_i2c_of_match[] = {
        { .compatible = "snps,designware-i2c", },
        { .compatible = "mscc,ocelot-i2c", .data = (void *)MODEL_MSCC_OCELOT },
        { .compatible = "baikal,bt1-sys-i2c", .data = (void *)MODEL_BAIKAL_BT1 
},
+       { .compatible = "intel,socfpga-i2c", .data = (void *)MODEL_SOCFPGA },
        {},
 };
 MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
-- 
2.25.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#12541): 
https://lists.yoctoproject.org/g/linux-yocto/message/12541
Mute This Topic: https://lists.yoctoproject.org/mt/98898782/21656
Group Owner: linux-yocto+ow...@lists.yoctoproject.org
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to