mv64x60_i2c.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Bootloader version of the i2c driver for the MV64x60.
  3. *
  4. * Author: Dale Farnsworth <dfarnsworth@mvista.com>
  5. * Maintained by: Mark A. Greer <mgreer@mvista.com>
  6. *
  7. * 2003, 2007 (c) MontaVista, Software, Inc. This file is licensed under
  8. * the terms of the GNU General Public License version 2. This program is
  9. * licensed "as is" without any warranty of any kind, whether express or
  10. * implied.
  11. */
  12. #include <stdarg.h>
  13. #include <stddef.h>
  14. #include "types.h"
  15. #include "elf.h"
  16. #include "page.h"
  17. #include "string.h"
  18. #include "stdio.h"
  19. #include "io.h"
  20. #include "ops.h"
  21. #include "mv64x60.h"
  22. /* Register defines */
  23. #define MV64x60_I2C_REG_SLAVE_ADDR 0x00
  24. #define MV64x60_I2C_REG_DATA 0x04
  25. #define MV64x60_I2C_REG_CONTROL 0x08
  26. #define MV64x60_I2C_REG_STATUS 0x0c
  27. #define MV64x60_I2C_REG_BAUD 0x0c
  28. #define MV64x60_I2C_REG_EXT_SLAVE_ADDR 0x10
  29. #define MV64x60_I2C_REG_SOFT_RESET 0x1c
  30. #define MV64x60_I2C_CONTROL_ACK 0x04
  31. #define MV64x60_I2C_CONTROL_IFLG 0x08
  32. #define MV64x60_I2C_CONTROL_STOP 0x10
  33. #define MV64x60_I2C_CONTROL_START 0x20
  34. #define MV64x60_I2C_CONTROL_TWSIEN 0x40
  35. #define MV64x60_I2C_CONTROL_INTEN 0x80
  36. #define MV64x60_I2C_STATUS_BUS_ERR 0x00
  37. #define MV64x60_I2C_STATUS_MAST_START 0x08
  38. #define MV64x60_I2C_STATUS_MAST_REPEAT_START 0x10
  39. #define MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK 0x18
  40. #define MV64x60_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20
  41. #define MV64x60_I2C_STATUS_MAST_WR_ACK 0x28
  42. #define MV64x60_I2C_STATUS_MAST_WR_NO_ACK 0x30
  43. #define MV64x60_I2C_STATUS_MAST_LOST_ARB 0x38
  44. #define MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK 0x40
  45. #define MV64x60_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48
  46. #define MV64x60_I2C_STATUS_MAST_RD_DATA_ACK 0x50
  47. #define MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58
  48. #define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0
  49. #define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8
  50. #define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0
  51. #define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8
  52. #define MV64x60_I2C_STATUS_NO_STATUS 0xf8
  53. static u8 *ctlr_base;
  54. static int mv64x60_i2c_wait_for_status(int wanted)
  55. {
  56. int i;
  57. int status;
  58. for (i=0; i<1000; i++) {
  59. udelay(10);
  60. status = in_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_STATUS))
  61. & 0xff;
  62. if (status == wanted)
  63. return status;
  64. }
  65. return -status;
  66. }
  67. static int mv64x60_i2c_control(int control, int status)
  68. {
  69. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff);
  70. return mv64x60_i2c_wait_for_status(status);
  71. }
  72. static int mv64x60_i2c_read_byte(int control, int status)
  73. {
  74. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff);
  75. if (mv64x60_i2c_wait_for_status(status) < 0)
  76. return -1;
  77. return in_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_DATA)) & 0xff;
  78. }
  79. static int mv64x60_i2c_write_byte(int data, int control, int status)
  80. {
  81. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_DATA), data & 0xff);
  82. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff);
  83. return mv64x60_i2c_wait_for_status(status);
  84. }
  85. int mv64x60_i2c_read(u32 devaddr, u8 *buf, u32 offset, u32 offset_size,
  86. u32 count)
  87. {
  88. int i;
  89. int data;
  90. int control;
  91. int status;
  92. if (ctlr_base == NULL)
  93. return -1;
  94. /* send reset */
  95. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_SOFT_RESET), 0);
  96. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_SLAVE_ADDR), 0);
  97. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_EXT_SLAVE_ADDR), 0);
  98. out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_BAUD), (4 << 3) | 0x4);
  99. if (mv64x60_i2c_control(MV64x60_I2C_CONTROL_TWSIEN,
  100. MV64x60_I2C_STATUS_NO_STATUS) < 0)
  101. return -1;
  102. /* send start */
  103. control = MV64x60_I2C_CONTROL_START | MV64x60_I2C_CONTROL_TWSIEN;
  104. status = MV64x60_I2C_STATUS_MAST_START;
  105. if (mv64x60_i2c_control(control, status) < 0)
  106. return -1;
  107. /* select device for writing */
  108. data = devaddr & ~0x1;
  109. control = MV64x60_I2C_CONTROL_TWSIEN;
  110. status = MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK;
  111. if (mv64x60_i2c_write_byte(data, control, status) < 0)
  112. return -1;
  113. /* send offset of data */
  114. control = MV64x60_I2C_CONTROL_TWSIEN;
  115. status = MV64x60_I2C_STATUS_MAST_WR_ACK;
  116. if (offset_size > 1) {
  117. if (mv64x60_i2c_write_byte(offset >> 8, control, status) < 0)
  118. return -1;
  119. }
  120. if (mv64x60_i2c_write_byte(offset, control, status) < 0)
  121. return -1;
  122. /* resend start */
  123. control = MV64x60_I2C_CONTROL_START | MV64x60_I2C_CONTROL_TWSIEN;
  124. status = MV64x60_I2C_STATUS_MAST_REPEAT_START;
  125. if (mv64x60_i2c_control(control, status) < 0)
  126. return -1;
  127. /* select device for reading */
  128. data = devaddr | 0x1;
  129. control = MV64x60_I2C_CONTROL_TWSIEN;
  130. status = MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK;
  131. if (mv64x60_i2c_write_byte(data, control, status) < 0)
  132. return -1;
  133. /* read all but last byte of data */
  134. control = MV64x60_I2C_CONTROL_ACK | MV64x60_I2C_CONTROL_TWSIEN;
  135. status = MV64x60_I2C_STATUS_MAST_RD_DATA_ACK;
  136. for (i=1; i<count; i++) {
  137. data = mv64x60_i2c_read_byte(control, status);
  138. if (data < 0) {
  139. printf("errors on iteration %d\n", i);
  140. return -1;
  141. }
  142. *buf++ = data;
  143. }
  144. /* read last byte of data */
  145. control = MV64x60_I2C_CONTROL_TWSIEN;
  146. status = MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK;
  147. data = mv64x60_i2c_read_byte(control, status);
  148. if (data < 0)
  149. return -1;
  150. *buf++ = data;
  151. /* send stop */
  152. control = MV64x60_I2C_CONTROL_STOP | MV64x60_I2C_CONTROL_TWSIEN;
  153. status = MV64x60_I2C_STATUS_NO_STATUS;
  154. if (mv64x60_i2c_control(control, status) < 0)
  155. return -1;
  156. return count;
  157. }
  158. int mv64x60_i2c_open(void)
  159. {
  160. u32 v;
  161. void *devp;
  162. devp = find_node_by_compatible(NULL, "marvell,mv64360-i2c");
  163. if (devp == NULL)
  164. goto err_out;
  165. if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
  166. goto err_out;
  167. ctlr_base = (u8 *)v;
  168. return 0;
  169. err_out:
  170. return -1;
  171. }
  172. void mv64x60_i2c_close(void)
  173. {
  174. ctlr_base = NULL;
  175. }