aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-davinci.c
diff options
context:
space:
mode:
authorPhilby John <pjohn@in.mvista.com>2010-01-11 12:09:44 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2010-08-05 12:38:32 -0400
commit8574faf9a5ae71fdd84c6413779a9b076138eb9e (patch)
tree4369234894343b6ab53853930ca3b0a592cc3621 /drivers/i2c/busses/i2c-davinci.c
parent82c0de11b734c5acec13c0f6007466da81cd16d9 (diff)
i2c: davinci: bus recovery procedure to clear the bus
Come out of i2c time out condition by following the bus recovery procedure outlined in the i2c protocol v3 spec. The kernel must be robust enough to gracefully recover from i2c bus failure without having to reset the machine. This is done by first NACKing the slave, pulsing the SCL line 9 times and then sending the stop command. This patch has been tested on a DM6446 and DM355 Signed-off-by: Philby John <pjohn@in.mvista.com> Signed-off-by: Srinivasan, Nageswari <nageswari@ti.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'drivers/i2c/busses/i2c-davinci.c')
-rw-r--r--drivers/i2c/busses/i2c-davinci.c57
1 files changed, 53 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 352b4e7bdd9e..2222c87876b9 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -37,6 +37,7 @@
37#include <linux/io.h> 37#include <linux/io.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/cpufreq.h> 39#include <linux/cpufreq.h>
40#include <linux/gpio.h>
40 41
41#include <mach/hardware.h> 42#include <mach/hardware.h>
42#include <mach/i2c.h> 43#include <mach/i2c.h>
@@ -44,6 +45,7 @@
44/* ----- global defines ----------------------------------------------- */ 45/* ----- global defines ----------------------------------------------- */
45 46
46#define DAVINCI_I2C_TIMEOUT (1*HZ) 47#define DAVINCI_I2C_TIMEOUT (1*HZ)
48#define DAVINCI_I2C_MAX_TRIES 2
47#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ 49#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \
48 DAVINCI_I2C_IMR_SCD | \ 50 DAVINCI_I2C_IMR_SCD | \
49 DAVINCI_I2C_IMR_ARDY | \ 51 DAVINCI_I2C_IMR_ARDY | \
@@ -131,6 +133,44 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
131 return __raw_readw(i2c_dev->base + reg); 133 return __raw_readw(i2c_dev->base + reg);
132} 134}
133 135
136/* Generate a pulse on the i2c clock pin. */
137static void generic_i2c_clock_pulse(unsigned int scl_pin)
138{
139 u16 i;
140
141 if (scl_pin) {
142 /* Send high and low on the SCL line */
143 for (i = 0; i < 9; i++) {
144 gpio_set_value(scl_pin, 0);
145 udelay(20);
146 gpio_set_value(scl_pin, 1);
147 udelay(20);
148 }
149 }
150}
151
152/* This routine does i2c bus recovery as specified in the
153 * i2c protocol Rev. 03 section 3.16 titled "Bus clear"
154 */
155static void i2c_recover_bus(struct davinci_i2c_dev *dev)
156{
157 u32 flag = 0;
158 struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
159
160 dev_err(dev->dev, "initiating i2c bus recovery\n");
161 /* Send NACK to the slave */
162 flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
163 flag |= DAVINCI_I2C_MDR_NACK;
164 /* write the data into mode register */
165 davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
166 if (pdata)
167 generic_i2c_clock_pulse(pdata->scl_pin);
168 /* Send STOP */
169 flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
170 flag |= DAVINCI_I2C_MDR_STP;
171 davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
172}
173
134static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, 174static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
135 int val) 175 int val)
136{ 176{
@@ -236,14 +276,22 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
236 char allow_sleep) 276 char allow_sleep)
237{ 277{
238 unsigned long timeout; 278 unsigned long timeout;
279 static u16 to_cnt;
239 280
240 timeout = jiffies + dev->adapter.timeout; 281 timeout = jiffies + dev->adapter.timeout;
241 while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) 282 while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG)
242 & DAVINCI_I2C_STR_BB) { 283 & DAVINCI_I2C_STR_BB) {
243 if (time_after(jiffies, timeout)) { 284 if (to_cnt <= DAVINCI_I2C_MAX_TRIES) {
244 dev_warn(dev->dev, 285 if (time_after(jiffies, timeout)) {
245 "timeout waiting for bus ready\n"); 286 dev_warn(dev->dev,
246 return -ETIMEDOUT; 287 "timeout waiting for bus ready\n");
288 to_cnt++;
289 return -ETIMEDOUT;
290 } else {
291 to_cnt = 0;
292 i2c_recover_bus(dev);
293 i2c_davinci_init(dev);
294 }
247 } 295 }
248 if (allow_sleep) 296 if (allow_sleep)
249 schedule_timeout(1); 297 schedule_timeout(1);
@@ -327,6 +375,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
327 dev->adapter.timeout); 375 dev->adapter.timeout);
328 if (r == 0) { 376 if (r == 0) {
329 dev_err(dev->dev, "controller timed out\n"); 377 dev_err(dev->dev, "controller timed out\n");
378 i2c_recover_bus(dev);
330 i2c_davinci_init(dev); 379 i2c_davinci_init(dev);
331 dev->buf_len = 0; 380 dev->buf_len = 0;
332 return -ETIMEDOUT; 381 return -ETIMEDOUT;