#19816: 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/19816>
OpenWrt <http://openwrt.org>
Opensource Wireless Router Technology
_______________________________________________
openwrt-tickets mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-tickets

Reply via email to