diff options
author | Richard Zhao <linuxzsc@gmail.com> | 2009-10-17 05:46:22 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2009-11-02 18:28:46 -0500 |
commit | 43309f3b521302bb66c4c9e66704dd3675e4d725 (patch) | |
tree | 4f2e927b301a9b89d6fb35e524c90b37331129b2 /drivers/i2c | |
parent | 1836d95928a0f41ada0cbb2a6c4e46b027db9491 (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/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 62 |
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 | ||
128 | static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx) | 129 | static 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 | ||
182 | static void i2c_imx_start(struct imx_i2c_struct *i2c_imx) | 188 | static 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 | ||
198 | static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) | 216 | static 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); |