diff options
author | Alexander Monakov <amonakov@ispras.ru> | 2018-04-28 16:56:07 +0300 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2018-05-15 10:42:19 +0200 |
commit | 9f4659ba384780f8bc5b18717865026d83d455ce (patch) | |
tree | 36c570dbf4a689c24272cc5e564b3ab7cbbfd67c /drivers/i2c/busses/i2c-designware-common.c | |
parent | e6218bf390a9992de86a535bcb227f75e2c20cf9 (diff) | |
download | linux-9f4659ba384780f8bc5b18717865026d83d455ce.tar.gz linux-9f4659ba384780f8bc5b18717865026d83d455ce.tar.bz2 linux-9f4659ba384780f8bc5b18717865026d83d455ce.zip |
i2c: designware: refactor low-level enable/disable
Low-level controller enable function __i2c_dw_enable is overloaded to
also handle disabling. What's worse, even though the documentation
requires polling the IC_ENABLE_STATUS register when disabling, this
is not done: polling needs to be requested specifically by calling
__i2c_dw_enable_and_wait, which can also poll on enabling, but that
doesn't work if the IC_ENABLE_STATUS register is not implemented.
This is quite confusing if not in fact backwards.
Especially since the documentation says that disabling should be
followed by polling, the driver should be using a separate function
where it does one-shot disables to make the optimization stand out.
This refactors the two functions so that requested status is given
in the name rather than in a boolean argument. Specifically:
- __i2c_dw_enable: enable without polling (in accordance with docs)
- __i2c_dw_disable: disable and do poll (also as suggested by docs)
- __i2c_dw_disable_nowait: disable without polling (Linux-specific)
No functional change.
Signed-off-by: Alexander Monakov <amonakov@ispras.ru>
Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
[wsa: fixed blank lines in header file]
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-common.c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-common.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index 27ebd90de43b..48914dfc8ce8 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -149,18 +149,17 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; } -void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) -{ - dw_writel(dev, enable, DW_IC_ENABLE); -} - -void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable) +void __i2c_dw_disable(struct dw_i2c_dev *dev) { int timeout = 100; do { - __i2c_dw_enable(dev, enable); - if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable) + __i2c_dw_disable_nowait(dev); + /* + * The enable status register may be unimplemented, but + * in that case this test reads zero and exits the loop. + */ + if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == 0) return; /* @@ -171,8 +170,7 @@ void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable) usleep_range(25, 250); } while (timeout--); - dev_warn(dev->dev, "timeout in %sabling adapter\n", - enable ? "en" : "dis"); + dev_warn(dev->dev, "timeout in disabling adapter\n"); } unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev) @@ -277,7 +275,7 @@ u32 i2c_dw_func(struct i2c_adapter *adap) void i2c_dw_disable(struct dw_i2c_dev *dev) { /* Disable controller */ - __i2c_dw_enable_and_wait(dev, false); + __i2c_dw_disable(dev); /* Disable all interupts */ dw_writel(dev, 0, DW_IC_INTR_MASK); |