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"
25
typedef struct OMAPI2CState {
51
#define OMAP2_INTR_REV 0x34
52
#define OMAP2_GC_REV 0x34
54
static void omap_i2c_interrupts_update(OMAPI2CState *s)
56
qemu_set_irq(s->irq, s->stat & s->mask);
57
if ((s->dma >> 15) & 1) /* RDMA_EN */
58
qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
59
if ((s->dma >> 7) & 1) /* XDMA_EN */
60
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
63
static void omap_i2c_fifo_run(OMAPI2CState *s)
67
if (!i2c_bus_busy(s->bus))
70
if ((s->control >> 2) & 1) { /* RM */
71
if ((s->control >> 1) & 1) { /* STP */
72
i2c_end_transfer(s->bus);
73
s->control &= ~(1 << 1); /* STP */
74
s->count_cur = s->count;
76
} else if ((s->control >> 9) & 1) { /* TRX */
77
while (ack && s->txlen)
78
ack = (i2c_send(s->bus,
79
(s->fifo >> ((-- s->txlen) << 3)) &
81
s->stat |= 1 << 4; /* XRDY */
84
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
85
s->stat |= 1 << 3; /* RRDY */
88
if ((s->control >> 9) & 1) { /* TRX */
89
while (ack && s->count_cur && s->txlen) {
90
ack = (i2c_send(s->bus,
91
(s->fifo >> ((-- s->txlen) << 3)) &
95
if (ack && s->count_cur)
96
s->stat |= 1 << 4; /* XRDY */
98
s->stat &= ~(1 << 4); /* XRDY */
100
s->stat |= 1 << 2; /* ARDY */
101
s->control &= ~(1 << 10); /* MST */
104
while (s->count_cur && s->rxlen < 4) {
105
s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
109
s->stat |= 1 << 3; /* RRDY */
111
s->stat &= ~(1 << 3); /* RRDY */
114
if ((s->control >> 1) & 1) { /* STP */
115
i2c_end_transfer(s->bus);
116
s->control &= ~(1 << 1); /* STP */
117
s->count_cur = s->count;
120
s->stat |= 1 << 2; /* ARDY */
121
s->control &= ~(1 << 10); /* MST */
126
s->stat |= (!ack) << 1; /* NACK */
128
s->control &= ~(1 << 1); /* STP */
131
static void omap_i2c_reset(DeviceState *dev)
133
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
134
SYS_BUS_DEVICE(dev));
152
static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
154
OMAPI2CState *s = opaque;
155
int offset = addr & OMAP_MPUI_REG_MASK;
159
case 0x00: /* I2C_REV */
160
return s->revision; /* REV */
162
case 0x04: /* I2C_IE */
165
case 0x08: /* I2C_STAT */
166
return s->stat | (i2c_bus_busy(s->bus) << 12);
168
case 0x0c: /* I2C_IV */
169
if (s->revision >= OMAP2_INTR_REV)
171
ret = ffs(s->stat & s->mask);
173
s->stat ^= 1 << (ret - 1);
174
omap_i2c_interrupts_update(s);
177
case 0x10: /* I2C_SYSS */
178
return (s->control >> 15) & 1; /* I2C_EN */
180
case 0x14: /* I2C_BUF */
183
case 0x18: /* I2C_CNT */
184
return s->count_cur; /* DCOUNT */
186
case 0x1c: /* I2C_DATA */
188
if (s->control & (1 << 14)) { /* BE */
189
ret |= ((s->fifo >> 0) & 0xff) << 8;
190
ret |= ((s->fifo >> 8) & 0xff) << 0;
192
ret |= ((s->fifo >> 8) & 0xff) << 8;
193
ret |= ((s->fifo >> 0) & 0xff) << 0;
196
s->stat |= 1 << 15; /* SBD */
198
} else if (s->rxlen > 1) {
203
/* XXX: remote access (qualifier) error - what's that? */
206
s->stat &= ~(1 << 3); /* RRDY */
207
if (((s->control >> 10) & 1) && /* MST */
208
((~s->control >> 9) & 1)) { /* TRX */
209
s->stat |= 1 << 2; /* ARDY */
210
s->control &= ~(1 << 10); /* MST */
213
s->stat &= ~(1 << 11); /* ROVR */
214
omap_i2c_fifo_run(s);
215
omap_i2c_interrupts_update(s);
218
case 0x20: /* I2C_SYSC */
221
case 0x24: /* I2C_CON */
224
case 0x28: /* I2C_OA */
227
case 0x2c: /* I2C_SA */
230
case 0x30: /* I2C_PSC */
233
case 0x34: /* I2C_SCLL */
236
case 0x38: /* I2C_SCLH */
239
case 0x3c: /* I2C_SYSTEST */
240
if (s->test & (1 << 15)) { /* ST_EN */
244
return s->test & ~0x300f;
251
static void omap_i2c_write(void *opaque, hwaddr addr,
254
OMAPI2CState *s = opaque;
255
int offset = addr & OMAP_MPUI_REG_MASK;
259
case 0x00: /* I2C_REV */
260
case 0x0c: /* I2C_IV */
261
case 0x10: /* I2C_SYSS */
265
case 0x04: /* I2C_IE */
266
s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
269
case 0x08: /* I2C_STAT */
270
if (s->revision < OMAP2_INTR_REV) {
275
/* RRDY and XRDY are reset by hardware. (in all versions???) */
276
s->stat &= ~(value & 0x27);
277
omap_i2c_interrupts_update(s);
280
case 0x14: /* I2C_BUF */
281
s->dma = value & 0x8080;
282
if (value & (1 << 15)) /* RDMA_EN */
283
s->mask &= ~(1 << 3); /* RRDY_IE */
284
if (value & (1 << 7)) /* XDMA_EN */
285
s->mask &= ~(1 << 4); /* XRDY_IE */
288
case 0x18: /* I2C_CNT */
289
s->count = value; /* DCOUNT */
292
case 0x1c: /* I2C_DATA */
294
/* XXX: remote access (qualifier) error - what's that? */
299
if (s->control & (1 << 14)) { /* BE */
300
s->fifo |= ((value >> 8) & 0xff) << 8;
301
s->fifo |= ((value >> 0) & 0xff) << 0;
303
s->fifo |= ((value >> 0) & 0xff) << 8;
304
s->fifo |= ((value >> 8) & 0xff) << 0;
306
s->stat &= ~(1 << 10); /* XUDF */
308
s->stat &= ~(1 << 4); /* XRDY */
309
omap_i2c_fifo_run(s);
310
omap_i2c_interrupts_update(s);
313
case 0x20: /* I2C_SYSC */
314
if (s->revision < OMAP2_INTR_REV) {
320
omap_i2c_reset(&s->busdev.qdev);
323
case 0x24: /* I2C_CON */
324
s->control = value & 0xcf87;
325
if (~value & (1 << 15)) { /* I2C_EN */
326
if (s->revision < OMAP2_INTR_REV)
327
omap_i2c_reset(&s->busdev.qdev);
330
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
331
fprintf(stderr, "%s: I^2C slave mode not supported\n",
335
if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
336
fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
340
if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
341
nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
342
(~value >> 9) & 1); /* TRX */
343
s->stat |= nack << 1; /* NACK */
344
s->control &= ~(1 << 0); /* STT */
347
s->control &= ~(1 << 1); /* STP */
349
s->count_cur = s->count;
350
omap_i2c_fifo_run(s);
352
omap_i2c_interrupts_update(s);
356
case 0x28: /* I2C_OA */
357
s->addr[0] = value & 0x3ff;
360
case 0x2c: /* I2C_SA */
361
s->addr[1] = value & 0x3ff;
364
case 0x30: /* I2C_PSC */
368
case 0x34: /* I2C_SCLL */
372
case 0x38: /* I2C_SCLH */
376
case 0x3c: /* I2C_SYSTEST */
377
s->test = value & 0xf80f;
378
if (value & (1 << 11)) /* SBB */
379
if (s->revision >= OMAP2_INTR_REV) {
381
omap_i2c_interrupts_update(s);
383
if (value & (1 << 15)) /* ST_EN */
384
fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
393
static void omap_i2c_writeb(void *opaque, hwaddr addr,
396
OMAPI2CState *s = opaque;
397
int offset = addr & OMAP_MPUI_REG_MASK;
400
case 0x1c: /* I2C_DATA */
402
/* XXX: remote access (qualifier) error - what's that? */
407
s->fifo |= value & 0xff;
408
s->stat &= ~(1 << 10); /* XUDF */
410
s->stat &= ~(1 << 4); /* XRDY */
411
omap_i2c_fifo_run(s);
412
omap_i2c_interrupts_update(s);
421
static const MemoryRegionOps omap_i2c_ops = {
424
omap_badwidth_read16,
426
omap_badwidth_read16,
429
omap_i2c_writeb, /* Only the last fifo write can be 8 bit. */
431
omap_badwidth_write16,
434
.endianness = DEVICE_NATIVE_ENDIAN,
437
static int omap_i2c_init(SysBusDevice *dev)
439
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
442
hw_error("omap_i2c: fclk not connected\n");
444
if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
445
/* Note that OMAP1 doesn't have a separate interface clock */
446
hw_error("omap_i2c: iclk not connected\n");
448
sysbus_init_irq(dev, &s->irq);
449
sysbus_init_irq(dev, &s->drq[0]);
450
sysbus_init_irq(dev, &s->drq[1]);
451
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c",
452
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
453
sysbus_init_mmio(dev, &s->iomem);
454
s->bus = i2c_init_bus(&dev->qdev, NULL);
458
static Property omap_i2c_properties[] = {
459
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
460
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
461
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
462
DEFINE_PROP_END_OF_LIST(),
465
static void omap_i2c_class_init(ObjectClass *klass, void *data)
467
DeviceClass *dc = DEVICE_CLASS(klass);
468
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
469
k->init = omap_i2c_init;
470
dc->props = omap_i2c_properties;
471
dc->reset = omap_i2c_reset;
474
static const TypeInfo omap_i2c_info = {
476
.parent = TYPE_SYS_BUS_DEVICE,
477
.instance_size = sizeof(OMAPI2CState),
478
.class_init = omap_i2c_class_init,
481
static void omap_i2c_register_types(void)
483
type_register_static(&omap_i2c_info);
486
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
488
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, SYS_BUS_DEVICE(omap_i2c));
492
type_init(omap_i2c_register_types)