aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2013-04-14 20:16:54 -0400
committerWolfram Sang <wsa@the-dreams.de>2013-04-15 12:26:46 -0400
commit535ebd217d38dde481a927f21e6824d8b37bdb28 (patch)
tree776409d99148c5f3754e05f69c725dbac0112513
parent43452335224bc0cbd605c6aee82b5c9c33e94cc6 (diff)
i2c: mxs: remove races in PIO code
This commit fixes the three following races in PIO code: - The CTRL0 register is racy in itself, when programming transfer state and run bit in the same cycle the hardware sometimes ends up using the state from the last transfer. Fix this by programming state in one cycle, make sure the write is flushed down APBX bus by reading back the reg and only then trigger the run bit. - Only clear the DMAREQ bit in DEBUG0 after the read/write to the data reg happened. Otherwise we are racing with the hardware about who touches the data reg first. - When checking for completion of a transfer it's not sufficient to check if the data engine finished, but also a check for i2c bus idle is needed. In PIO mode we are really fast to program the next transfer after a finished one, so the controller possibly tries to start a new transfer while the clkgen engine is still busy writing the NAK/STOP from the last transfer to the bus. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-mxs.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 804eb6b0a0b8..0ec1f1502def 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -65,6 +65,10 @@
65#define MXS_I2C_CTRL1_SLAVE_STOP_IRQ 0x02 65#define MXS_I2C_CTRL1_SLAVE_STOP_IRQ 0x02
66#define MXS_I2C_CTRL1_SLAVE_IRQ 0x01 66#define MXS_I2C_CTRL1_SLAVE_IRQ 0x01
67 67
68#define MXS_I2C_STAT (0x50)
69#define MXS_I2C_STAT_BUS_BUSY 0x00000800
70#define MXS_I2C_STAT_CLK_GEN_BUSY 0x00000400
71
68#define MXS_I2C_DATA (0xa0) 72#define MXS_I2C_DATA (0xa0)
69 73
70#define MXS_I2C_DEBUG0 (0xb0) 74#define MXS_I2C_DEBUG0 (0xb0)
@@ -297,12 +301,10 @@ static int mxs_i2c_pio_wait_dmareq(struct mxs_i2c_dev *i2c)
297 cond_resched(); 301 cond_resched();
298 } 302 }
299 303
300 writel(MXS_I2C_DEBUG0_DMAREQ, i2c->regs + MXS_I2C_DEBUG0_CLR);
301
302 return 0; 304 return 0;
303} 305}
304 306
305static int mxs_i2c_pio_wait_cplt(struct mxs_i2c_dev *i2c) 307static int mxs_i2c_pio_wait_cplt(struct mxs_i2c_dev *i2c, int last)
306{ 308{
307 unsigned long timeout = jiffies + msecs_to_jiffies(1000); 309 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
308 310
@@ -323,9 +325,33 @@ static int mxs_i2c_pio_wait_cplt(struct mxs_i2c_dev *i2c)
323 writel(MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ, 325 writel(MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ,
324 i2c->regs + MXS_I2C_CTRL1_CLR); 326 i2c->regs + MXS_I2C_CTRL1_CLR);
325 327
328 /*
329 * When ending a transfer with a stop, we have to wait for the bus to
330 * go idle before we report the transfer as completed. Otherwise the
331 * start of the next transfer may race with the end of the current one.
332 */
333 while (last && (readl(i2c->regs + MXS_I2C_STAT) &
334 (MXS_I2C_STAT_BUS_BUSY | MXS_I2C_STAT_CLK_GEN_BUSY))) {
335 if (time_after(jiffies, timeout))
336 return -ETIMEDOUT;
337 cond_resched();
338 }
339
326 return 0; 340 return 0;
327} 341}
328 342
343static void mxs_i2c_pio_trigger_cmd(struct mxs_i2c_dev *i2c, u32 cmd)
344{
345 u32 reg;
346
347 writel(cmd, i2c->regs + MXS_I2C_CTRL0);
348
349 /* readback makes sure the write is latched into hardware */
350 reg = readl(i2c->regs + MXS_I2C_CTRL0);
351 reg |= MXS_I2C_CTRL0_RUN;
352 writel(reg, i2c->regs + MXS_I2C_CTRL0);
353}
354
329static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap, 355static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
330 struct i2c_msg *msg, uint32_t flags) 356 struct i2c_msg *msg, uint32_t flags)
331{ 357{
@@ -341,23 +367,23 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
341 addr_data |= I2C_SMBUS_READ; 367 addr_data |= I2C_SMBUS_READ;
342 368
343 /* SELECT command. */ 369 /* SELECT command. */
344 writel(MXS_I2C_CTRL0_RUN | MXS_CMD_I2C_SELECT, 370 mxs_i2c_pio_trigger_cmd(i2c, MXS_CMD_I2C_SELECT);
345 i2c->regs + MXS_I2C_CTRL0);
346 371
347 ret = mxs_i2c_pio_wait_dmareq(i2c); 372 ret = mxs_i2c_pio_wait_dmareq(i2c);
348 if (ret) 373 if (ret)
349 return ret; 374 return ret;
350 375
351 writel(addr_data, i2c->regs + MXS_I2C_DATA); 376 writel(addr_data, i2c->regs + MXS_I2C_DATA);
377 writel(MXS_I2C_DEBUG0_DMAREQ, i2c->regs + MXS_I2C_DEBUG0_CLR);
352 378
353 ret = mxs_i2c_pio_wait_cplt(i2c); 379 ret = mxs_i2c_pio_wait_cplt(i2c, 0);
354 if (ret) 380 if (ret)
355 return ret; 381 return ret;
356 382
357 /* READ command. */ 383 /* READ command. */
358 writel(MXS_I2C_CTRL0_RUN | MXS_CMD_I2C_READ | flags | 384 mxs_i2c_pio_trigger_cmd(i2c,
359 MXS_I2C_CTRL0_XFER_COUNT(msg->len), 385 MXS_CMD_I2C_READ | flags |
360 i2c->regs + MXS_I2C_CTRL0); 386 MXS_I2C_CTRL0_XFER_COUNT(msg->len));
361 387
362 for (i = 0; i < msg->len; i++) { 388 for (i = 0; i < msg->len; i++) {
363 if ((i & 3) == 0) { 389 if ((i & 3) == 0) {
@@ -365,6 +391,8 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
365 if (ret) 391 if (ret)
366 return ret; 392 return ret;
367 data = readl(i2c->regs + MXS_I2C_DATA); 393 data = readl(i2c->regs + MXS_I2C_DATA);
394 writel(MXS_I2C_DEBUG0_DMAREQ,
395 i2c->regs + MXS_I2C_DEBUG0_CLR);
368 } 396 }
369 msg->buf[i] = data & 0xff; 397 msg->buf[i] = data & 0xff;
370 data >>= 8; 398 data >>= 8;
@@ -373,9 +401,9 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
373 addr_data |= I2C_SMBUS_WRITE; 401 addr_data |= I2C_SMBUS_WRITE;
374 402
375 /* WRITE command. */ 403 /* WRITE command. */
376 writel(MXS_I2C_CTRL0_RUN | MXS_CMD_I2C_WRITE | flags | 404 mxs_i2c_pio_trigger_cmd(i2c,
377 MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1), 405 MXS_CMD_I2C_WRITE | flags |
378 i2c->regs + MXS_I2C_CTRL0); 406 MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1));
379 407
380 /* 408 /*
381 * The LSB of data buffer is the first byte blasted across 409 * The LSB of data buffer is the first byte blasted across
@@ -391,6 +419,8 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
391 if (ret) 419 if (ret)
392 return ret; 420 return ret;
393 writel(data, i2c->regs + MXS_I2C_DATA); 421 writel(data, i2c->regs + MXS_I2C_DATA);
422 writel(MXS_I2C_DEBUG0_DMAREQ,
423 i2c->regs + MXS_I2C_DEBUG0_CLR);
394 } 424 }
395 } 425 }
396 426
@@ -401,10 +431,12 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
401 if (ret) 431 if (ret)
402 return ret; 432 return ret;
403 writel(data, i2c->regs + MXS_I2C_DATA); 433 writel(data, i2c->regs + MXS_I2C_DATA);
434 writel(MXS_I2C_DEBUG0_DMAREQ,
435 i2c->regs + MXS_I2C_DEBUG0_CLR);
404 } 436 }
405 } 437 }
406 438
407 ret = mxs_i2c_pio_wait_cplt(i2c); 439 ret = mxs_i2c_pio_wait_cplt(i2c, flags & MXS_I2C_CTRL0_POST_SEND_STOP);
408 if (ret) 440 if (ret)
409 return ret; 441 return ret;
410 442