]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
i2c: designware: Combine the init functions
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>
Tue, 20 Jan 2026 13:07:26 +0000 (14:07 +0100)
committerAndi Shyti <andi.shyti@kernel.org>
Thu, 22 Jan 2026 13:43:46 +0000 (14:43 +0100)
Providing a single function for controller initialisation.
The controller initialisation has the same steps for master
and slave modes, except the timing parameters are only
needed in master mode.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260120130729.1679560-3-heikki.krogerus@linux.intel.com
drivers/i2c/busses/i2c-designware-amdisp.c
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-slave.c

index 450793d5f83921ac9a8c6d00414890779da49c07..ec9259dd2a4f9997c97b581167e8e014d7777de2 100644 (file)
@@ -163,8 +163,8 @@ static int amd_isp_dw_i2c_plat_runtime_resume(struct device *dev)
 
        if (!i_dev->shared_with_punit)
                i2c_dw_prepare_clk(i_dev, true);
-       if (i_dev->init)
-               i_dev->init(i_dev);
+
+       i2c_dw_init(i_dev);
 
        return 0;
 }
index 7066d05e5e43cfeb92a51fcfffa873dbd4080c03..17affdecbe30ae6b864a3deed827b65755b5351b 100644 (file)
@@ -359,6 +359,83 @@ static inline u32 i2c_dw_acpi_round_bus_speed(struct device *device) { return 0;
 
 #endif /* CONFIG_ACPI */
 
+static void i2c_dw_configure_mode(struct dw_i2c_dev *dev)
+{
+       switch (dev->mode) {
+       case DW_IC_MASTER:
+               regmap_write(dev->map, DW_IC_TX_TL, dev->tx_fifo_depth / 2);
+               regmap_write(dev->map, DW_IC_RX_TL, 0);
+               regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
+               break;
+       case DW_IC_SLAVE:
+               regmap_write(dev->map, DW_IC_TX_TL, 0);
+               regmap_write(dev->map, DW_IC_RX_TL, 0);
+               regmap_write(dev->map, DW_IC_CON, dev->slave_cfg);
+               regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_SLAVE_MASK);
+               break;
+       default:
+               return;
+       }
+}
+
+static void i2c_dw_write_timings(struct dw_i2c_dev *dev)
+{
+       /* Write standard speed timing parameters */
+       regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
+       regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
+
+       /* Write fast mode/fast mode plus timing parameters */
+       regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
+       regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
+
+       /* Write high speed timing parameters if supported */
+       if (dev->hs_hcnt && dev->hs_lcnt) {
+               regmap_write(dev->map, DW_IC_HS_SCL_HCNT, dev->hs_hcnt);
+               regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt);
+       }
+}
+
+/**
+ * i2c_dw_init() - Initialize the DesignWare I2C hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the DesigWare I2C hardware.
+ *
+ * Return: 0 on success, or negative errno otherwise.
+ */
+int i2c_dw_init(struct dw_i2c_dev *dev)
+{
+       int ret;
+
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
+
+       /* Disable the adapter */
+       __i2c_dw_disable(dev);
+
+       /*
+        * Mask SMBus interrupts to block storms from broken
+        * firmware that leaves IC_SMBUS=1; the handler never
+        * services them.
+        */
+       regmap_write(dev->map, DW_IC_SMBUS_INTR_MASK, 0);
+
+       if (dev->mode == DW_IC_MASTER)
+               i2c_dw_write_timings(dev);
+
+       /* Write SDA hold time if supported */
+       if (dev->sda_hold_time)
+               regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
+
+       i2c_dw_configure_mode(dev);
+
+       i2c_dw_release_lock(dev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(i2c_dw_init);
+
 static void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
 {
        u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev);
@@ -801,7 +878,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
        if (ret)
                return ret;
 
-       ret = dev->init(dev);
+       ret = i2c_dw_init(dev);
        if (ret)
                return ret;
 
@@ -894,7 +971,7 @@ static int i2c_dw_runtime_resume(struct device *device)
        if (!dev->shared_with_punit)
                i2c_dw_prepare_clk(dev, true);
 
-       dev->init(dev);
+       i2c_dw_init(dev);
 
        return 0;
 }
index 9727143f5419aea2b1061c993086457eed736a0d..63a59bb0316349180bf2091fe137bca2f68dd183 100644 (file)
@@ -253,7 +253,6 @@ struct reset_control;
  * @semaphore_idx: Index of table with semaphore type attached to the bus. It's
  *     -1 if there is no semaphore.
  * @shared_with_punit: true if this bus is shared with the SoC's PUNIT
- * @init: function to initialize the I2C hardware
  * @set_sda_hold_time: callback to retrieve IP specific SDA hold timing
  * @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE
  * @rinfo: I²C GPIO recovery information
@@ -314,7 +313,6 @@ struct dw_i2c_dev {
        void                    (*release_lock)(void);
        int                     semaphore_idx;
        bool                    shared_with_punit;
-       int                     (*init)(struct dw_i2c_dev *dev);
        int                     (*set_sda_hold_time)(struct dw_i2c_dev *dev);
        int                     mode;
        struct i2c_bus_recovery_info rinfo;
@@ -419,6 +417,7 @@ static inline void i2c_dw_configure(struct dw_i2c_dev *dev)
 }
 
 int i2c_dw_probe(struct dw_i2c_dev *dev);
+int i2c_dw_init(struct dw_i2c_dev *dev);
 
 #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL)
 int i2c_dw_baytrail_probe_lock_support(struct dw_i2c_dev *dev);
index fdd75e30017647544b767ffd09763cf534637e14..22c1bb463c2c0450b256f69f8e168cee2199363e 100644 (file)
 #define AMD_TIMEOUT_MAX_US     250
 #define AMD_MASTERCFG_MASK     GENMASK(15, 0)
 
-static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
-{
-       /* Configure Tx/Rx FIFO threshold levels */
-       regmap_write(dev->map, DW_IC_TX_TL, dev->tx_fifo_depth / 2);
-       regmap_write(dev->map, DW_IC_RX_TL, 0);
-
-       /* Configure the I2C master */
-       regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
-}
-
 static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
 {
        unsigned int comp_param1;
@@ -195,58 +185,6 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
        return 0;
 }
 
-/**
- * i2c_dw_init_master() - Initialize the DesignWare I2C master hardware
- * @dev: device private data
- *
- * This functions configures and enables the I2C master.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- *
- * Return: 0 on success, or negative errno otherwise.
- */
-static int i2c_dw_init_master(struct dw_i2c_dev *dev)
-{
-       int ret;
-
-       ret = i2c_dw_acquire_lock(dev);
-       if (ret)
-               return ret;
-
-       /* Disable the adapter */
-       __i2c_dw_disable(dev);
-
-       /*
-        * Mask SMBus interrupts to block storms from broken
-        * firmware that leaves IC_SMBUS=1; the handler never
-        * services them.
-        */
-       regmap_write(dev->map, DW_IC_SMBUS_INTR_MASK, 0);
-
-       /* Write standard speed timing parameters */
-       regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
-       regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
-
-       /* Write fast mode/fast mode plus timing parameters */
-       regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
-       regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
-
-       /* Write high speed timing parameters if supported */
-       if (dev->hs_hcnt && dev->hs_lcnt) {
-               regmap_write(dev->map, DW_IC_HS_SCL_HCNT, dev->hs_hcnt);
-               regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt);
-       }
-
-       /* Write SDA hold time if supported */
-       if (dev->sda_hold_time)
-               regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
-
-       i2c_dw_configure_fifo_master(dev);
-       i2c_dw_release_lock(dev);
-
-       return 0;
-}
-
 static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
 {
        struct i2c_msg *msgs = dev->msgs;
@@ -843,9 +781,9 @@ i2c_dw_xfer_common(struct dw_i2c_dev *dev, struct i2c_msg msgs[], int num)
        ret = i2c_dw_wait_transfer(dev);
        if (ret) {
                dev_err(dev->dev, "controller timed out\n");
-               /* i2c_dw_init_master() implicitly disables the adapter */
+               /* i2c_dw_init() implicitly disables the adapter */
                i2c_recover_bus(&dev->adapter);
-               i2c_dw_init_master(dev);
+               i2c_dw_init(dev);
                goto done;
        }
 
@@ -950,7 +888,7 @@ static void i2c_dw_unprepare_recovery(struct i2c_adapter *adap)
 
        i2c_dw_prepare_clk(dev, true);
        reset_control_deassert(dev->rst);
-       i2c_dw_init_master(dev);
+       i2c_dw_init(dev);
 }
 
 static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
