aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;