diff options
author | Wolfram Sang <wsa+renesas@sang-engineering.com> | 2020-08-29 22:38:09 +0200 |
---|---|---|
committer | Wolfram Sang <wsa@kernel.org> | 2020-09-18 23:02:02 +0200 |
commit | 9374ed1dfe1f862f6dd7552b8164252fe5cc424f (patch) | |
tree | 52e7739d351c90fed59629fe29e029df696a8510 /drivers | |
parent | 6af077194600d5445f802ce4587a3254a215a851 (diff) |
i2c: rcar: improve bus busy detection
I2C doesn't define a timeout for bus busy, so an arbitrary value like
LOOP_TIMEOUT is not a good idea. Let's use the timeout value in struct
adapter which is meant for such cases and is user-configurable (via
IOCTL). To reduce the load, wait 10us instead of 1us which is good
enough for the slow frequencies used by I2C. Finally, use the
poll_timeout helper instead of open coding it.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 9e883474db8c..c5ba018d74a7 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -19,6 +19,7 @@ #include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> @@ -221,18 +222,18 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv) static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) { - int i; + int ret; + u32 val; - for (i = 0; i < LOOP_TIMEOUT; i++) { - /* make sure that bus is not busy */ - if (!(rcar_i2c_read(priv, ICMCR) & FSDA)) - return 0; - udelay(1); + ret = readl_poll_timeout(priv->io + ICMCR, val, !(val & FSDA), 10, + priv->adap.timeout); + if (ret) { + /* Waiting did not help, try to recover */ + priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL; + ret = i2c_recover_bus(&priv->adap); } - /* Waiting did not help, try to recover */ - priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL; - return i2c_recover_bus(&priv->adap); + return ret; } static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv) |