From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lucas De Marchi Subject: [PATCH v3 2/3] i2c: designware: detect when dynamic tar update is possible Date: Thu, 28 Jul 2016 19:03:43 -0300 Message-ID: <1469743424-2480-3-git-send-email-lucas.demarchi@intel.com> References: <1469743424-2480-1-git-send-email-lucas.demarchi@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Return-path: In-Reply-To: <1469743424-2480-1-git-send-email-lucas.demarchi@intel.com> Sender: linux-kernel-owner@vger.kernel.org To: linux-i2c@vger.kernel.org Cc: christian.ruppert@alitech.com, linux-kernel@vger.kernel.org, mika.westerberg@linux.intel.com, jarkko.nikula@linux.intel.com, Lucas De Marchi , =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= List-Id: linux-i2c@vger.kernel.org This adapter can be synthesized with dynamic tar update enabled or disa= bled. When enabled it is not necessary to disable the adapter to change the s= lave address in some situations, which saves some time per transaction. There is no direct register to know if this feature is enabled but we c= an 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 Signed-off-by: Jos=C3=A9 Roberto de Souza --- drivers/i2c/busses/i2c-designware-core.c | 37 ++++++++++++++++++++++--= -------- drivers/i2c/busses/i2c-designware-core.h | 1 + 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/bus= ses/i2c-designware-core.c index 2c61585..a8408db 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -388,6 +388,20 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* configure the i2c master */ dw_writel(dev, dev->master_cfg , DW_IC_CON); =20 + /* + * Test if dynamic TAR update is enabled in this controller by writin= g to + * IC_10BITADDR_MASTER field in IC_CON: when it is enabled this field + * is read-only so it should not succeed + */ + reg =3D 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) =3D=3D + (reg & DW_IC_CON_10BITADDR_MASTER)) { + dev->dynamic_tar_update_enabled =3D true; + dev_dbg(dev->dev, "Dynamic TAR update enabled"); + } + if (dev->release_lock) dev->release_lock(dev); return 0; @@ -416,28 +430,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) { struct i2c_msg *msgs =3D dev->msgs; - u32 ic_con, ic_tar =3D 0; + u32 ic_tar =3D 0; =20 /* Disable the adapter */ __i2c_dw_enable_and_wait(dev, false); =20 /* if the slave address is ten bit address, enable 10BITADDR */ - ic_con =3D dw_readl(dev, DW_IC_CON); - if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { - ic_con |=3D DW_IC_CON_10BITADDR_MASTER; + if (dev->dynamic_tar_update_enabled) { /* * 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. + * mode has to be enabled via bit 12 of IC_TAR register, + * otherwise bit 4 of IC_CON is used. */ - ic_tar =3D DW_IC_TAR_10BITADDR_MASTER; + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) + ic_tar =3D DW_IC_TAR_10BITADDR_MASTER; } else { - ic_con &=3D ~DW_IC_CON_10BITADDR_MASTER; + u32 ic_con =3D dw_readl(dev, DW_IC_CON); + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) + ic_con |=3D DW_IC_CON_10BITADDR_MASTER; + else + ic_con &=3D ~DW_IC_CON_10BITADDR_MASTER; + dw_writel(dev, ic_con, DW_IC_CON); } =20 - dw_writel(dev, ic_con, DW_IC_CON); - /* * Set the slave (target) address and enable 10-bit addressing mode * if applicable. diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/bus= ses/i2c-designware-core.h index cd409e7..cd6e9ec 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -105,6 +105,7 @@ struct dw_i2c_dev { int (*acquire_lock)(struct dw_i2c_dev *dev); void (*release_lock)(struct dw_i2c_dev *dev); bool pm_runtime_disabled; + bool dynamic_tar_update_enabled; }; =20 #define ACCESS_SWAP 0x00000001 --=20 2.7.4