@@ -999,8 +937,6 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
 
        init_completion(&dev->cmd_complete);
 
-       dev->init = i2c_dw_init_master;
-
        ret = i2c_dw_set_timings_master(dev);
        if (ret)
                return ret;
index c0baf53e97d893151848f3701c479137867c5d05..9fc8faa33735c39d14980c54c9686e861cef4ba7 100644 (file)
 
 #include "i2c-designware-core.h"
 
-static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
-{
-       /* Configure Tx/Rx FIFO threshold levels. */
-       regmap_write(dev->map, DW_IC_TX_TL, 0);
-       regmap_write(dev->map, DW_IC_RX_TL, 0);
-
-       /* Configure the I2C slave. */
-       regmap_write(dev->map, DW_IC_CON, dev->slave_cfg);
-       regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_SLAVE_MASK);
-}
-
-/**
- * i2c_dw_init_slave() - Initialize the DesignWare i2c slave hardware
- * @dev: device private data
- *
- * This function configures and enables the I2C in slave mode.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- *
- * Return: 0 on success, or negative errno otherwise.
- */
-static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
-{
-       int ret;
-
-       ret = i2c_dw_acquire_lock(dev);
-       if (ret)
-               return ret;
-
-       /* Disable the adapter. */
-       __i2c_dw_disable(dev);
-
-       /* Write SDA hold time if supported */
-       if (dev->sda_hold_time)
-               regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
-
-       i2c_dw_configure_fifo_slave(dev);
-       i2c_dw_release_lock(dev);
-
-       return 0;
-}
-
 int i2c_dw_reg_slave(struct i2c_client *slave)
 {
        struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter);
@@ -232,8 +190,6 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
        if (dev->flags & ACCESS_POLLING)
                return -EOPNOTSUPP;
 
-       dev->init = i2c_dw_init_slave;
-
        return 0;
 }