i2c: designware: add a new bit check for IC_CON control
authorShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Tue, 24 Jan 2023 11:11:27 +0000 (16:41 +0530)
committerWolfram Sang <wsa@kernel.org>
Sat, 28 Jan 2023 19:05:32 +0000 (20:05 +0100)
On some AMD platforms, based on the new designware datasheet,
BIOS sets the BIT(11) within the IC_CON register to advertise
the "bus clear feature capability".

AMD/Designware datasheet says:

Bit(11) BUS_CLEAR_FEATURE_CTRL. Read-write,Volatile. Reset: 0.
Description: In Master mode:
- 1'b1: Bus Clear Feature is enabled.
- 1'b0: Bus Clear Feature is Disabled.
In Slave mode, this register bit is not applicable.

On AMD platform designs:
1. BIOS programs the BUS_CLEAR_FEATURE_CTRL and enables the detection
of SCL/SDA stuck low.
2. Whenever the stuck low is detected, the SMU FW shall do the bus
recovery procedure.

Currently, the way in which the "master_cfg" is built in the driver, it
overrides the BUS_CLEAR_FEATURE_CTRL advertised by BIOS and the SMU FW
cannot initiate the bus recovery if the stuck low is detected.

Hence add a check in i2c_dw_probe_master() that if the BIOS
advertises the bus clear feature, let driver not ignore it and
adapt accordingly.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-master.c

index 6bc2ede..932395d 100644 (file)
@@ -37,6 +37,7 @@
 #define DW_IC_CON_STOP_DET_IFADDRESSED         BIT(7)
 #define DW_IC_CON_TX_EMPTY_CTRL                        BIT(8)
 #define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL                BIT(9)
+#define DW_IC_CON_BUS_CLEAR_CTRL               BIT(11)
 
 #define DW_IC_DATA_CMD_DAT                     GENMASK(7, 0)
 
index 45f5691..3be7581 100644 (file)
@@ -865,6 +865,7 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
 {
        struct i2c_adapter *adap = &dev->adapter;
        unsigned long irq_flags;
+       unsigned int ic_con;
        int ret;
 
        init_completion(&dev->cmd_complete);
@@ -884,6 +885,25 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
        if (ret)
                return ret;
 
+       /* Lock the bus for accessing DW_IC_CON */
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
+
+       /*
+        * On AMD platforms BIOS advertises the bus clear feature
+        * and enables the SCL/SDA stuck low. SMU FW does the
+        * bus recovery process. Driver should not ignore this BIOS
+        * advertisement of bus clear feature.
+        */
+       ret = regmap_read(dev->map, DW_IC_CON, &ic_con);
+       i2c_dw_release_lock(dev);
+       if (ret)
+               return ret;
+
+       if (ic_con & DW_IC_CON_BUS_CLEAR_CTRL)
+               dev->master_cfg |= DW_IC_CON_BUS_CLEAR_CTRL;
+
        ret = dev->init(dev);
        if (ret)
                return ret;