fti2c010.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * Faraday I2C Controller
  3. *
  4. * (C) Copyright 2010 Faraday Technology
  5. * Dante Su <dantesu@faraday-tech.com>
  6. *
  7. * This file is released under the terms of GPL v2 and any later version.
  8. * See the file COPYING in the root directory of the source tree for details.
  9. */
  10. #include <common.h>
  11. #include <asm/io.h>
  12. #include <i2c.h>
  13. #include "fti2c010.h"
  14. #ifndef CONFIG_HARD_I2C
  15. #error "fti2c010: CONFIG_HARD_I2C is not defined"
  16. #endif
  17. #ifndef CONFIG_SYS_I2C_SPEED
  18. #define CONFIG_SYS_I2C_SPEED 50000
  19. #endif
  20. #ifndef CONFIG_FTI2C010_FREQ
  21. #define CONFIG_FTI2C010_FREQ clk_get_rate("I2C")
  22. #endif
  23. /* command timeout */
  24. #define CFG_CMD_TIMEOUT 10 /* ms */
  25. /* 7-bit chip address + 1-bit read/write */
  26. #define I2C_RD(chip) ((((chip) << 1) & 0xff) | 1)
  27. #define I2C_WR(chip) (((chip) << 1) & 0xff)
  28. struct fti2c010_chip {
  29. void __iomem *regs;
  30. uint bus;
  31. uint speed;
  32. };
  33. static struct fti2c010_chip chip_list[] = {
  34. {
  35. .bus = 0,
  36. .regs = (void __iomem *)CONFIG_FTI2C010_BASE,
  37. },
  38. #ifdef CONFIG_I2C_MULTI_BUS
  39. # ifdef CONFIG_FTI2C010_BASE1
  40. {
  41. .bus = 1,
  42. .regs = (void __iomem *)CONFIG_FTI2C010_BASE1,
  43. },
  44. # endif
  45. # ifdef CONFIG_FTI2C010_BASE2
  46. {
  47. .bus = 2,
  48. .regs = (void __iomem *)CONFIG_FTI2C010_BASE2,
  49. },
  50. # endif
  51. # ifdef CONFIG_FTI2C010_BASE3
  52. {
  53. .bus = 3,
  54. .regs = (void __iomem *)CONFIG_FTI2C010_BASE3,
  55. },
  56. # endif
  57. #endif /* #ifdef CONFIG_I2C_MULTI_BUS */
  58. };
  59. static struct fti2c010_chip *curr = chip_list;
  60. static int fti2c010_wait(uint32_t mask)
  61. {
  62. int ret = -1;
  63. uint32_t stat, ts;
  64. struct fti2c010_regs *regs = curr->regs;
  65. for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
  66. stat = readl(&regs->sr);
  67. if ((stat & mask) == mask) {
  68. ret = 0;
  69. break;
  70. }
  71. }
  72. return ret;
  73. }
  74. /*
  75. * u-boot I2C API
  76. */
  77. /*
  78. * Initialization, must be called once on start up, may be called
  79. * repeatedly to change the speed and slave addresses.
  80. */
  81. void i2c_init(int speed, int slaveaddr)
  82. {
  83. if (speed || !curr->speed)
  84. i2c_set_bus_speed(speed);
  85. /* if slave mode disabled */
  86. if (!slaveaddr)
  87. return;
  88. /*
  89. * TODO:
  90. * Implement slave mode, but is it really necessary?
  91. */
  92. }
  93. /*
  94. * Probe the given I2C chip address. Returns 0 if a chip responded,
  95. * not 0 on failure.
  96. */
  97. int i2c_probe(uchar chip)
  98. {
  99. int ret;
  100. struct fti2c010_regs *regs = curr->regs;
  101. i2c_init(0, 0);
  102. /* 1. Select slave device (7bits Address + 1bit R/W) */
  103. writel(I2C_WR(chip), &regs->dr);
  104. writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
  105. ret = fti2c010_wait(SR_DT);
  106. if (ret)
  107. return ret;
  108. /* 2. Select device register */
  109. writel(0, &regs->dr);
  110. writel(CR_ENABLE | CR_TBEN, &regs->cr);
  111. ret = fti2c010_wait(SR_DT);
  112. return ret;
  113. }
  114. /*
  115. * Read/Write interface:
  116. * chip: I2C chip address, range 0..127
  117. * addr: Memory (register) address within the chip
  118. * alen: Number of bytes to use for addr (typically 1, 2 for larger
  119. * memories, 0 for register type devices with only one
  120. * register)
  121. * buffer: Where to read/write the data
  122. * len: How many bytes to read/write
  123. *
  124. * Returns: 0 on success, not 0 on failure
  125. */
  126. int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
  127. {
  128. int ret, pos;
  129. uchar paddr[4];
  130. struct fti2c010_regs *regs = curr->regs;
  131. i2c_init(0, 0);
  132. paddr[0] = (addr >> 0) & 0xFF;
  133. paddr[1] = (addr >> 8) & 0xFF;
  134. paddr[2] = (addr >> 16) & 0xFF;
  135. paddr[3] = (addr >> 24) & 0xFF;
  136. /*
  137. * Phase A. Set register address
  138. */
  139. /* A.1 Select slave device (7bits Address + 1bit R/W) */
  140. writel(I2C_WR(chip), &regs->dr);
  141. writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
  142. ret = fti2c010_wait(SR_DT);
  143. if (ret)
  144. return ret;
  145. /* A.2 Select device register */
  146. for (pos = 0; pos < alen; ++pos) {
  147. uint32_t ctrl = CR_ENABLE | CR_TBEN;
  148. writel(paddr[pos], &regs->dr);
  149. writel(ctrl, &regs->cr);
  150. ret = fti2c010_wait(SR_DT);
  151. if (ret)
  152. return ret;
  153. }
  154. /*
  155. * Phase B. Get register data
  156. */
  157. /* B.1 Select slave device (7bits Address + 1bit R/W) */
  158. writel(I2C_RD(chip), &regs->dr);
  159. writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
  160. ret = fti2c010_wait(SR_DT);
  161. if (ret)
  162. return ret;
  163. /* B.2 Get register data */
  164. for (pos = 0; pos < len; ++pos) {
  165. uint32_t ctrl = CR_ENABLE | CR_TBEN;
  166. uint32_t stat = SR_DR;
  167. if (pos == len - 1) {
  168. ctrl |= CR_NAK | CR_STOP;
  169. stat |= SR_ACK;
  170. }
  171. writel(ctrl, &regs->cr);
  172. ret = fti2c010_wait(stat);
  173. if (ret)
  174. break;
  175. buf[pos] = (uchar)(readl(&regs->dr) & 0xFF);
  176. }
  177. return ret;
  178. }
  179. /*
  180. * Read/Write interface:
  181. * chip: I2C chip address, range 0..127
  182. * addr: Memory (register) address within the chip
  183. * alen: Number of bytes to use for addr (typically 1, 2 for larger
  184. * memories, 0 for register type devices with only one
  185. * register)
  186. * buffer: Where to read/write the data
  187. * len: How many bytes to read/write
  188. *
  189. * Returns: 0 on success, not 0 on failure
  190. */
  191. int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
  192. {
  193. int ret, pos;
  194. uchar paddr[4];
  195. struct fti2c010_regs *regs = curr->regs;
  196. i2c_init(0, 0);
  197. paddr[0] = (addr >> 0) & 0xFF;
  198. paddr[1] = (addr >> 8) & 0xFF;
  199. paddr[2] = (addr >> 16) & 0xFF;
  200. paddr[3] = (addr >> 24) & 0xFF;
  201. /*
  202. * Phase A. Set register address
  203. *
  204. * A.1 Select slave device (7bits Address + 1bit R/W)
  205. */
  206. writel(I2C_WR(chip), &regs->dr);
  207. writel(CR_ENABLE | CR_TBEN | CR_START, &regs->cr);
  208. ret = fti2c010_wait(SR_DT);
  209. if (ret)
  210. return ret;
  211. /* A.2 Select device register */
  212. for (pos = 0; pos < alen; ++pos) {
  213. uint32_t ctrl = CR_ENABLE | CR_TBEN;
  214. writel(paddr[pos], &regs->dr);
  215. writel(ctrl, &regs->cr);
  216. ret = fti2c010_wait(SR_DT);
  217. if (ret)
  218. return ret;
  219. }
  220. /*
  221. * Phase B. Set register data
  222. */
  223. for (pos = 0; pos < len; ++pos) {
  224. uint32_t ctrl = CR_ENABLE | CR_TBEN;
  225. if (pos == len - 1)
  226. ctrl |= CR_STOP;
  227. writel(buf[pos], &regs->dr);
  228. writel(ctrl, &regs->cr);
  229. ret = fti2c010_wait(SR_DT);
  230. if (ret)
  231. break;
  232. }
  233. return ret;
  234. }
  235. /*
  236. * Functions for setting the current I2C bus and its speed
  237. */
  238. #ifdef CONFIG_I2C_MULTI_BUS
  239. /*
  240. * i2c_set_bus_num:
  241. *
  242. * Change the active I2C bus. Subsequent read/write calls will
  243. * go to this one.
  244. *
  245. * bus - bus index, zero based
  246. *
  247. * Returns: 0 on success, not 0 on failure
  248. */
  249. int i2c_set_bus_num(uint bus)
  250. {
  251. if (bus >= ARRAY_SIZE(chip_list))
  252. return -1;
  253. curr = chip_list + bus;
  254. i2c_init(0, 0);
  255. return 0;
  256. }
  257. /*
  258. * i2c_get_bus_num:
  259. *
  260. * Returns index of currently active I2C bus. Zero-based.
  261. */
  262. uint i2c_get_bus_num(void)
  263. {
  264. return curr->bus;
  265. }
  266. #endif /* #ifdef CONFIG_I2C_MULTI_BUS */
  267. /*
  268. * i2c_set_bus_speed:
  269. *
  270. * Change the speed of the active I2C bus
  271. *
  272. * speed - bus speed in Hz
  273. *
  274. * Returns: 0 on success, not 0 on failure
  275. */
  276. int i2c_set_bus_speed(uint speed)
  277. {
  278. struct fti2c010_regs *regs = curr->regs;
  279. uint clk = CONFIG_FTI2C010_FREQ;
  280. uint gsr = 0, tsr = 32;
  281. uint spd, div;
  282. if (!speed)
  283. speed = CONFIG_SYS_I2C_SPEED;
  284. for (div = 0; div < 0x3ffff; ++div) {
  285. /* SCLout = PCLK/(2*(COUNT + 2) + GSR) */
  286. spd = clk / (2 * (div + 2) + gsr);
  287. if (spd <= speed)
  288. break;
  289. }
  290. if (curr->speed == spd)
  291. return 0;
  292. writel(CR_I2CRST, &regs->cr);
  293. mdelay(100);
  294. if (readl(&regs->cr) & CR_I2CRST) {
  295. printf("fti2c010: reset timeout\n");
  296. return -1;
  297. }
  298. curr->speed = spd;
  299. writel(TGSR_GSR(gsr) | TGSR_TSR(tsr), &regs->tgsr);
  300. writel(CDR_DIV(div), &regs->cdr);
  301. return 0;
  302. }
  303. /*
  304. * i2c_get_bus_speed:
  305. *
  306. * Returns speed of currently active I2C bus in Hz
  307. */
  308. uint i2c_get_bus_speed(void)
  309. {
  310. return curr->speed;
  311. }