Commit 63d0f0a6 authored by Lucas De Marchi's avatar Lucas De Marchi Committed by Wolfram Sang

i2c: designware: detect when dynamic tar update is possible

This adapter can be synthesized with dynamic tar update enabled or disabled.
When enabled it is not necessary to disable the adapter to change the slave
address in some situations, which saves some time per transaction.

There is no direct register to know if this feature is enabled but we can do it
indirectly by writing to the 10BIT_ADDR field in IC_CON: this field is
read only when dynamic tar update is enabled.
Signed-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
Acked-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: default avatarChristian Ruppert <christian.ruppert@alitech.com>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 8c5660bb
...@@ -460,27 +460,29 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) ...@@ -460,27 +460,29 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
{ {
struct i2c_msg *msgs = dev->msgs; struct i2c_msg *msgs = dev->msgs;
u32 ic_con, ic_tar = 0; u32 ic_tar = 0;
/* Disable the adapter */ /* Disable the adapter */
__i2c_dw_enable_and_wait(dev, false); __i2c_dw_enable_and_wait(dev, false);
/* if the slave address is ten bit address, enable 10BITADDR */ /* if the slave address is ten bit address, enable 10BITADDR */
ic_con = dw_readl(dev, DW_IC_CON); if (dev->dynamic_tar_update_enabled) {
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
ic_con |= DW_IC_CON_10BITADDR_MASTER;
/* /*
* If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
* mode has to be enabled via bit 12 of IC_TAR register. * mode has to be enabled via bit 12 of IC_TAR register,
* We set it always as I2C_DYNAMIC_TAR_UPDATE can't be * otherwise bit 4 of IC_CON is used.
* detected from registers.
*/ */
ic_tar = DW_IC_TAR_10BITADDR_MASTER; if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
ic_tar = DW_IC_TAR_10BITADDR_MASTER;
} else { } else {
ic_con &= ~DW_IC_CON_10BITADDR_MASTER; u32 ic_con = dw_readl(dev, DW_IC_CON);
}
dw_writel(dev, ic_con, DW_IC_CON); if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
ic_con |= DW_IC_CON_10BITADDR_MASTER;
else
ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
dw_writel(dev, ic_con, DW_IC_CON);
}
/* /*
* Set the slave (target) address and enable 10-bit addressing mode * Set the slave (target) address and enable 10-bit addressing mode
...@@ -901,6 +903,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) ...@@ -901,6 +903,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
{ {
struct i2c_adapter *adap = &dev->adapter; struct i2c_adapter *adap = &dev->adapter;
int r; int r;
u32 reg;
init_completion(&dev->cmd_complete); init_completion(&dev->cmd_complete);
...@@ -908,6 +911,26 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) ...@@ -908,6 +911,26 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
if (r) if (r)
return r; return r;
r = i2c_dw_acquire_lock(dev);
if (r)
return r;
/*
* Test if dynamic TAR update is enabled in this controller by writing
* to IC_10BITADDR_MASTER field in IC_CON: when it is enabled this
* field is read-only so it should not succeed
*/
reg = dw_readl(dev, DW_IC_CON);
dw_writel(dev, reg ^ DW_IC_CON_10BITADDR_MASTER, DW_IC_CON);
if ((dw_readl(dev, DW_IC_CON) & DW_IC_CON_10BITADDR_MASTER) ==
(reg & DW_IC_CON_10BITADDR_MASTER)) {
dev->dynamic_tar_update_enabled = true;
dev_dbg(dev->dev, "Dynamic TAR update enabled");
}
i2c_dw_release_lock(dev);
snprintf(adap->name, sizeof(adap->name), snprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C adapter"); "Synopsys DesignWare I2C adapter");
adap->retries = 3; adap->retries = 3;
......
...@@ -117,6 +117,7 @@ struct dw_i2c_dev { ...@@ -117,6 +117,7 @@ struct dw_i2c_dev {
int (*acquire_lock)(struct dw_i2c_dev *dev); int (*acquire_lock)(struct dw_i2c_dev *dev);
void (*release_lock)(struct dw_i2c_dev *dev); void (*release_lock)(struct dw_i2c_dev *dev);
bool pm_runtime_disabled; bool pm_runtime_disabled;
bool dynamic_tar_update_enabled;
}; };
#define ACCESS_SWAP 0x00000001 #define ACCESS_SWAP 0x00000001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment