omap_i2c.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /*
  2. * TI OMAP on-chip I2C controller. Only "new I2C" mode supported.
  3. *
  4. * Copyright (C) 2007 Andrzej Zaborowski <balrog@zabor.org>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "hw/hw.h"
  20. #include "hw/i2c/i2c.h"
  21. #include "hw/arm/omap.h"
  22. #include "hw/sysbus.h"
  23. #define TYPE_OMAP_I2C "omap_i2c"
  24. #define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
  25. typedef struct OMAPI2CState {
  26. SysBusDevice parent_obj;
  27. MemoryRegion iomem;
  28. qemu_irq irq;
  29. qemu_irq drq[2];
  30. I2CBus *bus;
  31. uint8_t revision;
  32. void *iclk;
  33. void *fclk;
  34. uint8_t mask;
  35. uint16_t stat;
  36. uint16_t dma;
  37. uint16_t count;
  38. int count_cur;
  39. uint32_t fifo;
  40. int rxlen;
  41. int txlen;
  42. uint16_t control;
  43. uint16_t addr[2];
  44. uint8_t divider;
  45. uint8_t times[2];
  46. uint16_t test;
  47. } OMAPI2CState;
  48. #define OMAP2_INTR_REV 0x34
  49. #define OMAP2_GC_REV 0x34
  50. static void omap_i2c_interrupts_update(OMAPI2CState *s)
  51. {
  52. qemu_set_irq(s->irq, s->stat & s->mask);
  53. if ((s->dma >> 15) & 1) /* RDMA_EN */
  54. qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
  55. if ((s->dma >> 7) & 1) /* XDMA_EN */
  56. qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
  57. }
  58. static void omap_i2c_fifo_run(OMAPI2CState *s)
  59. {
  60. int ack = 1;
  61. if (!i2c_bus_busy(s->bus))
  62. return;
  63. if ((s->control >> 2) & 1) { /* RM */
  64. if ((s->control >> 1) & 1) { /* STP */
  65. i2c_end_transfer(s->bus);
  66. s->control &= ~(1 << 1); /* STP */
  67. s->count_cur = s->count;
  68. s->txlen = 0;
  69. } else if ((s->control >> 9) & 1) { /* TRX */
  70. while (ack && s->txlen)
  71. ack = (i2c_send(s->bus,
  72. (s->fifo >> ((-- s->txlen) << 3)) &
  73. 0xff) >= 0);
  74. s->stat |= 1 << 4; /* XRDY */
  75. } else {
  76. while (s->rxlen < 4)
  77. s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
  78. s->stat |= 1 << 3; /* RRDY */
  79. }
  80. } else {
  81. if ((s->control >> 9) & 1) { /* TRX */
  82. while (ack && s->count_cur && s->txlen) {
  83. ack = (i2c_send(s->bus,
  84. (s->fifo >> ((-- s->txlen) << 3)) &
  85. 0xff) >= 0);
  86. s->count_cur --;
  87. }
  88. if (ack && s->count_cur)
  89. s->stat |= 1 << 4; /* XRDY */
  90. else
  91. s->stat &= ~(1 << 4); /* XRDY */
  92. if (!s->count_cur) {
  93. s->stat |= 1 << 2; /* ARDY */
  94. s->control &= ~(1 << 10); /* MST */
  95. }
  96. } else {
  97. while (s->count_cur && s->rxlen < 4) {
  98. s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
  99. s->count_cur --;
  100. }
  101. if (s->rxlen)
  102. s->stat |= 1 << 3; /* RRDY */
  103. else
  104. s->stat &= ~(1 << 3); /* RRDY */
  105. }
  106. if (!s->count_cur) {
  107. if ((s->control >> 1) & 1) { /* STP */
  108. i2c_end_transfer(s->bus);
  109. s->control &= ~(1 << 1); /* STP */
  110. s->count_cur = s->count;
  111. s->txlen = 0;
  112. } else {
  113. s->stat |= 1 << 2; /* ARDY */
  114. s->control &= ~(1 << 10); /* MST */
  115. }
  116. }
  117. }
  118. s->stat |= (!ack) << 1; /* NACK */
  119. if (!ack)
  120. s->control &= ~(1 << 1); /* STP */
  121. }
  122. static void omap_i2c_reset(DeviceState *dev)
  123. {
  124. OMAPI2CState *s = OMAP_I2C(dev);
  125. s->mask = 0;
  126. s->stat = 0;
  127. s->dma = 0;
  128. s->count = 0;
  129. s->count_cur = 0;
  130. s->fifo = 0;
  131. s->rxlen = 0;
  132. s->txlen = 0;
  133. s->control = 0;
  134. s->addr[0] = 0;
  135. s->addr[1] = 0;
  136. s->divider = 0;
  137. s->times[0] = 0;
  138. s->times[1] = 0;
  139. s->test = 0;
  140. }
  141. static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
  142. {
  143. OMAPI2CState *s = opaque;
  144. int offset = addr & OMAP_MPUI_REG_MASK;
  145. uint16_t ret;
  146. switch (offset) {
  147. case 0x00: /* I2C_REV */
  148. return s->revision; /* REV */
  149. case 0x04: /* I2C_IE */
  150. return s->mask;
  151. case 0x08: /* I2C_STAT */
  152. return s->stat | (i2c_bus_busy(s->bus) << 12);
  153. case 0x0c: /* I2C_IV */
  154. if (s->revision >= OMAP2_INTR_REV)
  155. break;
  156. ret = ffs(s->stat & s->mask);
  157. if (ret)
  158. s->stat ^= 1 << (ret - 1);
  159. omap_i2c_interrupts_update(s);
  160. return ret;
  161. case 0x10: /* I2C_SYSS */
  162. return (s->control >> 15) & 1; /* I2C_EN */
  163. case 0x14: /* I2C_BUF */
  164. return s->dma;
  165. case 0x18: /* I2C_CNT */
  166. return s->count_cur; /* DCOUNT */
  167. case 0x1c: /* I2C_DATA */
  168. ret = 0;
  169. if (s->control & (1 << 14)) { /* BE */
  170. ret |= ((s->fifo >> 0) & 0xff) << 8;
  171. ret |= ((s->fifo >> 8) & 0xff) << 0;
  172. } else {
  173. ret |= ((s->fifo >> 8) & 0xff) << 8;
  174. ret |= ((s->fifo >> 0) & 0xff) << 0;
  175. }
  176. if (s->rxlen == 1) {
  177. s->stat |= 1 << 15; /* SBD */
  178. s->rxlen = 0;
  179. } else if (s->rxlen > 1) {
  180. if (s->rxlen > 2)
  181. s->fifo >>= 16;
  182. s->rxlen -= 2;
  183. } else {
  184. /* XXX: remote access (qualifier) error - what's that? */
  185. }
  186. if (!s->rxlen) {
  187. s->stat &= ~(1 << 3); /* RRDY */
  188. if (((s->control >> 10) & 1) && /* MST */
  189. ((~s->control >> 9) & 1)) { /* TRX */
  190. s->stat |= 1 << 2; /* ARDY */
  191. s->control &= ~(1 << 10); /* MST */
  192. }
  193. }
  194. s->stat &= ~(1 << 11); /* ROVR */
  195. omap_i2c_fifo_run(s);
  196. omap_i2c_interrupts_update(s);
  197. return ret;
  198. case 0x20: /* I2C_SYSC */
  199. return 0;
  200. case 0x24: /* I2C_CON */
  201. return s->control;
  202. case 0x28: /* I2C_OA */
  203. return s->addr[0];
  204. case 0x2c: /* I2C_SA */
  205. return s->addr[1];
  206. case 0x30: /* I2C_PSC */
  207. return s->divider;
  208. case 0x34: /* I2C_SCLL */
  209. return s->times[0];
  210. case 0x38: /* I2C_SCLH */
  211. return s->times[1];
  212. case 0x3c: /* I2C_SYSTEST */
  213. if (s->test & (1 << 15)) { /* ST_EN */
  214. s->test ^= 0xa;
  215. return s->test;
  216. } else
  217. return s->test & ~0x300f;
  218. }
  219. OMAP_BAD_REG(addr);
  220. return 0;
  221. }
  222. static void omap_i2c_write(void *opaque, hwaddr addr,
  223. uint32_t value)
  224. {
  225. OMAPI2CState *s = opaque;
  226. int offset = addr & OMAP_MPUI_REG_MASK;
  227. int nack;
  228. switch (offset) {
  229. case 0x00: /* I2C_REV */
  230. case 0x0c: /* I2C_IV */
  231. case 0x10: /* I2C_SYSS */
  232. OMAP_RO_REG(addr);
  233. return;
  234. case 0x04: /* I2C_IE */
  235. s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
  236. break;
  237. case 0x08: /* I2C_STAT */
  238. if (s->revision < OMAP2_INTR_REV) {
  239. OMAP_RO_REG(addr);
  240. return;
  241. }
  242. /* RRDY and XRDY are reset by hardware. (in all versions???) */
  243. s->stat &= ~(value & 0x27);
  244. omap_i2c_interrupts_update(s);
  245. break;
  246. case 0x14: /* I2C_BUF */
  247. s->dma = value & 0x8080;
  248. if (value & (1 << 15)) /* RDMA_EN */
  249. s->mask &= ~(1 << 3); /* RRDY_IE */
  250. if (value & (1 << 7)) /* XDMA_EN */
  251. s->mask &= ~(1 << 4); /* XRDY_IE */
  252. break;
  253. case 0x18: /* I2C_CNT */
  254. s->count = value; /* DCOUNT */
  255. break;
  256. case 0x1c: /* I2C_DATA */
  257. if (s->txlen > 2) {
  258. /* XXX: remote access (qualifier) error - what's that? */
  259. break;
  260. }
  261. s->fifo <<= 16;
  262. s->txlen += 2;
  263. if (s->control & (1 << 14)) { /* BE */
  264. s->fifo |= ((value >> 8) & 0xff) << 8;
  265. s->fifo |= ((value >> 0) & 0xff) << 0;
  266. } else {
  267. s->fifo |= ((value >> 0) & 0xff) << 8;
  268. s->fifo |= ((value >> 8) & 0xff) << 0;
  269. }
  270. s->stat &= ~(1 << 10); /* XUDF */
  271. if (s->txlen > 2)
  272. s->stat &= ~(1 << 4); /* XRDY */
  273. omap_i2c_fifo_run(s);
  274. omap_i2c_interrupts_update(s);
  275. break;
  276. case 0x20: /* I2C_SYSC */
  277. if (s->revision < OMAP2_INTR_REV) {
  278. OMAP_BAD_REG(addr);
  279. return;
  280. }
  281. if (value & 2) {
  282. omap_i2c_reset(DEVICE(s));
  283. }
  284. break;
  285. case 0x24: /* I2C_CON */
  286. s->control = value & 0xcf87;
  287. if (~value & (1 << 15)) { /* I2C_EN */
  288. if (s->revision < OMAP2_INTR_REV) {
  289. omap_i2c_reset(DEVICE(s));
  290. }
  291. break;
  292. }
  293. if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
  294. fprintf(stderr, "%s: I^2C slave mode not supported\n",
  295. __FUNCTION__);
  296. break;
  297. }
  298. if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
  299. fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
  300. __FUNCTION__);
  301. break;
  302. }
  303. if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
  304. nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
  305. (~value >> 9) & 1); /* TRX */
  306. s->stat |= nack << 1; /* NACK */
  307. s->control &= ~(1 << 0); /* STT */
  308. s->fifo = 0;
  309. if (nack)
  310. s->control &= ~(1 << 1); /* STP */
  311. else {
  312. s->count_cur = s->count;
  313. omap_i2c_fifo_run(s);
  314. }
  315. omap_i2c_interrupts_update(s);
  316. }
  317. break;
  318. case 0x28: /* I2C_OA */
  319. s->addr[0] = value & 0x3ff;
  320. break;
  321. case 0x2c: /* I2C_SA */
  322. s->addr[1] = value & 0x3ff;
  323. break;
  324. case 0x30: /* I2C_PSC */
  325. s->divider = value;
  326. break;
  327. case 0x34: /* I2C_SCLL */
  328. s->times[0] = value;
  329. break;
  330. case 0x38: /* I2C_SCLH */
  331. s->times[1] = value;
  332. break;
  333. case 0x3c: /* I2C_SYSTEST */
  334. s->test = value & 0xf80f;
  335. if (value & (1 << 11)) /* SBB */
  336. if (s->revision >= OMAP2_INTR_REV) {
  337. s->stat |= 0x3f;
  338. omap_i2c_interrupts_update(s);
  339. }
  340. if (value & (1 << 15)) /* ST_EN */
  341. fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
  342. break;
  343. default:
  344. OMAP_BAD_REG(addr);
  345. return;
  346. }
  347. }
  348. static void omap_i2c_writeb(void *opaque, hwaddr addr,
  349. uint32_t value)
  350. {
  351. OMAPI2CState *s = opaque;
  352. int offset = addr & OMAP_MPUI_REG_MASK;
  353. switch (offset) {
  354. case 0x1c: /* I2C_DATA */
  355. if (s->txlen > 2) {
  356. /* XXX: remote access (qualifier) error - what's that? */
  357. break;
  358. }
  359. s->fifo <<= 8;
  360. s->txlen += 1;
  361. s->fifo |= value & 0xff;
  362. s->stat &= ~(1 << 10); /* XUDF */
  363. if (s->txlen > 2)
  364. s->stat &= ~(1 << 4); /* XRDY */
  365. omap_i2c_fifo_run(s);
  366. omap_i2c_interrupts_update(s);
  367. break;
  368. default:
  369. OMAP_BAD_REG(addr);
  370. return;
  371. }
  372. }
  373. static const MemoryRegionOps omap_i2c_ops = {
  374. .old_mmio = {
  375. .read = {
  376. omap_badwidth_read16,
  377. omap_i2c_read,
  378. omap_badwidth_read16,
  379. },
  380. .write = {
  381. omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
  382. omap_i2c_write,
  383. omap_badwidth_write16,
  384. },
  385. },
  386. .endianness = DEVICE_NATIVE_ENDIAN,
  387. };
  388. static int omap_i2c_init(SysBusDevice *sbd)
  389. {
  390. DeviceState *dev = DEVICE(sbd);
  391. OMAPI2CState *s = OMAP_I2C(dev);
  392. if (!s->fclk) {
  393. hw_error("omap_i2c: fclk not connected\n");
  394. }
  395. if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
  396. /* Note that OMAP1 doesn't have a separate interface clock */
  397. hw_error("omap_i2c: iclk not connected\n");
  398. }
  399. sysbus_init_irq(sbd, &s->irq);
  400. sysbus_init_irq(sbd, &s->drq[0]);
  401. sysbus_init_irq(sbd, &s->drq[1]);
  402. memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
  403. (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
  404. sysbus_init_mmio(sbd, &s->iomem);
  405. s->bus = i2c_init_bus(dev, NULL);
  406. return 0;
  407. }
  408. static Property omap_i2c_properties[] = {
  409. DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
  410. DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
  411. DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
  412. DEFINE_PROP_END_OF_LIST(),
  413. };
  414. static void omap_i2c_class_init(ObjectClass *klass, void *data)
  415. {
  416. DeviceClass *dc = DEVICE_CLASS(klass);
  417. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  418. k->init = omap_i2c_init;
  419. dc->props = omap_i2c_properties;
  420. dc->reset = omap_i2c_reset;
  421. /* Reason: pointer properties "iclk", "fclk" */
  422. dc->cannot_instantiate_with_device_add_yet = true;
  423. }
  424. static const TypeInfo omap_i2c_info = {
  425. .name = TYPE_OMAP_I2C,
  426. .parent = TYPE_SYS_BUS_DEVICE,
  427. .instance_size = sizeof(OMAPI2CState),
  428. .class_init = omap_i2c_class_init,
  429. };
  430. static void omap_i2c_register_types(void)
  431. {
  432. type_register_static(&omap_i2c_info);
  433. }
  434. I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
  435. {
  436. OMAPI2CState *s = OMAP_I2C(omap_i2c);
  437. return s->bus;
  438. }
  439. type_init(omap_i2c_register_types)