forked from Minki/linux
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: Lucas De Marchi <lucas.demarchi@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Tested-by: Christian Ruppert <christian.ruppert@alitech.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
8c5660bb29
commit
63d0f0a695
@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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 {
|
|||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user