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, see <http://www.gnu.org/licenses/>.
21
#include "hw/i2c/i2c.h"
22
#include "hw/arm/omap.h"
23
#include "hw/sysbus.h"
25
#define TYPE_OMAP_I2C "omap_i2c"
26
#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
28
#define I2C_MAX_FIFO_SIZE (1 << 6)
29
#define I2C_FIFO_SIZE_MASK ((I2C_MAX_FIFO_SIZE) - 1)
31
typedef struct OMAPI2CState {
32
SysBusDevice parent_obj;
60
uint8_t fifo[I2C_MAX_FIFO_SIZE];
63
/* I2C controller revision register values */
64
#define OMAP1_INTR_REV 0x11
65
#define OMAP2_INTR_REV 0x34
66
#define OMAP3_INTR_REV 0x3c
67
#define OMAP3630_INTR_REV 0x40
69
static void omap_i2c_interrupts_update(OMAPI2CState *s)
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(OMAPI2CState *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
for (; ack && s->count_cur && s->fifolen; s->count_cur--) {
109
ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
110
s->fifostart &= I2C_FIFO_SIZE_MASK;
113
s->stat &= ~0x4410; /* XDR | XUDF | XRDY */
114
if (ack && s->count_cur) { /* send more? */
115
/* we know that FIFO is empty */
116
if (s->revision < OMAP3_INTR_REV)
117
s->stat |= 1 << 4; /* XRDY */
119
if (s->count_cur > (s->dma & 0x3f)) /* XTRSH */
120
s->stat |= 1 << 4; /* XRDY */
122
s->stat |= 1 << 14; /* XDR */
125
if (!s->count_cur) /* everything sent? */
126
s->stat |= 1 << 2; /* ARDY */
128
for (; s->count_cur && s->fifolen < s->fifosize; s->count_cur--) {
129
i = i2c_recv(s->bus);
130
if (i < 0) break; /* stop receiving if nothing to receive */
131
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
134
s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
136
if (s->revision < OMAP3_INTR_REV)
137
s->stat |= 1 << 3; /* RRDY */
139
if (s->fifolen > ((s->dma >> 8) & 0x3f)) /* RTRSH */
140
s->stat |= 1 << 3; /* RRDY */
142
s->stat |= 1 << 13; /* RDR */
144
} else if (!s->count_cur && (s->control & 2)) /* STP */
145
s->stat |= 1 << 2; /* ARDY */
148
i2c_end_transfer(s->bus);
149
if ((s->control >> 1) & 1) { /* STP */
150
s->control &= ~0x0602; /* MST | TRX | STP */
151
s->count_cur = s->count;
156
s->stat |= (!ack) << 1; /* NACK */
158
s->control &= ~(1 << 1); /* STP */
161
static void omap_i2c_reset(DeviceState *dev)
163
OMAPI2CState *s = OMAP_I2C(dev);
186
i2c_end_transfer(s->bus);
189
static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
191
OMAPI2CState *s = opaque;
192
int offset = addr & OMAP_MPUI_REG_MASK;
196
case 0x00: /* I2C_REV */
197
return s->revision; /* REV */
199
case 0x04: /* I2C_IE */
202
case 0x08: /* I2C_STAT */
203
return s->stat | (i2c_bus_busy(s->bus) << 12);
205
case 0x0c: /* I2C_IV / I2C_WE */
206
if (s->revision >= OMAP3_INTR_REV)
208
if (s->revision >= OMAP2_INTR_REV)
210
ret = ffs(s->stat & s->mask);
212
s->stat ^= 1 << (ret - 1);
213
omap_i2c_interrupts_update(s);
216
case 0x10: /* I2C_SYSS */
217
return (s->control >> 15) & 1; /* I2C_EN */
219
case 0x14: /* I2C_BUF */
222
case 0x18: /* I2C_CNT */
223
return s->count_cur; /* DCOUNT */
225
case 0x1c: /* I2C_DATA */
228
if (s->revision < OMAP3_INTR_REV) {
229
if (s->control & (1 << 14)) /* BE */
230
ret = (((uint16_t)s->fifo[s->fifostart]) << 8)
231
| s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK];
233
ret = (((uint16_t)s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK]) << 8)
234
| s->fifo[s->fifostart];
235
s->fifostart = (s->fifostart + 2) & I2C_FIFO_SIZE_MASK;
236
if (s->fifolen == 1) {
237
s->stat |= 1 << 15; /* SBD */
242
s->stat &= ~(1 << 3); /* RRDY */
243
s->stat |= 1 << 2; /* ARDY */
246
s->stat &= ~(1 << 7); /* AERR */
247
ret = s->fifo[s->fifostart++];
248
s->fifostart &= I2C_FIFO_SIZE_MASK;
250
if (s->fifolen <= ((s->dma >> 8) & 0x3f)) {
251
s->stat &= ~(1 << 3); /* RRDY */
252
s->stat |= 1 << 13; /* RDR */
255
s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
256
s->stat |= 1 << 2; /* ARDY */
259
s->stat &= ~(1 << 11); /* ROVR */
260
} else if (s->revision >= OMAP3_INTR_REV)
261
s->stat |= (1 << 7); /* AERR */
262
omap_i2c_fifo_run(s);
263
omap_i2c_interrupts_update(s);
266
case 0x20: /* I2C_SYSC */
269
case 0x24: /* I2C_CON */
272
case 0x28: /* I2C_OA / I2C_OA0 */
273
return s->own_addr[0];
275
case 0x2c: /* I2C_SA */
276
return s->slave_addr;
278
case 0x30: /* I2C_PSC */
281
case 0x34: /* I2C_SCLL */
284
case 0x38: /* I2C_SCLH */
287
case 0x3c: /* I2C_SYSTEST */
288
if (s->test & (1 << 15)) { /* ST_EN */
292
return s->test & ~0x300f;
293
case 0x40: /* I2C_BUFSTAT */
294
if (s->revision >= OMAP3_INTR_REV) {
295
switch (s->fifosize) {
296
case 8: ret = 0x0000; break;
297
case 16: ret = 0x4000; break;
298
case 32: ret = 0x8000; break;
299
case 64: ret = 0xc000; break;
300
default: ret = 0x0000; break;
302
ret |= ((s->fifolen) & 0x3f) << 8; /* RXSTAT */
303
ret |= (s->count_cur) & 0x3f; /* TXSTAT */
307
case 0x44: /* I2C_OA1 */
308
case 0x48: /* I2C_OA2 */
309
case 0x4c: /* I2C_OA3 */
310
if (s->revision >= OMAP3_INTR_REV)
311
return s->own_addr[(addr >> 2) & 3];
313
case 0x50: /* I2C_ACTOA */
314
if (s->revision >= OMAP3_INTR_REV)
315
return 0; /* TODO: determine accessed slave own address */
317
case 0x54: /* I2C_SBLOCK */
318
if (s->revision >= OMAP3_INTR_REV)
329
static uint32_t omap_i2c_readb(void *opaque, hwaddr addr)
331
OMAPI2CState *s = opaque;
332
int offset = addr & OMAP_MPUI_REG_MASK;
336
case 0x1c: /* I2C_DATA */
339
if (s->revision < OMAP3_INTR_REV) {
340
if (s->control & (1 << 14)) /* BE */
341
ret = (((uint8_t)s->fifo[s->fifostart]) << 8)
342
| s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK];
344
ret = (((uint8_t)s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK]) << 8)
345
| s->fifo[s->fifostart];
346
s->fifostart = (s->fifostart + 2) & I2C_FIFO_SIZE_MASK;
347
if (s->fifolen == 1) {
348
s->stat |= 1 << 15; /* SBD */
353
s->stat &= ~(1 << 3); /* RRDY */
354
s->stat |= 1 << 2; /* ARDY */
357
s->stat &= ~(1 << 7); /* AERR */
358
ret = (uint8_t)s->fifo[s->fifostart++];
359
s->fifostart &= I2C_FIFO_SIZE_MASK;
361
if (s->fifolen <= ((s->dma >> 8) & 0x3f)) {
362
s->stat &= ~(1 << 3); /* RRDY */
363
s->stat |= 1 << 13; /* RDR */
366
s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
367
s->stat |= 1 << 2; /* ARDY */
370
s->stat &= ~(1 << 11); /* ROVR */
371
} else if (s->revision >= OMAP3_INTR_REV)
372
s->stat |= (1 << 7); /* AERR */
373
omap_i2c_fifo_run(s);
374
omap_i2c_interrupts_update(s);
384
static void omap_i2c_write(void *opaque, hwaddr addr,
387
OMAPI2CState *s = opaque;
388
int offset = addr & OMAP_MPUI_REG_MASK;
392
case 0x00: /* I2C_REV */
393
case 0x10: /* I2C_SYSS */
394
case 0x40: /* I2C_BUFSTAT */
395
case 0x50: /* I2C_ACTOA */
398
case 0x04: /* I2C_IE */
399
if (s->revision < OMAP2_INTR_REV) {
400
s->mask = value & 0x1f;
401
} else if (s->revision < OMAP3_INTR_REV) {
402
s->mask = value & 0x3f;
403
} else if (s->revision == OMAP3_INTR_REV) {
404
s->mask = value & 0x63ff;
405
} else { /* omap3630 */
406
s->mask = value & 0x6fff;
408
omap_i2c_interrupts_update(s);
410
case 0x08: /* I2C_STAT */
411
if (s->revision < OMAP2_INTR_REV)
414
/* RRDY and XRDY are reset by hardware. (in all versions???) */
415
if (s->revision < OMAP3_INTR_REV) {
417
} else if (s->revision == OMAP3_INTR_REV) {
419
} else { /* omap3630 */
423
omap_i2c_interrupts_update(s);
427
case 0x0c: /* I2C_IV / I2C_WE */
428
if (s->revision < OMAP3_INTR_REV) {
430
} else if (s->revision == OMAP3_INTR_REV) {
431
s->we = value & 0x636f;
432
} else { /* omap3630 */
433
s->we = value & 0x6f6f;
437
case 0x14: /* I2C_BUF */
438
if (s->revision < OMAP3_INTR_REV)
439
s->dma = value & 0x8080;
441
s->dma = value & 0xbfbf;
442
if ((value & (1 << 14)) /* RXFIFO_CLR */
443
|| (value & (1 << 6))) /* TXFIFO_CLR */
446
if (value & (1 << 15)) /* RDMA_EN */
447
s->mask &= ~(1 << 3); /* RRDY_IE */
448
if (value & (1 << 7)) /* XDMA_EN */
449
s->mask &= ~(1 << 4); /* XRDY_IE */
452
case 0x18: /* I2C_CNT */
453
s->count = value; /* DCOUNT */
456
case 0x1c: /* I2C_DATA */
457
if (s->revision < OMAP3_INTR_REV) {
458
if (s->fifolen > 2) {
459
/* XXX: remote access (qualifier) error - what's that? */
462
if (s->control & (1 << 14)) { /* BE */
463
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
464
(uint8_t)((value >> 8) & 0xff);
465
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
466
(uint8_t)(value & 0xff);
468
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
469
(uint8_t)(value & 0xff);
470
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
471
(uint8_t)((value >> 8) & 0xff);
474
if (s->fifolen < s->fifosize) {
475
s->stat &= ~(1 << 7); /* AERR */
476
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
477
(uint8_t)(value & 0xff);
479
s->stat |= (1 << 7); /* AERR */
481
s->stat &= ~(1 << 10); /* XUDF */
482
omap_i2c_fifo_run(s);
483
omap_i2c_interrupts_update(s);
486
case 0x20: /* I2C_SYSC */
487
if (s->revision < OMAP2_INTR_REV) {
493
omap_i2c_reset(DEVICE(s));
494
} else if (s->revision >= OMAP3_INTR_REV) {
495
s->sysc = value & 0x031d;
499
case 0x24: /* I2C_CON */
500
s->control = value & (s->revision < OMAP3_INTR_REV ? 0xcf87 : 0xbff3);
501
if (~value & (1 << 15)) { /* I2C_EN */
502
if (s->revision < OMAP2_INTR_REV) {
503
omap_i2c_reset(DEVICE(s));
507
if (s->revision >= OMAP3_INTR_REV && ((value >> 12) & 3) > 1) { /* OPMODE */
509
"%s: only FS and HS modes are supported\n",
513
if ((value & (1 << 10))) { /* MST */
514
if (value & 1) { /* STT */
515
nack = !!i2c_start_transfer(s->bus, s->slave_addr, /*SA*/
516
(~value >> 9) & 1); /* TRX */
517
s->stat |= nack << 1; /* NACK */
518
s->control &= ~(1 << 0); /* STT */
521
s->control &= ~(1 << 1); /* STP */
523
s->count_cur = s->count;
524
omap_i2c_fifo_run(s);
526
omap_i2c_interrupts_update(s);
527
} else if (value & 2) { /* STP, but not STT */
528
i2c_end_transfer(s->bus);
529
s->control &= ~0x0602; /* MST | TRX | STP */
530
s->count_cur = s->count;
534
case 0x28: /* I2C_OA / I2C_OA0 */
535
s->own_addr[0] = value & (s->revision < OMAP3_INTR_REV
537
/*i2c_set_slave_address(&s->slave[0],
538
value & (s->revision >= OMAP3_INTR_REV
539
&& (s->control & 0x80)
543
case 0x2c: /* I2C_SA */
544
s->slave_addr = value & 0x3ff;
547
case 0x30: /* I2C_PSC */
551
case 0x34: /* I2C_SCLL */
552
s->times[0] = value & (s->revision < OMAP3_INTR_REV ? 0xff : 0xffff);
555
case 0x38: /* I2C_SCLH */
556
s->times[1] = value & (s->revision < OMAP3_INTR_REV ? 0xff : 0xffff);
559
case 0x3c: /* I2C_SYSTEST */
560
if (s->revision < OMAP3_INTR_REV) {
562
} else if (s->revision == OMAP3_INTR_REV) {
564
} else { /* omap3630 */
565
value = (value & 0xf835) | 0x1c00;
567
if ((value & (1 << 15))) { /* ST_EN */
568
fprintf(stderr, "%s: System Test not supported\n",
570
s->test = (s->test & 0x0a) | value;
573
s->test = (s->test & 0x1f) | value;
575
if (value & (1 << 11)) { /* SBB */
576
if (s->revision >= OMAP2_INTR_REV) {
578
if (s->revision >= OMAP3_INTR_REV) {
580
if (s->revision > OMAP3_INTR_REV) {
584
omap_i2c_interrupts_update(s);
589
case 0x44: /* I2C_OA1 */
590
case 0x48: /* I2C_OA2 */
591
case 0x4c: /* I2C_OA3 */
592
if (s->revision < OMAP3_INTR_REV)
595
addr = (addr >> 2) & 3;
596
s->own_addr[addr] = value & 0x3ff;
597
/*i2c_set_slave_address(&s->slave[addr],
598
value & ((s->control & (0x80 >> addr))
602
case 0x54: /* I2C_SBLOCK */
603
if (s->revision < OMAP3_INTR_REV)
606
s->sblock = value & 0x0f;
615
static void omap_i2c_writeb(void *opaque, hwaddr addr,
618
OMAPI2CState *s = opaque;
619
int offset = addr & OMAP_MPUI_REG_MASK;
622
case 0x1c: /* I2C_DATA */
623
if (s->revision < OMAP3_INTR_REV && s->fifolen > 2) {
624
/* XXX: remote access (qualifier) error - what's that? */
627
if (s->fifolen < s->fifosize) {
628
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
629
(uint8_t)(value & 0xff);
630
if (s->revision >= OMAP3_INTR_REV)
631
s->stat &= ~(1 << 7); /* AERR */
632
s->stat &= ~(1 << 10); /* XUDF */
633
omap_i2c_fifo_run(s);
634
} else if (s->revision >= OMAP3_INTR_REV)
635
s->stat |= (1 << 7); /* AERR */
636
omap_i2c_interrupts_update(s);
644
static const MemoryRegionOps omap_i2c_ops = {
649
omap_badwidth_read16,
652
omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
654
omap_badwidth_write16,
657
.endianness = DEVICE_NATIVE_ENDIAN,
660
static int omap_i2c_bus_post_load(void *opaque, int version_id)
662
OMAPI2CState *s = opaque;
663
omap_i2c_interrupts_update(s);
667
static const VMStateDescription vmstate_omap_i2c = {
670
.minimum_version_id = 1,
671
.post_load = omap_i2c_bus_post_load,
672
.fields = (VMStateField[]) {
673
VMSTATE_UINT16(mask, OMAPI2CState),
674
VMSTATE_UINT16(stat, OMAPI2CState),
675
VMSTATE_UINT16(we, OMAPI2CState),
676
VMSTATE_UINT16(dma, OMAPI2CState),
677
VMSTATE_UINT16(count, OMAPI2CState),
678
VMSTATE_INT32(count_cur, OMAPI2CState),
679
VMSTATE_UINT16(sysc, OMAPI2CState),
680
VMSTATE_UINT16(control, OMAPI2CState),
681
VMSTATE_UINT16_ARRAY(own_addr, OMAPI2CState, 4),
682
VMSTATE_UINT16(slave_addr, OMAPI2CState),
683
VMSTATE_UINT8(sblock, OMAPI2CState),
684
VMSTATE_UINT8(divider, OMAPI2CState),
685
VMSTATE_UINT16_ARRAY(times, OMAPI2CState, 2),
686
VMSTATE_UINT16(test, OMAPI2CState),
687
VMSTATE_INT32(fifostart, OMAPI2CState),
688
VMSTATE_INT32(fifolen, OMAPI2CState),
689
VMSTATE_UINT8_ARRAY(fifo, OMAPI2CState, I2C_MAX_FIFO_SIZE),
690
VMSTATE_END_OF_LIST()
694
static int omap_i2c_init(SysBusDevice *sbd)
696
DeviceState *dev = DEVICE(sbd);
697
OMAPI2CState *s = OMAP_I2C(dev);
700
hw_error("omap_i2c: fclk not connected\n");
702
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
703
/* Note that OMAP1 doesn't have a separate interface clock */
704
hw_error("omap_i2c: iclk not connected\n");
706
sysbus_init_irq(sbd, &s->irq);
707
sysbus_init_irq(sbd, &s->drq[0]);
708
sysbus_init_irq(sbd, &s->drq[1]);
709
memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
710
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
711
sysbus_init_mmio(sbd, &s->iomem);
712
s->bus = i2c_init_bus(dev, NULL);
716
static Property omap_i2c_properties[] = {
717
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
718
DEFINE_PROP_UINT32("fifo-size", OMAPI2CState, fifosize, 4),
719
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
720
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
721
DEFINE_PROP_END_OF_LIST(),
724
static void omap_i2c_class_init(ObjectClass *klass, void *data)
726
DeviceClass *dc = DEVICE_CLASS(klass);
727
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
728
k->init = omap_i2c_init;
729
dc->props = omap_i2c_properties;
730
dc->reset = omap_i2c_reset;
731
dc->vmsd = &vmstate_omap_i2c;
734
static const TypeInfo omap_i2c_info = {
735
.name = TYPE_OMAP_I2C,
736
.parent = TYPE_SYS_BUS_DEVICE,
737
.instance_size = sizeof(OMAPI2CState),
738
.class_init = omap_i2c_class_init,
741
static void omap_i2c_register_types(void)
743
type_register_static(&omap_i2c_info);
746
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
748
OMAPI2CState *s = OMAP_I2C(omap_i2c);
752
type_init(omap_i2c_register_types)