| From b37119cfa1a026a1c3830ede600e44d002b7ab2e Mon Sep 17 00:00:00 2001 |
| From: "Chew, Chiau Ee" <chiau.ee.chew@intel.com> |
| Date: Fri, 27 Sep 2013 02:57:35 +0800 |
| Subject: i2c: designware: 10-bit addressing mode enabling if |
| I2C_DYNAMIC_TAR_UPDATE is set |
| |
| According to Designware I2C spec, if I2C_DYNAMIC_TAR_UPDATE is set to 1, |
| the 10-bit addressing mode is controlled by IC_10BITADDR_MASTER bit of |
| IC_TAR register instead of IC_CON register. The IC_10BITADDR_MASTER |
| in IC_CON register becomes read-only copy. Since I2C_DYNAMIC_TAR_UPDATE |
| value can't be detected from hardware register, so we will always set the |
| IC_10BITADDR_MASTER bit in both IC_CON and IC_TAR register whenever 10-bit |
| addresing mode is requested by user application. |
| |
| Signed-off-by: Chew, Chiau Ee <chiau.ee.chew@intel.com> |
| Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> |
| Signed-off-by: Wolfram Sang <wsa@the-dreams.de> |
| (cherry picked from commit bd63ace4dc4290165bbf3bf546eba50453d0aa9d) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/i2c/busses/i2c-designware-core.c | 26 ++++++++++++++++++++------ |
| 1 file changed, 20 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/i2c/busses/i2c-designware-core.c |
| +++ b/drivers/i2c/busses/i2c-designware-core.c |
| @@ -98,6 +98,8 @@ |
| |
| #define DW_IC_ERR_TX_ABRT 0x1 |
| |
| +#define DW_IC_TAR_10BITADDR_MASTER BIT(12) |
| + |
| /* |
| * status codes |
| */ |
| @@ -388,22 +390,34 @@ static int i2c_dw_wait_bus_not_busy(stru |
| static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) |
| { |
| struct i2c_msg *msgs = dev->msgs; |
| - u32 ic_con; |
| + u32 ic_con, ic_tar = 0; |
| |
| /* Disable the adapter */ |
| __i2c_dw_enable(dev, false); |
| |
| - /* set the slave (target) address */ |
| - dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR); |
| - |
| /* if the slave address is ten bit address, enable 10BITADDR */ |
| ic_con = dw_readl(dev, DW_IC_CON); |
| - if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) |
| + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { |
| ic_con |= DW_IC_CON_10BITADDR_MASTER; |
| - else |
| + /* |
| + * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing |
| + * mode has to be enabled via bit 12 of IC_TAR register. |
| + * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be |
| + * detected from registers. |
| + */ |
| + ic_tar = DW_IC_TAR_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 |
| + * if applicable. |
| + */ |
| + dw_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, DW_IC_TAR); |
| + |
| /* enforce disabled interrupts (due to HW issues) */ |
| i2c_dw_disable_int(dev); |
| |