i2c: designware: Detect the FIFO size in the common code
authorSerge Semin <Sergey.Semin@baikalelectronics.ru>
Fri, 6 Mar 2020 13:19:54 +0000 (16:19 +0300)
committerWolfram Sang <wsa@the-dreams.de>
Sat, 21 Mar 2020 18:32:15 +0000 (19:32 +0100)
The problem with detecting the FIFO depth in the platform driver
is that in order to implement this we have to access the controller
IC_COMP_PARAM_1 register. Currently it's done before the
i2c_dw_set_reg_access() method execution, which is errors prone since
the method determines the registers endianness and access mode and we
can't use dw_readl/dw_writel accessors before this information is
retrieved. We also can't move the i2c_dw_set_reg_access() function
invocation to after the master/slave probe functions call (when endianness
and access mode are determined), since the FIFO depth information is used
by them for initializations. So in order to fix the problem we have no
choice but to move the FIFO size detection methods to the common code and
call it at the probe stage.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-designware-slave.c

index 2de7452fcd6d70117931b0fe36f807a76742d77b..4291ff6246d848a27e65b24eebf3aa3b23795f00 100644 (file)
@@ -344,6 +344,28 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
                return -EIO;
 }
 
+void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
+{
+       u32 param, tx_fifo_depth, rx_fifo_depth;
+
+       /*
+        * Try to detect the FIFO depth if not set by interface driver,
+        * the depth could be from 2 to 256 from HW spec.
+        */
+       param = dw_readl(dev, DW_IC_COMP_PARAM_1);
+       tx_fifo_depth = ((param >> 16) & 0xff) + 1;
+       rx_fifo_depth = ((param >> 8)  & 0xff) + 1;
+       if (!dev->tx_fifo_depth) {
+               dev->tx_fifo_depth = tx_fifo_depth;
+               dev->rx_fifo_depth = rx_fifo_depth;
+       } else if (tx_fifo_depth >= 2) {
+               dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
+                               tx_fifo_depth);
+               dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
+                               rx_fifo_depth);
+       }
+}
+
 u32 i2c_dw_func(struct i2c_adapter *adap)
 {
        struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
index 67edbbde1070a1efd5794da9cbce77b827a2a0f3..3fbc9f22fcf1cc9cc2fb2b86bb1c7379bd6ab84d 100644 (file)
@@ -297,6 +297,7 @@ int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
 void i2c_dw_release_lock(struct dw_i2c_dev *dev);
 int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
 int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
+void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
 u32 i2c_dw_func(struct i2c_adapter *adap);
 void i2c_dw_disable(struct dw_i2c_dev *dev);
 void i2c_dw_disable_int(struct dw_i2c_dev *dev);
index e8b328242256ede4704f2da21b8c7abb233bab42..05da900cf3759cbe2b3d714cded0f0ad1d186e60 100644 (file)
@@ -698,6 +698,8 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
        if (ret)
                return ret;
 
+       i2c_dw_set_fifo_size(dev);
+
        ret = dev->init(dev);
        if (ret)
                return ret;
index 3b7d58c2fe8598fd658ccc7aac5c9d5a944900ea..cb494273bb605d7c2148e4021495e003154621c1 100644 (file)
@@ -219,28 +219,6 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
        dev->mode = DW_IC_SLAVE;
 }
 
-static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev)
-{
-       u32 param, tx_fifo_depth, rx_fifo_depth;
-
-       /*
-        * Try to detect the FIFO depth if not set by interface driver,
-        * the depth could be from 2 to 256 from HW spec.
-        */
-       param = i2c_dw_read_comp_param(dev);
-       tx_fifo_depth = ((param >> 16) & 0xff) + 1;
-       rx_fifo_depth = ((param >> 8)  & 0xff) + 1;
-       if (!dev->tx_fifo_depth) {
-               dev->tx_fifo_depth = tx_fifo_depth;
-               dev->rx_fifo_depth = rx_fifo_depth;
-       } else if (tx_fifo_depth >= 2) {
-               dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
-                               tx_fifo_depth);
-               dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
-                               rx_fifo_depth);
-       }
-}
-
 static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
 {
        pm_runtime_disable(dev->dev);
@@ -362,8 +340,6 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
                                div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
        }
 
-       dw_i2c_set_fifo_size(dev);
-
        adap = &dev->adapter;
        adap->owner = THIS_MODULE;
        adap->class = I2C_CLASS_DEPRECATED;
index f5f001738df5e2b1b8c6e9db4973a9ce8f065140..0fc3aa31d46aa51cbfa64aa988e38890c4eadbf5 100644 (file)
@@ -260,6 +260,8 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
        if (ret)
                return ret;
 
+       i2c_dw_set_fifo_size(dev);
+
        ret = dev->init(dev);
        if (ret)
                return ret;