2
* TI OMAP on-chip I2C controller. Only "new I2C" mode supported.
4
* Copyright (C) 2007 Andrzej Zaborowski <balrog@zabor.org>
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.
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.
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/>.
20
#include "hw/i2c/i2c.h"
21
#include "hw/arm/omap.h"
22
#include "hw/sysbus.h"
24
#define TYPE_OMAP_I2C "omap_i2c"
25
#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
27
#define I2C_MAX_FIFO_SIZE (1 << 6)
28
#define I2C_FIFO_SIZE_MASK ((I2C_MAX_FIFO_SIZE) - 1)
30
typedef struct OMAPI2CState {
31
SysBusDevice parent_obj;
55
uint8_t fifo[I2C_MAX_FIFO_SIZE];
58
/* I2C controller revision register values */
59
#define OMAP1_INTR_REV 0x11
60
#define OMAP2_INTR_REV 0x34
61
#define OMAP3_INTR_REV 0x3c
62
#define OMAP3630_INTR_REV 0x40
64
static void omap_i2c_interrupts_update(OMAPI2CState *s)
66
qemu_set_irq(s->irq, s->stat & s->mask);
67
if ((s->dma >> 15) & 1) /* RDMA_EN */
68
qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
69
if ((s->dma >> 7) & 1) /* XDMA_EN */
70
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
73
static void omap_i2c_fifo_run(OMAPI2CState *s)
77
if (!i2c_bus_busy(s->bus))
80
if ((s->control >> 2) & 1) { /* RM */
81
if ((s->control >> 1) & 1) { /* STP */
82
i2c_end_transfer(s->bus);
83
s->control &= ~(1 << 1); /* STP */
84
s->count_cur = s->count;
86
} else if ((s->control >> 9) & 1) { /* TRX */
87
while (ack && s->fifolen) {
88
ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
89
s->fifostart &= I2C_FIFO_SIZE_MASK;
93
s->stat |= 1 << 4; /* XRDY */
95
for (i = 0; i < 4; i++)
96
s->fifo[(s->fifostart + i) & I2C_FIFO_SIZE_MASK] =
99
s->stat |= 1 << 3; /* RRDY */
102
if ((s->control >> 9) & 1) { /* TRX */
103
for (; ack && s->count_cur && s->fifolen; s->count_cur--) {
104
ack = (i2c_send(s->bus, s->fifo[s->fifostart++]) >= 0);
105
s->fifostart &= I2C_FIFO_SIZE_MASK;
108
s->stat &= ~0x4410; /* XDR | XUDF | XRDY */
109
if (ack && s->count_cur) { /* send more? */
110
/* we know that FIFO is empty */
111
if (s->revision < OMAP3_INTR_REV)
112
s->stat |= 1 << 4; /* XRDY */
114
if (s->count_cur > (s->dma & 0x3f)) /* XTRSH */
115
s->stat |= 1 << 4; /* XRDY */
117
s->stat |= 1 << 14; /* XDR */
120
if (!s->count_cur) /* everything sent? */
121
s->stat |= 1 << 2; /* ARDY */
123
for (; s->count_cur && s->fifolen < s->fifosize; s->count_cur--) {
124
i = i2c_recv(s->bus);
125
if (i < 0) break; /* stop receiving if nothing to receive */
126
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
129
s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
131
if (s->revision < OMAP3_INTR_REV)
132
s->stat |= 1 << 3; /* RRDY */
134
if (s->fifolen > ((s->dma >> 8) & 0x3f)) /* RTRSH */
135
s->stat |= 1 << 3; /* RRDY */
137
s->stat |= 1 << 13; /* RDR */
139
} else if (!s->count_cur && (s->control & 2)) /* STP */
140
s->stat |= 1 << 2; /* ARDY */
143
if ((s->control >> 1) & 1) { /* STP */
144
i2c_end_transfer(s->bus);
145
s->control &= ~0x0602; /* MST | TRX | STP */
146
s->count_cur = s->count;
151
s->stat |= (!ack) << 1; /* NACK */
153
s->control &= ~(1 << 1); /* STP */
156
static void omap_i2c_reset(DeviceState *dev)
158
OMAPI2CState *s = OMAP_I2C(dev);
176
static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
178
OMAPI2CState *s = opaque;
179
int offset = addr & OMAP_MPUI_REG_MASK;
183
case 0x00: /* I2C_REV */
184
return s->revision; /* REV */
186
case 0x04: /* I2C_IE */
189
case 0x08: /* I2C_STAT */
190
return s->stat | (i2c_bus_busy(s->bus) << 12);
192
case 0x0c: /* I2C_IV */
193
if (s->revision >= OMAP2_INTR_REV)
195
ret = ffs(s->stat & s->mask);
197
s->stat ^= 1 << (ret - 1);
198
omap_i2c_interrupts_update(s);
201
case 0x10: /* I2C_SYSS */
202
return (s->control >> 15) & 1; /* I2C_EN */
204
case 0x14: /* I2C_BUF */
207
case 0x18: /* I2C_CNT */
208
return s->count_cur; /* DCOUNT */
210
case 0x1c: /* I2C_DATA */
213
if (s->revision < OMAP3_INTR_REV) {
214
if (s->control & (1 << 14)) /* BE */
215
ret = (((uint16_t)s->fifo[s->fifostart]) << 8)
216
| s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK];
218
ret = (((uint16_t)s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK]) << 8)
219
| s->fifo[s->fifostart];
220
s->fifostart = (s->fifostart + 2) & I2C_FIFO_SIZE_MASK;
221
if (s->fifolen == 1) {
222
s->stat |= 1 << 15; /* SBD */
227
s->stat &= ~(1 << 3); /* RRDY */
228
s->stat |= 1 << 2; /* ARDY */
231
s->stat &= ~(1 << 7); /* AERR */
232
ret = s->fifo[s->fifostart++];
233
s->fifostart &= I2C_FIFO_SIZE_MASK;
235
if (s->fifolen <= ((s->dma >> 8) & 0x3f)) {
236
s->stat &= ~(1 << 3); /* RRDY */
237
s->stat |= 1 << 13; /* RDR */
240
s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
241
s->stat |= 1 << 2; /* ARDY */
244
s->stat &= ~(1 << 11); /* ROVR */
245
} else if (s->revision >= OMAP3_INTR_REV)
246
s->stat |= (1 << 7); /* AERR */
247
omap_i2c_fifo_run(s);
248
omap_i2c_interrupts_update(s);
251
case 0x20: /* I2C_SYSC */
254
case 0x24: /* I2C_CON */
257
case 0x28: /* I2C_OA */
260
case 0x2c: /* I2C_SA */
263
case 0x30: /* I2C_PSC */
266
case 0x34: /* I2C_SCLL */
269
case 0x38: /* I2C_SCLH */
272
case 0x3c: /* I2C_SYSTEST */
273
if (s->test & (1 << 15)) { /* ST_EN */
277
return s->test & ~0x300f;
284
static void omap_i2c_write(void *opaque, hwaddr addr,
287
OMAPI2CState *s = opaque;
288
int offset = addr & OMAP_MPUI_REG_MASK;
292
case 0x00: /* I2C_REV */
293
case 0x0c: /* I2C_IV */
294
case 0x10: /* I2C_SYSS */
298
case 0x04: /* I2C_IE */
299
s->mask = value & (s->revision < OMAP2_INTR_REV ? 0x1f : 0x3f);
302
case 0x08: /* I2C_STAT */
303
if (s->revision < OMAP2_INTR_REV) {
308
/* RRDY and XRDY are reset by hardware. (in all versions???) */
309
s->stat &= ~(value & 0x27);
310
omap_i2c_interrupts_update(s);
313
case 0x14: /* I2C_BUF */
314
s->dma = value & 0x8080;
315
if (value & (1 << 15)) /* RDMA_EN */
316
s->mask &= ~(1 << 3); /* RRDY_IE */
317
if (value & (1 << 7)) /* XDMA_EN */
318
s->mask &= ~(1 << 4); /* XRDY_IE */
321
case 0x18: /* I2C_CNT */
322
s->count = value; /* DCOUNT */
325
case 0x1c: /* I2C_DATA */
326
if (s->revision < OMAP3_INTR_REV) {
327
if (s->fifolen > 2) {
328
/* XXX: remote access (qualifier) error - what's that? */
331
if (s->control & (1 << 14)) { /* BE */
332
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
333
(uint8_t)((value >> 8) & 0xff);
334
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
335
(uint8_t)(value & 0xff);
337
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
338
(uint8_t)(value & 0xff);
339
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
340
(uint8_t)((value >> 8) & 0xff);
343
if (s->fifolen < s->fifosize) {
344
s->stat &= ~(1 << 7); /* AERR */
345
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
346
(uint8_t)(value & 0xff);
348
s->stat |= (1 << 7); /* AERR */
350
s->stat &= ~(1 << 10); /* XUDF */
351
omap_i2c_fifo_run(s);
352
omap_i2c_interrupts_update(s);
355
case 0x20: /* I2C_SYSC */
356
if (s->revision < OMAP2_INTR_REV) {
362
omap_i2c_reset(DEVICE(s));
366
case 0x24: /* I2C_CON */
367
s->control = value & 0xcf87;
368
if (~value & (1 << 15)) { /* I2C_EN */
369
if (s->revision < OMAP2_INTR_REV) {
370
omap_i2c_reset(DEVICE(s));
374
if ((value & (1 << 10))) { /* MST */
375
if (value & 1) { /* STT */
376
nack = !!i2c_start_transfer(s->bus, s->addr[1], /*SA*/
377
(~value >> 9) & 1); /* TRX */
378
s->stat |= nack << 1; /* NACK */
379
s->control &= ~(1 << 0); /* STT */
382
s->control &= ~(1 << 1); /* STP */
384
s->count_cur = s->count;
385
omap_i2c_fifo_run(s);
387
omap_i2c_interrupts_update(s);
388
} else if (value & 2) { /* STP, but not STT */
389
i2c_end_transfer(s->bus);
390
s->control &= ~0x0602; /* MST | TRX | STP */
391
s->count_cur = s->count;
396
case 0x28: /* I2C_OA */
397
s->addr[0] = value & 0x3ff;
400
case 0x2c: /* I2C_SA */
401
s->addr[1] = value & 0x3ff;
404
case 0x30: /* I2C_PSC */
408
case 0x34: /* I2C_SCLL */
412
case 0x38: /* I2C_SCLH */
416
case 0x3c: /* I2C_SYSTEST */
417
s->test = value & 0xf80f;
418
if (value & (1 << 11)) /* SBB */
419
if (s->revision >= OMAP2_INTR_REV) {
421
omap_i2c_interrupts_update(s);
423
if (value & (1 << 15)) /* ST_EN */
424
fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
433
static void omap_i2c_writeb(void *opaque, hwaddr addr,
436
OMAPI2CState *s = opaque;
437
int offset = addr & OMAP_MPUI_REG_MASK;
440
case 0x1c: /* I2C_DATA */
441
if (s->revision < OMAP3_INTR_REV && s->fifolen > 2) {
442
/* XXX: remote access (qualifier) error - what's that? */
445
if (s->fifolen < s->fifosize) {
446
s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
447
(uint8_t)(value & 0xff);
448
if (s->revision >= OMAP3_INTR_REV)
449
s->stat &= ~(1 << 7); /* AERR */
450
s->stat &= ~(1 << 10); /* XUDF */
451
omap_i2c_fifo_run(s);
452
} else if (s->revision >= OMAP3_INTR_REV)
453
s->stat |= (1 << 7); /* AERR */
454
omap_i2c_interrupts_update(s);
462
static const MemoryRegionOps omap_i2c_ops = {
465
omap_badwidth_read16,
467
omap_badwidth_read16,
470
omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
472
omap_badwidth_write16,
475
.endianness = DEVICE_NATIVE_ENDIAN,
478
static int omap_i2c_init(SysBusDevice *sbd)
480
DeviceState *dev = DEVICE(sbd);
481
OMAPI2CState *s = OMAP_I2C(dev);
484
hw_error("omap_i2c: fclk not connected\n");
486
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
487
/* Note that OMAP1 doesn't have a separate interface clock */
488
hw_error("omap_i2c: iclk not connected\n");
490
sysbus_init_irq(sbd, &s->irq);
491
sysbus_init_irq(sbd, &s->drq[0]);
492
sysbus_init_irq(sbd, &s->drq[1]);
493
memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
494
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
495
sysbus_init_mmio(sbd, &s->iomem);
496
s->bus = i2c_init_bus(dev, NULL);
500
static Property omap_i2c_properties[] = {
501
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
502
DEFINE_PROP_UINT32("fifo-size", OMAPI2CState, fifosize, 4),
503
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
504
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
505
DEFINE_PROP_END_OF_LIST(),
508
static void omap_i2c_class_init(ObjectClass *klass, void *data)
510
DeviceClass *dc = DEVICE_CLASS(klass);
511
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
512
k->init = omap_i2c_init;
513
dc->props = omap_i2c_properties;
514
dc->reset = omap_i2c_reset;
517
static const TypeInfo omap_i2c_info = {
518
.name = TYPE_OMAP_I2C,
519
.parent = TYPE_SYS_BUS_DEVICE,
520
.instance_size = sizeof(OMAPI2CState),
521
.class_init = omap_i2c_class_init,
524
static void omap_i2c_register_types(void)
526
type_register_static(&omap_i2c_info);
529
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
531
OMAPI2CState *s = OMAP_I2C(omap_i2c);
535
type_init(omap_i2c_register_types)