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
typedef struct OMAPI2CState {
28
SysBusDevice parent_obj;
54
#define OMAP2_INTR_REV 0x34
55
#define OMAP2_GC_REV 0x34
57
static void omap_i2c_interrupts_update(OMAPI2CState *s)
59
qemu_set_irq(s->irq, s->stat & s->mask);
60
if ((s->dma >> 15) & 1) /* RDMA_EN */
61
qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
62
if ((s->dma >> 7) & 1) /* XDMA_EN */
63
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
66
static void omap_i2c_fifo_run(OMAPI2CState *s)
70
if (!i2c_bus_busy(s->bus))
73
if ((s->control >> 2) & 1) { /* RM */
74
if ((s->control >> 1) & 1) { /* STP */
75
i2c_end_transfer(s->bus);
76
s->control &= ~(1 << 1); /* STP */
77
s->count_cur = s->count;
79
} else if ((s->control >> 9) & 1) { /* TRX */
80
while (ack && s->txlen)
81
ack = (i2c_send(s->bus,
82
(s->fifo >> ((-- s->txlen) << 3)) &
84
s->stat |= 1 << 4; /* XRDY */
87
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
88
s->stat |= 1 << 3; /* RRDY */
91
if ((s->control >> 9) & 1) { /* TRX */
92
while (ack && s->count_cur && s->txlen) {
93
ack = (i2c_send(s->bus,
94
(s->fifo >> ((-- s->txlen) << 3)) &
98
if (ack && s->count_cur)
99
s->stat |= 1 << 4; /* XRDY */
101
s->stat &= ~(1 << 4); /* XRDY */
103
s->stat |= 1 << 2; /* ARDY */
104
s->control &= ~(1 << 10); /* MST */
107
while (s->count_cur && s->rxlen < 4) {
108
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
112
s->stat |= 1 << 3; /* RRDY */
114
s->stat &= ~(1 << 3); /* RRDY */
117
if ((s->control >> 1) & 1) { /* STP */
118
i2c_end_transfer(s->bus);
119
s->control &= ~(1 << 1); /* STP */
120
s->count_cur = s->count;
123
s->stat |= 1 << 2; /* ARDY */
124
s->control &= ~(1 << 10); /* MST */
129
s->stat |= (!ack) << 1; /* NACK */
131
s->control &= ~(1 << 1); /* STP */
134
static void omap_i2c_reset(DeviceState *dev)
136
OMAPI2CState *s = OMAP_I2C(dev);
155
static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
157
OMAPI2CState *s = opaque;
158
int offset = addr & OMAP_MPUI_REG_MASK;
162
case 0x00: /* I2C_REV */
163
return s->revision; /* REV */
165
case 0x04: /* I2C_IE */
168
case 0x08: /* I2C_STAT */
169
return s->stat | (i2c_bus_busy(s->bus) << 12);
171
case 0x0c: /* I2C_IV */
172
if (s->revision >= OMAP2_INTR_REV)
174
ret = ffs(s->stat & s->mask);
176
s->stat ^= 1 << (ret - 1);
177
omap_i2c_interrupts_update(s);
180
case 0x10: /* I2C_SYSS */
181
return (s->control >> 15) & 1; /* I2C_EN */
183
case 0x14: /* I2C_BUF */
186
case 0x18: /* I2C_CNT */
187
return s->count_cur; /* DCOUNT */
189
case 0x1c: /* I2C_DATA */
191
if (s->control & (1 << 14)) { /* BE */
192
ret |= ((s->fifo >> 0) & 0xff) << 8;
193
ret |= ((s->fifo >> 8) & 0xff) << 0;
195
ret |= ((s->fifo >> 8) & 0xff) << 8;
196
ret |= ((s->fifo >> 0) & 0xff) << 0;
199
s->stat |= 1 << 15; /* SBD */
201
} else if (s->rxlen > 1) {
206
/* XXX: remote access (qualifier) error - what's that? */
209
s->stat &= ~(1 << 3); /* RRDY */
210
if (((s->control >> 10) & 1) && /* MST */
211
((~s->control >> 9) & 1)) { /* TRX */
212
s->stat |= 1 << 2; /* ARDY */
213
s->control &= ~(1 << 10); /* MST */
216
s->stat &= ~(1 << 11); /* ROVR */
217
omap_i2c_fifo_run(s);
218
omap_i2c_interrupts_update(s);
221
case 0x20: /* I2C_SYSC */
224
case 0x24: /* I2C_CON */
227
case 0x28: /* I2C_OA */
230
case 0x2c: /* I2C_SA */
233
case 0x30: /* I2C_PSC */
236
case 0x34: /* I2C_SCLL */
239
case 0x38: /* I2C_SCLH */
242
case 0x3c: /* I2C_SYSTEST */
243
if (s->test & (1 << 15)) { /* ST_EN */
247
return s->test & ~0x300f;
254
static void omap_i2c_write(void *opaque, hwaddr addr,
257
OMAPI2CState *s = opaque;
258
int offset = addr & OMAP_MPUI_REG_MASK;
262
case 0x00: /* I2C_REV */
263
case 0x0c: /* I2C_IV */
264
case 0x10: /* I2C_SYSS */
268
case 0x04: /* I2C_IE */
269
s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
272
case 0x08: /* I2C_STAT */
273
if (s->revision < OMAP2_INTR_REV) {
278
/* RRDY and XRDY are reset by hardware. (in all versions???) */
279
s->stat &= ~(value & 0x27);
280
omap_i2c_interrupts_update(s);
283
case 0x14: /* I2C_BUF */
284
s->dma = value & 0x8080;
285
if (value & (1 << 15)) /* RDMA_EN */
286
s->mask &= ~(1 << 3); /* RRDY_IE */
287
if (value & (1 << 7)) /* XDMA_EN */
288
s->mask &= ~(1 << 4); /* XRDY_IE */
291
case 0x18: /* I2C_CNT */
292
s->count = value; /* DCOUNT */
295
case 0x1c: /* I2C_DATA */
297
/* XXX: remote access (qualifier) error - what's that? */
302
if (s->control & (1 << 14)) { /* BE */
303
s->fifo |= ((value >> 8) & 0xff) << 8;
304
s->fifo |= ((value >> 0) & 0xff) << 0;
306
s->fifo |= ((value >> 0) & 0xff) << 8;
307
s->fifo |= ((value >> 8) & 0xff) << 0;
309
s->stat &= ~(1 << 10); /* XUDF */
311
s->stat &= ~(1 << 4); /* XRDY */
312
omap_i2c_fifo_run(s);
313
omap_i2c_interrupts_update(s);
316
case 0x20: /* I2C_SYSC */
317
if (s->revision < OMAP2_INTR_REV) {
323
omap_i2c_reset(DEVICE(s));
327
case 0x24: /* I2C_CON */
328
s->control = value & 0xcf87;
329
if (~value & (1 << 15)) { /* I2C_EN */
330
if (s->revision < OMAP2_INTR_REV) {
331
omap_i2c_reset(DEVICE(s));
335
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
336
fprintf(stderr, "%s: I^2C slave mode not supported\n",
340
if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
341
fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
345
if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
346
nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
347
(~value >> 9) & 1); /* TRX */
348
s->stat |= nack << 1; /* NACK */
349
s->control &= ~(1 << 0); /* STT */
352
s->control &= ~(1 << 1); /* STP */
354
s->count_cur = s->count;
355
omap_i2c_fifo_run(s);
357
omap_i2c_interrupts_update(s);
361
case 0x28: /* I2C_OA */
362
s->addr[0] = value & 0x3ff;
365
case 0x2c: /* I2C_SA */
366
s->addr[1] = value & 0x3ff;
369
case 0x30: /* I2C_PSC */
373
case 0x34: /* I2C_SCLL */
377
case 0x38: /* I2C_SCLH */
381
case 0x3c: /* I2C_SYSTEST */
382
s->test = value & 0xf80f;
383
if (value & (1 << 11)) /* SBB */
384
if (s->revision >= OMAP2_INTR_REV) {
386
omap_i2c_interrupts_update(s);
388
if (value & (1 << 15)) /* ST_EN */
389
fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
398
static void omap_i2c_writeb(void *opaque, hwaddr addr,
401
OMAPI2CState *s = opaque;
402
int offset = addr & OMAP_MPUI_REG_MASK;
405
case 0x1c: /* I2C_DATA */
407
/* XXX: remote access (qualifier) error - what's that? */
412
s->fifo |= value & 0xff;
413
s->stat &= ~(1 << 10); /* XUDF */
415
s->stat &= ~(1 << 4); /* XRDY */
416
omap_i2c_fifo_run(s);
417
omap_i2c_interrupts_update(s);
426
static const MemoryRegionOps omap_i2c_ops = {
429
omap_badwidth_read16,
431
omap_badwidth_read16,
434
omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
436
omap_badwidth_write16,
439
.endianness = DEVICE_NATIVE_ENDIAN,
442
static int omap_i2c_init(SysBusDevice *sbd)
444
DeviceState *dev = DEVICE(sbd);
445
OMAPI2CState *s = OMAP_I2C(dev);
448
hw_error("omap_i2c: fclk not connected\n");
450
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
451
/* Note that OMAP1 doesn't have a separate interface clock */
452
hw_error("omap_i2c: iclk not connected\n");
454
sysbus_init_irq(sbd, &s->irq);
455
sysbus_init_irq(sbd, &s->drq[0]);
456
sysbus_init_irq(sbd, &s->drq[1]);
457
memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
458
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
459
sysbus_init_mmio(sbd, &s->iomem);
460
s->bus = i2c_init_bus(dev, NULL);
464
static Property omap_i2c_properties[] = {
465
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
466
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
467
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
468
DEFINE_PROP_END_OF_LIST(),
471
static void omap_i2c_class_init(ObjectClass *klass, void *data)
473
DeviceClass *dc = DEVICE_CLASS(klass);
474
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
475
k->init = omap_i2c_init;
476
dc->props = omap_i2c_properties;
477
dc->reset = omap_i2c_reset;
480
static const TypeInfo omap_i2c_info = {
481
.name = TYPE_OMAP_I2C,
482
.parent = TYPE_SYS_BUS_DEVICE,
483
.instance_size = sizeof(OMAPI2CState),
484
.class_init = omap_i2c_class_init,
487
static void omap_i2c_register_types(void)
489
type_register_static(&omap_i2c_info);
492
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
494
OMAPI2CState *s = OMAP_I2C(omap_i2c);
498
type_init(omap_i2c_register_types)