0020-Perform-I2C-combined-transactions-when-possible.patch 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. From 0262abfaac71799e3688285f1f30bead42b8ff7e Mon Sep 17 00:00:00 2001
  2. From: cbeytas <cbeytas@shaw.ca>
  3. Date: Mon, 24 Jun 2013 00:05:40 -0400
  4. Subject: [PATCH 020/114] Perform I2C combined transactions when possible
  5. Perform I2C combined transactions whenever possible, within the
  6. restrictions of the Broadcomm Serial Controller.
  7. Disable DONE interrupt during TA poll
  8. Prevent interrupt from being triggered if poll is missed and transfer
  9. starts and finishes.
  10. i2c: Make combined transactions optional and disabled by default
  11. ---
  12. drivers/i2c/busses/i2c-bcm2708.c | 31 ++++++++++++++++++++++++++++++-
  13. 1 file changed, 30 insertions(+), 1 deletion(-)
  14. --- a/drivers/i2c/busses/i2c-bcm2708.c
  15. +++ b/drivers/i2c/busses/i2c-bcm2708.c
  16. @@ -74,6 +74,9 @@ static unsigned int baudrate = CONFIG_I2
  17. module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
  18. MODULE_PARM_DESC(baudrate, "The I2C baudrate");
  19. +static bool combined = false;
  20. +module_param(combined, bool, 0644);
  21. +MODULE_PARM_DESC(combined, "Use combined transactions");
  22. struct bcm2708_i2c {
  23. struct i2c_adapter adapter;
  24. @@ -150,7 +153,7 @@ static inline void bcm2708_bsc_fifo_fill
  25. static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
  26. {
  27. unsigned long bus_hz;
  28. - u32 cdiv;
  29. + u32 cdiv, s;
  30. u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
  31. bus_hz = clk_get_rate(bi->clk);
  32. @@ -166,6 +169,32 @@ static inline void bcm2708_bsc_setup(str
  33. bcm2708_wr(bi, BSC_DIV, cdiv);
  34. bcm2708_wr(bi, BSC_A, bi->msg->addr);
  35. bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
  36. + if (combined)
  37. + {
  38. + /* Do the next two messages meet combined transaction criteria?
  39. + - Current message is a write, next message is a read
  40. + - Both messages to same slave address
  41. + - Write message can fit inside FIFO (16 bytes or less) */
  42. + if ( (bi->nmsgs > 1) &&
  43. + !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) &&
  44. + (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) {
  45. + /* Fill FIFO with entire write message (16 byte FIFO) */
  46. + while (bi->pos < bi->msg->len)
  47. + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
  48. + /* Start write transfer (no interrupts, don't clear FIFO) */
  49. + bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST);
  50. + /* poll for transfer start bit (should only take 1-20 polls) */
  51. + do {
  52. + s = bcm2708_rd(bi, BSC_S);
  53. + } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)));
  54. + /* Send next read message before the write transfer finishes. */
  55. + bi->nmsgs--;
  56. + bi->msg++;
  57. + bi->pos = 0;
  58. + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
  59. + c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ;
  60. + }
  61. + }
  62. bcm2708_wr(bi, BSC_C, c);
  63. }