mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-30 15:24:31 -04:00
i2c: designware: Combine the init functions
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
This commit is contained in:
committed by
Andi Shyti
parent
6062443a05
commit
38fa29b01a
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -31,16 +31,6 @@
|
||||
#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;
|
||||
|
||||
@@ -21,48 +21,6 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user