2 * TI OMAP on-chip I2C controller. Only "new I2C" mode supported.
4 * Copyright (C) 2007 Andrzej Zaborowski <balrog@zabor.org>
5 * Copyright (C) 2009 Nokia Corporation
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #define I2C_MAX_FIFO_SIZE (1 << 6)
26 #define I2C_FIFO_SIZE_MASK ((I2C_MAX_FIFO_SIZE) - 1)
51 uint8_t fifo[I2C_MAX_FIFO_SIZE];
54 #define OMAP2_INTR_REV 0x34
55 #define OMAP2_GC_REV 0x34
56 #define OMAP3_INTR_REV 0x3c
60 #define TRACE(fmt, ...) fprintf(stderr, "%s " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
65 static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
67 TRACE("IRQ=%04x,RDRQ=%d,XDRQ=%d",
69 ((s->dma >> 15 ) & 1) & ((s->stat >> 3) & 1),
70 ((s->dma >> 7 ) & 1 )& ((s->stat >> 4 ) & 1));
71 qemu_set_irq(s->irq, s->stat & s->mask);
72 if ((s->dma >> 15) & 1) /* RDMA_EN */
73 qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
74 if ((s->dma >> 7) & 1) /* XDMA_EN */
75 qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
78 static void omap_i2c_fifo_run(struct omap_i2c_s *s)
82 if (!i2c_bus_busy(s->bus))
85 if ((s->control >> 2) & 1) { /* RM */
86 if ((s->control >> 1) & 1) { /* STP */
87 i2c_end_transfer(s->bus);
88 s->control &= ~(1 << 1); /* STP */
89 s->count_cur = s->count;
91 } else if ((s->control >> 9) & 1) { /* TRX */
92 while (ack && s->fifolen) {
93 ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
94 s->fifostart &= I2C_FIFO_SIZE_MASK;
98 s->stat |= 1 << 4; /* XRDY */
100 for (i = 0; i < 4; i++)
101 s->fifo[(s->fifostart + i) & I2C_FIFO_SIZE_MASK] =
104 s->stat |= 1 << 3; /* RRDY */
107 if ((s->control >> 9) & 1) { /* TRX */
108 TRACE("master transmit, count_cur=%d, fifolen=%d",
109 s->count_cur, s->fifolen);
110 for (; ack && s->count_cur && s->fifolen; s->count_cur--) {
111 ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
112 s->fifostart &= I2C_FIFO_SIZE_MASK;
115 s->stat &= ~0x4410; /* XDR | XUDF | XRDY */
116 if (ack && s->count_cur) { /* send more? */
117 /* we know that FIFO is empty */
118 if (s->revision < OMAP3_INTR_REV)
119 s->stat |= 1 << 4; /* XRDY */
121 if (s->count_cur > (s->dma & 0x3f)) /* XTRSH */
122 s->stat |= 1 << 4; /* XRDY */
124 s->stat |= 1 << 14; /* XDR */
127 if (!s->count_cur) /* everything sent? */
128 s->stat |= 1 << 2; /* ARDY */
130 TRACE("master receive");
131 for (; s->count_cur && s->fifolen < s->fifosize; s->count_cur--) {
132 i = i2c_recv(s->bus);
133 if (i < 0) break; /* stop receiving if nothing to receive */
134 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
136 TRACE("received fifo[%02x] = %02x", s->fifolen - 1,
137 s->fifo[(s->fifostart + s->fifolen - 1) & I2C_FIFO_SIZE_MASK]);
139 s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
141 if (s->revision < OMAP3_INTR_REV)
142 s->stat |= 1 << 3; /* RRDY */
144 if (s->fifolen > ((s->dma >> 8) & 0x3f)) /* RTRSH */
145 s->stat |= 1 << 3; /* RRDY */
147 s->stat |= 1 << 13; /* RDR */
149 } else if (!s->count_cur && (s->control & 2)) /* STP */
150 s->stat |= 1 << 2; /* ARDY */
153 TRACE("no more data to transmit/receive");
154 if ((s->control >> 1) & 1) { /* STP */
155 i2c_end_transfer(s->bus);
156 s->control &= ~0x0602; /* MST | TRX | STP */
157 s->count_cur = s->count;
162 s->stat |= (!ack) << 1; /* NACK */
164 s->control &= ~(1 << 1); /* STP */
165 TRACE("finished, STAT = %04x, CNT = %d", s->stat, s->count_cur);
168 void omap_i2c_reset(struct omap_i2c_s *s)
192 static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
194 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
195 int offset = addr & OMAP_MPUI_REG_MASK;
199 case 0x00: /* I2C_REV */
200 TRACE("REV returns %04x", s->revision);
202 case 0x04: /* I2C_IE */
203 TRACE("IE returns %04x", s->mask);
205 case 0x08: /* I2C_STAT */
206 TRACE("STAT returns %04x", s->stat | (i2c_bus_busy(s->bus) << 12));
207 return s->stat | (i2c_bus_busy(s->bus) << 12);
208 case 0x0c: /* I2C_IV / I2C_WE */
209 if (s->revision >= OMAP3_INTR_REV)
211 if (s->revision >= OMAP2_INTR_REV)
213 ret = ffs(s->stat & s->mask);
215 s->stat ^= 1 << (ret - 1);
216 omap_i2c_interrupts_update(s);
218 case 0x10: /* I2C_SYSS */
219 return (s->control >> 15) & 1; /* reset completed == I2C_EN */
220 case 0x14: /* I2C_BUF */
221 TRACE("BUF returns %04x", s->dma);
223 case 0x18: /* I2C_CNT */
224 TRACE("CNT returns %04x", s->count_cur);
225 return s->count_cur; /* DCOUNT */
226 case 0x1c: /* I2C_DATA */
229 if (s->revision < OMAP3_INTR_REV) {
230 if (s->control & (1 << 14)) /* BE */
231 ret = (((uint16_t)s->fifo[s->fifostart]) << 8)
232 | s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK];
234 ret = (((uint16_t)s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK]) << 8)
235 | s->fifo[s->fifostart];
236 s->fifostart = (s->fifostart + 2) & I2C_FIFO_SIZE_MASK;
237 if (s->fifolen == 1) {
238 s->stat |= 1 << 15; /* SBD */
243 s->stat &= ~(1 << 3); /* RRDY */
244 s->stat |= 1 << 2; /* ARDY */
247 s->stat &= ~(1 << 7); /* AERR */
248 ret = s->fifo[s->fifostart++];
249 s->fifostart &= I2C_FIFO_SIZE_MASK;
251 if (s->fifolen <= ((s->dma >> 8) & 0x3f)) {
252 s->stat &= ~(1 << 3); /* RRDY */
253 s->stat |= 1 << 13; /* RDR */
256 s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
257 s->stat |= 1 << 2; /* ARDY */
260 s->stat &= ~(1 << 11); /* ROVR */
261 } else if (s->revision >= OMAP3_INTR_REV)
262 s->stat |= (1 << 7); /* AERR */
263 TRACE("DATA returns %04x", ret);
264 omap_i2c_fifo_run(s);
265 omap_i2c_interrupts_update(s);
267 case 0x20: /* I2C_SYSC */
268 TRACE("SYSC returns %04x", s->sysc);
270 case 0x24: /* I2C_CON */
271 TRACE("CON returns %04x", s->control);
273 case 0x28: /* I2C_OA / I2C_OA0 */
274 return s->own_addr[0];
275 case 0x2c: /* I2C_SA */
276 return s->slave_addr;
277 case 0x30: /* I2C_PSC */
279 case 0x34: /* I2C_SCLL */
281 case 0x38: /* I2C_SCLH */
283 case 0x3c: /* I2C_SYSTEST */
284 if (s->test & (1 << 15)) { /* ST_EN */
288 return s->test & ~0x300f;
289 case 0x40: /* I2C_BUFSTAT */
290 if (s->revision >= OMAP3_INTR_REV) {
291 switch (s->fifosize) {
292 case 8: ret = 0x0000; break;
293 case 16: ret = 0x4000; break;
294 case 32: ret = 0x8000; break;
295 case 64: ret = 0xc000; break;
296 default: ret = 0x0000; break;
298 ret |= ((s->fifolen) & 0x3f) << 8; /* RXSTAT */
299 ret |= (s->count_cur) & 0x3f; /* TXSTAT */
300 TRACE("BUFSTAT returns %04x", ret);
304 case 0x44: /* I2C_OA1 */
305 case 0x48: /* I2C_OA2 */
306 case 0x4c: /* I2C_OA3 */
307 if (s->revision >= OMAP3_INTR_REV)
308 return s->own_addr[(addr >> 2) & 3];
310 case 0x50: /* I2C_ACTOA */
311 if (s->revision >= OMAP3_INTR_REV)
312 return 0; /* TODO: determine accessed slave own address */
314 case 0x54: /* I2C_SBLOCK */
315 if (s->revision >= OMAP3_INTR_REV)
326 static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
329 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
330 int offset = addr & OMAP_MPUI_REG_MASK;
334 case 0x00: /* I2C_REV */
335 case 0x10: /* I2C_SYSS */
336 case 0x40: /* I2C_BUFSTAT */
337 case 0x50: /* I2C_ACTOA */
340 case 0x04: /* I2C_IE */
341 TRACE("IE = %04x", value);
342 if (s->revision >= OMAP3_INTR_REV)
343 s->mask = value & 0x63ff;
345 s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
346 omap_i2c_interrupts_update(s);
348 case 0x08: /* I2C_STAT */
349 if (s->revision < OMAP2_INTR_REV)
352 TRACE("STAT = %04x", value);
353 /* RRDY and XRDY are reset by hardware. (in all versions???) */
354 s->stat &= ~(value & (s->revision < OMAP3_INTR_REV ? 0x27 : 0x63e7));
355 omap_i2c_interrupts_update(s);
358 case 0x0c: /* I2C_IV / I2C_WE */
359 if (s->revision < OMAP3_INTR_REV)
362 s->we = value & 0x636f;
364 case 0x14: /* I2C_BUF */
365 TRACE("BUF = %04x", value);
366 if (s->revision < OMAP3_INTR_REV)
367 s->dma = value & 0x8080;
369 s->dma = value & 0xbfbf;
370 if ((value & (1 << 14)) /* RXFIFO_CLR */
371 || (value & (1 << 6))) /* TXFIFO_CLR */
374 if (value & (1 << 15)) /* RDMA_EN */
375 s->mask &= ~(1 << 3); /* RRDY_IE */
376 if (value & (1 << 7)) /* XDMA_EN */
377 s->mask &= ~(1 << 4); /* XRDY_IE */
379 case 0x18: /* I2C_CNT */
380 TRACE("CNT = %04x", value);
381 s->count = value; /* DCOUNT */
383 case 0x1c: /* I2C_DATA */
384 TRACE("DATA = %04x", value);
385 if (s->revision < OMAP3_INTR_REV) {
386 if (s->fifolen > 2) {
387 /* XXX: remote access (qualifier) error - what's that? */
390 if (s->control & (1 << 14)) { /* BE */
391 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
392 (uint8_t)((value >> 8) & 0xff);
393 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
394 (uint8_t)(value & 0xff);
396 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
397 (uint8_t)(value & 0xff);
398 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
399 (uint8_t)((value >> 8) & 0xff);
402 if (s->fifolen < s->fifosize) {
403 s->stat &= ~(1 << 7); /* AERR */
404 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
405 (uint8_t)(value & 0xff);
407 s->stat |= (1 << 7); /* AERR */
409 s->stat &= ~(1 << 10); /* XUDF */
410 omap_i2c_fifo_run(s);
411 omap_i2c_interrupts_update(s);
413 case 0x20: /* I2C_SYSC */
414 if (s->revision < OMAP2_INTR_REV) {
418 TRACE("SYSC = %04x", value);
421 else if (s->revision >= OMAP3_INTR_REV)
422 s->sysc = value & 0x031d;
424 case 0x24: /* I2C_CON */
425 TRACE("CON = %04x", value);
426 s->control = value & (s->revision < OMAP3_INTR_REV ? 0xcf87 : 0xbff3);
427 if (~value & (1 << 15)) { /* I2C_EN */
428 if (s->revision < OMAP2_INTR_REV)
432 if (s->revision >= OMAP3_INTR_REV && ((value >> 12) & 3) > 1) { /* OPMODE */
434 "%s: only FS and HS modes are supported\n",
438 if ((value & (1 << 10))) { /* MST */
439 if (value & 1) { /* STT */
440 nack = !!i2c_start_transfer(s->bus, s->slave_addr, /*SA*/
441 (~value >> 9) & 1); /*TRX*/
442 s->stat |= nack << 1; /* NACK */
443 s->control &= ~(1 << 0); /* STT */
446 s->control &= ~(1 << 1); /* STP */
448 s->count_cur = s->count;
449 omap_i2c_fifo_run(s);
451 omap_i2c_interrupts_update(s);
452 } else if (value & 2) { /* STP, but not STT */
453 i2c_end_transfer(s->bus);
454 s->control &= ~0x0602; /* MST | TRX | STP */
455 s->count_cur = s->count;
459 case 0x28: /* I2C_OA / I2C_OA0 */
460 TRACE("OA0 = %04x", value);
461 s->own_addr[0] = value & (s->revision < OMAP3_INTR_REV
463 /*i2c_set_slave_address(&s->slave[0],
464 value & (s->revision >= OMAP3_INTR_REV
465 && (s->control & 0x80)
468 case 0x2c: /* I2C_SA */
469 TRACE("SA = %04x", value);
470 s->slave_addr = value & 0x3ff;
472 case 0x30: /* I2C_PSC */
475 case 0x34: /* I2C_SCLL */
476 s->times[0] = value & (s->revision < OMAP3_INTR_REV
479 case 0x38: /* I2C_SCLH */
480 s->times[1] = value & (s->revision < OMAP3_INTR_REV
483 case 0x3c: /* I2C_SYSTEST */
484 value &= s->revision < OMAP3_INTR_REV ? 0xf805 : 0xf815;
485 if ((value & (1 << 15))) { /* ST_EN */
486 fprintf(stderr, "%s: System Test not supported\n",
488 s->test = (s->test & 0x0a) | value;
490 s->test = (s->test & 0x1f) | (value & 0xf800);
491 if (value & (1 << 11)) /* SBB */
492 if (s->revision >= OMAP2_INTR_REV) {
494 if (s->revision >= OMAP3_INTR_REV)
496 omap_i2c_interrupts_update(s);
499 case 0x44: /* I2C_OA1 */
500 case 0x48: /* I2C_OA2 */
501 case 0x4c: /* I2C_OA3 */
502 if (s->revision < OMAP3_INTR_REV)
505 addr = (addr >> 2) & 3;
506 TRACE("OA%d = %04x", (int)addr, value);
507 s->own_addr[addr] = value & 0x3ff;
508 /*i2c_set_slave_address(&s->slave[addr],
509 value & ((s->control & (0x80 >> addr))
513 case 0x54: /* I2C_SBLOCK */
514 if (s->revision < OMAP3_INTR_REV)
517 s->sblock = value & 0x0f;
526 static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr,
529 struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
530 int offset = addr & OMAP_MPUI_REG_MASK;
533 case 0x1c: /* I2C_DATA */
534 TRACE("DATA = %02x", value);
535 if (s->revision < OMAP3_INTR_REV && s->fifolen > 2) {
536 /* XXX: remote access (qualifier) error - what's that? */
539 if (s->fifolen < s->fifosize) {
540 s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
541 (uint8_t)(value & 0xff);
542 if (s->revision >= OMAP3_INTR_REV)
543 s->stat &= ~(1 << 7); /* AERR */
544 s->stat &= ~(1 << 10); /* XUDF */
545 omap_i2c_fifo_run(s);
546 } else if (s->revision >= OMAP3_INTR_REV)
547 s->stat |= (1 << 7); /* AERR */
548 omap_i2c_interrupts_update(s);
556 static CPUReadMemoryFunc *omap_i2c_readfn[] = {
557 omap_badwidth_read16,
559 omap_badwidth_read16,
562 static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
563 omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
565 omap_badwidth_write16,
568 static void omap_i2c_save_state(QEMUFile *f, void *opaque)
570 struct omap_i2c_s *s = (struct omap_i2c_s *)opaque;
572 /* TODO: slave setup(s) */
573 qemu_put_be16(f, s->mask);
574 qemu_put_be16(f, s->stat);
575 qemu_put_be16(f, s->we);
576 qemu_put_be16(f, s->dma);
577 qemu_put_be16(f, s->count);
578 qemu_put_sbe32(f, s->count_cur);
579 qemu_put_be16(f, s->sysc);
580 qemu_put_be16(f, s->control);
581 qemu_put_be16(f, s->own_addr[0]);
582 qemu_put_be16(f, s->own_addr[1]);
583 qemu_put_be16(f, s->own_addr[2]);
584 qemu_put_be16(f, s->own_addr[3]);
585 qemu_put_be16(f, s->slave_addr);
586 qemu_put_byte(f, s->sblock);
587 qemu_put_byte(f, s->divider);
588 qemu_put_be16(f, s->times[0]);
589 qemu_put_be16(f, s->times[1]);
590 qemu_put_be16(f, s->test);
591 qemu_put_sbe32(f, s->fifostart);
592 qemu_put_sbe32(f, s->fifolen);
593 qemu_put_sbe32(f, s->fifosize);
594 qemu_put_buffer(f, s->fifo, sizeof(s->fifo));
597 static int omap_i2c_load_state(QEMUFile *f, void *opaque, int version_id)
599 struct omap_i2c_s *s = (struct omap_i2c_s *)opaque;
604 /* TODO: slave setup(s) */
605 s->mask = qemu_get_be16(f);
606 s->stat = qemu_get_be16(f);
607 s->we = qemu_get_be16(f);
608 s->dma = qemu_get_be16(f);
609 s->count = qemu_get_be16(f);
610 s->count_cur = qemu_get_sbe32(f);
611 s->sysc = qemu_get_be16(f);
612 s->control = qemu_get_be16(f);
613 s->own_addr[0] = qemu_get_be16(f);
614 s->own_addr[1] = qemu_get_be16(f);
615 s->own_addr[2] = qemu_get_be16(f);
616 s->own_addr[3] = qemu_get_be16(f);
617 s->slave_addr = qemu_get_be16(f);
618 s->sblock = qemu_get_byte(f);
619 s->divider = qemu_get_byte(f);
620 s->times[0] = qemu_get_be16(f);
621 s->times[1] = qemu_get_be16(f);
622 s->test = qemu_get_be16(f);
623 s->fifostart = qemu_get_sbe32(f);
624 s->fifolen = qemu_get_sbe32(f);
625 s->fifosize = qemu_get_sbe32(f);
626 qemu_get_buffer(f, s->fifo, sizeof(s->fifo));
628 omap_i2c_interrupts_update(s);
633 static struct omap_i2c_s *omap_i2c_common_init(uint8_t rev, int fifosize,
634 qemu_irq irq, qemu_irq *dma)
636 struct omap_i2c_s *s = (struct omap_i2c_s *)
637 qemu_mallocz(sizeof(struct omap_i2c_s));
639 if (fifosize > I2C_MAX_FIFO_SIZE) {
640 fprintf(stderr, "%s: maximum FIFO size is %d (tried to use %d)\n",
641 __FUNCTION__, I2C_MAX_FIFO_SIZE, fifosize);
648 s->bus = i2c_init_bus(NULL, "i2c");
649 s->fifosize = fifosize;
654 struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
655 qemu_irq irq, qemu_irq *dma, omap_clk clk)
657 struct omap_i2c_s *s = omap_i2c_common_init(0x11, 4, irq, dma);
659 cpu_register_physical_memory(base, 0x800,
660 cpu_register_io_memory(0, omap_i2c_readfn,
661 omap_i2c_writefn, s));
665 struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
666 qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
668 struct omap_i2c_s *s = omap_i2c_common_init(0x34, 4, irq, dma);
670 omap_l4_attach(ta, 0, l4_register_io_memory(0, omap_i2c_readfn,
671 omap_i2c_writefn, s));
675 struct omap_i2c_s *omap3_i2c_init(struct omap_target_agent_s *ta,
676 qemu_irq irq, qemu_irq *dma,
677 omap_clk fclk, omap_clk iclk,
680 struct omap_i2c_s *s;
682 if (fifosize != 8 && fifosize != 16 && fifosize != 32 && fifosize != 64) {
683 fprintf(stderr, "%s: unsupported FIFO depth specified (%d)\n",
684 __FUNCTION__, fifosize);
687 s = omap_i2c_common_init(OMAP3_INTR_REV, fifosize, irq, dma);
689 omap_l4_attach(ta, 0, l4_register_io_memory(0, omap_i2c_readfn,
690 omap_i2c_writefn, s));
691 register_savevm("omap3_i2c", (ta->base >> 12) & 0xff, 0,
692 omap_i2c_save_state, omap_i2c_load_state, s);
696 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)