aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRichard Zhao <linuxzsc@gmail.com>2009-10-17 05:46:22 -0400
committerBen Dooks <ben-linux@fluff.org>2009-11-02 18:28:46 -0500
commit43309f3b521302bb66c4c9e66704dd3675e4d725 (patch)
tree4f2e927b301a9b89d6fb35e524c90b37331129b2 /drivers
parent1836d95928a0f41ada0cbb2a6c4e46b027db9491 (diff)
i2c: imx: check busy bit when START/STOP
The controller can't do anything else before it actually generates START/STOP. So we check busy bit to make sure START/STOP is successfully finished. If we don't check busy bit, START/STOP may fail on some fast CPUs. Signed-off-by: Richard Zhao <linuxzsc@gmail.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-imx.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 4afba3ec2a61..6055e92f0ac8 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -120,19 +120,25 @@ struct imx_i2c_struct {
120 wait_queue_head_t queue; 120 wait_queue_head_t queue;
121 unsigned long i2csr; 121 unsigned long i2csr;
122 unsigned int disable_delay; 122 unsigned int disable_delay;
123 int stopped;
123}; 124};
124 125
125/** Functions for IMX I2C adapter driver *************************************** 126/** Functions for IMX I2C adapter driver ***************************************
126*******************************************************************************/ 127*******************************************************************************/
127 128
128static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx) 129static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
129{ 130{
130 unsigned long orig_jiffies = jiffies; 131 unsigned long orig_jiffies = jiffies;
132 unsigned int temp;
131 133
132 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); 134 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
133 135
134 /* wait for bus not busy */ 136 while (1) {
135 while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) { 137 temp = readb(i2c_imx->base + IMX_I2C_I2SR);
138 if (for_busy && (temp & I2SR_IBB))
139 break;
140 if (!for_busy && !(temp & I2SR_IBB))
141 break;
136 if (signal_pending(current)) { 142 if (signal_pending(current)) {
137 dev_dbg(&i2c_imx->adapter.dev, 143 dev_dbg(&i2c_imx->adapter.dev,
138 "<%s> I2C Interrupted\n", __func__); 144 "<%s> I2C Interrupted\n", __func__);
@@ -179,39 +185,55 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
179 return 0; 185 return 0;
180} 186}
181 187
182static void i2c_imx_start(struct imx_i2c_struct *i2c_imx) 188static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
183{ 189{
184 unsigned int temp = 0; 190 unsigned int temp = 0;
191 int result;
185 192
186 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); 193 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
187 194
188 /* Enable I2C controller */ 195 /* Enable I2C controller */
196 writeb(0, i2c_imx->base + IMX_I2C_I2SR);
189 writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); 197 writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
198
199 /* Wait controller to be stable */
200 udelay(50);
201
190 /* Start I2C transaction */ 202 /* Start I2C transaction */
191 temp = readb(i2c_imx->base + IMX_I2C_I2CR); 203 temp = readb(i2c_imx->base + IMX_I2C_I2CR);
192 temp |= I2CR_MSTA; 204 temp |= I2CR_MSTA;
193 writeb(temp, i2c_imx->base + IMX_I2C_I2CR); 205 writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
206 result = i2c_imx_bus_busy(i2c_imx, 1);
207 if (result)
208 return result;
209 i2c_imx->stopped = 0;
210
194 temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; 211 temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
195 writeb(temp, i2c_imx->base + IMX_I2C_I2CR); 212 writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
213 return result;
196} 214}
197 215
198static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) 216static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
199{ 217{
200 unsigned int temp = 0; 218 unsigned int temp = 0;
201 219
202 /* Stop I2C transaction */ 220 if (!i2c_imx->stopped) {
203 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); 221 /* Stop I2C transaction */
204 temp = readb(i2c_imx->base + IMX_I2C_I2CR); 222 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
205 temp &= ~I2CR_MSTA; 223 temp = readb(i2c_imx->base + IMX_I2C_I2CR);
206 writeb(temp, i2c_imx->base + IMX_I2C_I2CR); 224 temp &= ~(I2CR_MSTA | I2CR_MTX);
207 /* setup chip registers to defaults */ 225 writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
208 writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); 226 i2c_imx->stopped = 1;
209 writeb(0, i2c_imx->base + IMX_I2C_I2SR); 227 }
210 /* 228 /*
211 * This delay caused by an i.MXL hardware bug. 229 * This delay caused by an i.MXL hardware bug.
212 * If no (or too short) delay, no "STOP" bit will be generated. 230 * If no (or too short) delay, no "STOP" bit will be generated.
213 */ 231 */
214 udelay(i2c_imx->disable_delay); 232 udelay(i2c_imx->disable_delay);
233
234 if (!i2c_imx->stopped)
235 i2c_imx_bus_busy(i2c_imx, 0);
236
215 /* Disable I2C controller */ 237 /* Disable I2C controller */
216 writeb(0, i2c_imx->base + IMX_I2C_I2CR); 238 writeb(0, i2c_imx->base + IMX_I2C_I2CR);
217} 239}
@@ -341,11 +363,15 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
341 if (result) 363 if (result)
342 return result; 364 return result;
343 if (i == (msgs->len - 1)) { 365 if (i == (msgs->len - 1)) {
366 /* It must generate STOP before read I2DR to prevent
367 controller from generating another clock cycle */
344 dev_dbg(&i2c_imx->adapter.dev, 368 dev_dbg(&i2c_imx->adapter.dev,
345 "<%s> clear MSTA\n", __func__); 369 "<%s> clear MSTA\n", __func__);
346 temp = readb(i2c_imx->base + IMX_I2C_I2CR); 370 temp = readb(i2c_imx->base + IMX_I2C_I2CR);
347 temp &= ~I2CR_MSTA; 371 temp &= ~(I2CR_MSTA | I2CR_MTX);
348 writeb(temp, i2c_imx->base + IMX_I2C_I2CR); 372 writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
373 i2c_imx_bus_busy(i2c_imx, 0);
374 i2c_imx->stopped = 1;
349 } else if (i == (msgs->len - 2)) { 375 } else if (i == (msgs->len - 2)) {
350 dev_dbg(&i2c_imx->adapter.dev, 376 dev_dbg(&i2c_imx->adapter.dev,
351 "<%s> set TXAK\n", __func__); 377 "<%s> set TXAK\n", __func__);
@@ -370,14 +396,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
370 396
371 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); 397 dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
372 398
373 /* Check if i2c bus is not busy */ 399 /* Start I2C transfer */
374 result = i2c_imx_bus_busy(i2c_imx); 400 result = i2c_imx_start(i2c_imx);
375 if (result) 401 if (result)
376 goto fail0; 402 goto fail0;
377 403
378 /* Start I2C transfer */
379 i2c_imx_start(i2c_imx);
380
381 /* read/write data */ 404 /* read/write data */
382 for (i = 0; i < num; i++) { 405 for (i = 0; i < num; i++) {
383 if (i) { 406 if (i) {
@@ -386,6 +409,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
386 temp = readb(i2c_imx->base + IMX_I2C_I2CR); 409 temp = readb(i2c_imx->base + IMX_I2C_I2CR);
387 temp |= I2CR_RSTA; 410 temp |= I2CR_RSTA;
388 writeb(temp, i2c_imx->base + IMX_I2C_I2CR); 411 writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
412 result = i2c_imx_bus_busy(i2c_imx, 1);
413 if (result)
414 goto fail0;
389 } 415 }
390 dev_dbg(&i2c_imx->adapter.dev, 416 dev_dbg(&i2c_imx->adapter.dev,
391 "<%s> transfer message: %d\n", __func__, i); 417 "<%s> transfer message: %d\n", __func__, i);