#19817: I2C Ralink driver : timeout handling improvement
------------------------------+------------------------
Reporter: olivier.butler@… | Owner: developers
Type: enhancement | Status: new
Priority: normal | Milestone:
Component: kernel | Version: Trunk
Keywords: |
------------------------------+------------------------
Hi,
in the current I2C driver of Ralink's CPUs, the timeout on rx or tx phases
is handled by a basic counter ( 1000 counts , which is a very short
duration ).
This is not working with I2C slave device dealing with clock streching.
The following patch replace the basic counter with a 1000ms timeout using
jiffies :
{{{
--- drivers/i2c/busses/i2c-ralink.c 2015-05-28 10:30:55.060000000
+0200
+++ drivers/i2c/busses/i2c-ralink.c 2015-06-09 03:32:08.008000000
+0200
@@ -51,7 +51,6 @@
#define I2C_DEVADLEN_7 (6 << 2)
#define I2C_ADDRDIS BIT(1)
-#define I2C_RETRY 0x1000
#define CLKDIV_VALUE 200 // clock rate is 40M, 40M / (200*2) =
100k (standard i2c bus rate).
//#define CLKDIV_VALUE 50 // clock rate is 40M, 40M / (50*2) =
400k (fast i2c bus rate).
@@ -60,6 +59,10 @@
#define WRITE_CMD 0x00
#define READ_BLOCK 64
+
+/* timeout waiting for I2C devices to respond (clock streching) */
+#define RT_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
static void __iomem *membase;
static struct i2c_adapter *adapter;
@@ -80,38 +83,44 @@ static inline int rt_i2c_get_ack(void)
static inline int rt_i2c_wait_rx_done(void)
{
- int retries = I2C_RETRY;
+ unsigned long timeout;
+
+ timeout = jiffies + RT_I2C_TIMEOUT;
do {
- if (!retries--)
- break;
+ if (time_after(jiffies, timeout))
+ return (-ETIMEDOUT);
} while(!(rt_i2c_r32(REG_STATUS_REG) & I2C_DATARDY));
- return (retries < 0) ? -ETIMEDOUT : 0;
+ return (0);
}
static inline int rt_i2c_wait_idle(void)
{
- int retries = I2C_RETRY;
+ unsigned long timeout;
+
+ timeout = jiffies + RT_I2C_TIMEOUT;
do {
- if (!retries--)
- break;
+ if (time_after(jiffies, timeout))
+ return (1);
} while(rt_i2c_r32(REG_STATUS_REG) & I2C_BUSY);
- return (retries < 0);
+ return (0);
}
static inline int rt_i2c_wait_tx_done(void)
{
- int retries = I2C_RETRY;
+ unsigned long timeout;
+
+ timeout = jiffies + RT_I2C_TIMEOUT;
do {
- if (!retries--)
- break;
+ if (time_after(jiffies, timeout))
+ return (-ETIMEDOUT);
} while(!(rt_i2c_r32(REG_STATUS_REG) & I2C_SDOEMPTY));
- return (retries < 0) ? -ETIMEDOUT : 0;
+ return (0);
}
static int rt_i2c_handle_msg(struct i2c_adapter *a, struct i2c_msg* msg)
}}}
--
Ticket URL: <https://dev.openwrt.org/ticket/19817>
OpenWrt <http://openwrt.org>
Opensource Wireless Router Technology
_______________________________________________
openwrt-tickets mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-tickets