hw/ppc: Drop useless CONFIG_KVM ifdefery
[qemu/ar7.git] / hw / i2c / omap_i2c.c
blobd7ebeae8e2e258803500f23eaf3b60a882756806
1 /*
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 "qemu/osdep.h"
21 #include "qemu/log.h"
22 #include "qemu/module.h"
23 #include "hw/hw.h"
24 #include "hw/i2c/i2c.h"
25 #include "hw/arm/omap.h"
26 #include "hw/sysbus.h"
27 #include "qemu/error-report.h"
28 #include "qapi/error.h"
30 #define TYPE_OMAP_I2C "omap_i2c"
31 #define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
33 typedef struct OMAPI2CState {
34 SysBusDevice parent_obj;
36 MemoryRegion iomem;
37 qemu_irq irq;
38 qemu_irq drq[2];
39 I2CBus *bus;
41 uint8_t revision;
42 void *iclk;
43 void *fclk;
45 uint8_t mask;
46 uint16_t stat;
47 uint16_t dma;
48 uint16_t count;
49 int count_cur;
50 uint32_t fifo;
51 int rxlen;
52 int txlen;
53 uint16_t control;
54 uint16_t addr[2];
55 uint8_t divider;
56 uint8_t times[2];
57 uint16_t test;
58 } OMAPI2CState;
60 #define OMAP2_INTR_REV 0x34
61 #define OMAP2_GC_REV 0x34
63 static void omap_i2c_interrupts_update(OMAPI2CState *s)
65 qemu_set_irq(s->irq, s->stat & s->mask);
66 if ((s->dma >> 15) & 1) /* RDMA_EN */
67 qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
68 if ((s->dma >> 7) & 1) /* XDMA_EN */
69 qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
72 static void omap_i2c_fifo_run(OMAPI2CState *s)
74 int ack = 1;
76 if (!i2c_bus_busy(s->bus))
77 return;
79 if ((s->control >> 2) & 1) { /* RM */
80 if ((s->control >> 1) & 1) { /* STP */
81 i2c_end_transfer(s->bus);
82 s->control &= ~(1 << 1); /* STP */
83 s->count_cur = s->count;
84 s->txlen = 0;
85 } else if ((s->control >> 9) & 1) { /* TRX */
86 while (ack && s->txlen)
87 ack = (i2c_send(s->bus,
88 (s->fifo >> ((-- s->txlen) << 3)) &
89 0xff) >= 0);
90 s->stat |= 1 << 4; /* XRDY */
91 } else {
92 while (s->rxlen < 4)
93 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
94 s->stat |= 1 << 3; /* RRDY */
96 } else {
97 if ((s->control >> 9) & 1) { /* TRX */
98 while (ack && s->count_cur && s->txlen) {
99 ack = (i2c_send(s->bus,
100 (s->fifo >> ((-- s->txlen) << 3)) &
101 0xff) >= 0);
102 s->count_cur --;
104 if (ack && s->count_cur)
105 s->stat |= 1 << 4; /* XRDY */
106 else
107 s->stat &= ~(1 << 4); /* XRDY */
108 if (!s->count_cur) {
109 s->stat |= 1 << 2; /* ARDY */
110 s->control &= ~(1 << 10); /* MST */
112 } else {
113 while (s->count_cur && s->rxlen < 4) {
114 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
115 s->count_cur --;
117 if (s->rxlen)
118 s->stat |= 1 << 3; /* RRDY */
119 else
120 s->stat &= ~(1 << 3); /* RRDY */
122 if (!s->count_cur) {
123 if ((s->control >> 1) & 1) { /* STP */
124 i2c_end_transfer(s->bus);
125 s->control &= ~(1 << 1); /* STP */
126 s->count_cur = s->count;
127 s->txlen = 0;
128 } else {
129 s->stat |= 1 << 2; /* ARDY */
130 s->control &= ~(1 << 10); /* MST */
135 s->stat |= (!ack) << 1; /* NACK */
136 if (!ack)
137 s->control &= ~(1 << 1); /* STP */
140 static void omap_i2c_reset(DeviceState *dev)
142 OMAPI2CState *s = OMAP_I2C(dev);
144 s->mask = 0;
145 s->stat = 0;
146 s->dma = 0;
147 s->count = 0;
148 s->count_cur = 0;
149 s->fifo = 0;
150 s->rxlen = 0;
151 s->txlen = 0;
152 s->control = 0;
153 s->addr[0] = 0;
154 s->addr[1] = 0;
155 s->divider = 0;
156 s->times[0] = 0;
157 s->times[1] = 0;
158 s->test = 0;
161 static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
163 OMAPI2CState *s = opaque;
164 int offset = addr & OMAP_MPUI_REG_MASK;
165 uint16_t ret;
167 switch (offset) {
168 case 0x00: /* I2C_REV */
169 return s->revision; /* REV */
171 case 0x04: /* I2C_IE */
172 return s->mask;
174 case 0x08: /* I2C_STAT */
175 return s->stat | (i2c_bus_busy(s->bus) << 12);
177 case 0x0c: /* I2C_IV */
178 if (s->revision >= OMAP2_INTR_REV)
179 break;
180 ret = ctz32(s->stat & s->mask);
181 if (ret != 32) {
182 s->stat ^= 1 << ret;
183 ret++;
184 } else {
185 ret = 0;
187 omap_i2c_interrupts_update(s);
188 return ret;
190 case 0x10: /* I2C_SYSS */
191 return (s->control >> 15) & 1; /* I2C_EN */
193 case 0x14: /* I2C_BUF */
194 return s->dma;
196 case 0x18: /* I2C_CNT */
197 return s->count_cur; /* DCOUNT */
199 case 0x1c: /* I2C_DATA */
200 ret = 0;
201 if (s->control & (1 << 14)) { /* BE */
202 ret |= ((s->fifo >> 0) & 0xff) << 8;
203 ret |= ((s->fifo >> 8) & 0xff) << 0;
204 } else {
205 ret |= ((s->fifo >> 8) & 0xff) << 8;
206 ret |= ((s->fifo >> 0) & 0xff) << 0;
208 if (s->rxlen == 1) {
209 s->stat |= 1 << 15; /* SBD */
210 s->rxlen = 0;
211 } else if (s->rxlen > 1) {
212 if (s->rxlen > 2)
213 s->fifo >>= 16;
214 s->rxlen -= 2;
215 } else {
216 /* XXX: remote access (qualifier) error - what's that? */
218 if (!s->rxlen) {
219 s->stat &= ~(1 << 3); /* RRDY */
220 if (((s->control >> 10) & 1) && /* MST */
221 ((~s->control >> 9) & 1)) { /* TRX */
222 s->stat |= 1 << 2; /* ARDY */
223 s->control &= ~(1 << 10); /* MST */
226 s->stat &= ~(1 << 11); /* ROVR */
227 omap_i2c_fifo_run(s);
228 omap_i2c_interrupts_update(s);
229 return ret;
231 case 0x20: /* I2C_SYSC */
232 return 0;
234 case 0x24: /* I2C_CON */
235 return s->control;
237 case 0x28: /* I2C_OA */
238 return s->addr[0];
240 case 0x2c: /* I2C_SA */
241 return s->addr[1];
243 case 0x30: /* I2C_PSC */
244 return s->divider;
246 case 0x34: /* I2C_SCLL */
247 return s->times[0];
249 case 0x38: /* I2C_SCLH */
250 return s->times[1];
252 case 0x3c: /* I2C_SYSTEST */
253 if (s->test & (1 << 15)) { /* ST_EN */
254 s->test ^= 0xa;
255 return s->test;
256 } else
257 return s->test & ~0x300f;
260 OMAP_BAD_REG(addr);
261 return 0;
264 static void omap_i2c_write(void *opaque, hwaddr addr,
265 uint32_t value)
267 OMAPI2CState *s = opaque;
268 int offset = addr & OMAP_MPUI_REG_MASK;
269 int nack;
271 switch (offset) {
272 case 0x00: /* I2C_REV */
273 case 0x0c: /* I2C_IV */
274 case 0x10: /* I2C_SYSS */
275 OMAP_RO_REG(addr);
276 return;
278 case 0x04: /* I2C_IE */
279 s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
280 break;
282 case 0x08: /* I2C_STAT */
283 if (s->revision < OMAP2_INTR_REV) {
284 OMAP_RO_REG(addr);
285 return;
288 /* RRDY and XRDY are reset by hardware. (in all versions???) */
289 s->stat &= ~(value & 0x27);
290 omap_i2c_interrupts_update(s);
291 break;
293 case 0x14: /* I2C_BUF */
294 s->dma = value & 0x8080;
295 if (value & (1 << 15)) /* RDMA_EN */
296 s->mask &= ~(1 << 3); /* RRDY_IE */
297 if (value & (1 << 7)) /* XDMA_EN */
298 s->mask &= ~(1 << 4); /* XRDY_IE */
299 break;
301 case 0x18: /* I2C_CNT */
302 s->count = value; /* DCOUNT */
303 break;
305 case 0x1c: /* I2C_DATA */
306 if (s->txlen > 2) {
307 /* XXX: remote access (qualifier) error - what's that? */
308 break;
310 s->fifo <<= 16;
311 s->txlen += 2;
312 if (s->control & (1 << 14)) { /* BE */
313 s->fifo |= ((value >> 8) & 0xff) << 8;
314 s->fifo |= ((value >> 0) & 0xff) << 0;
315 } else {
316 s->fifo |= ((value >> 0) & 0xff) << 8;
317 s->fifo |= ((value >> 8) & 0xff) << 0;
319 s->stat &= ~(1 << 10); /* XUDF */
320 if (s->txlen > 2)
321 s->stat &= ~(1 << 4); /* XRDY */
322 omap_i2c_fifo_run(s);
323 omap_i2c_interrupts_update(s);
324 break;
326 case 0x20: /* I2C_SYSC */
327 if (s->revision < OMAP2_INTR_REV) {
328 OMAP_BAD_REG(addr);
329 return;
332 if (value & 2) {
333 omap_i2c_reset(DEVICE(s));
335 break;
337 case 0x24: /* I2C_CON */
338 s->control = value & 0xcf87;
339 if (~value & (1 << 15)) { /* I2C_EN */
340 if (s->revision < OMAP2_INTR_REV) {
341 omap_i2c_reset(DEVICE(s));
343 break;
345 if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
346 qemu_log_mask(LOG_UNIMP, "%s: I^2C slave mode not supported\n",
347 __func__);
348 break;
350 if ((value & (1 << 15)) && value & (1 << 8)) { /* XA */
351 qemu_log_mask(LOG_UNIMP,
352 "%s: 10-bit addressing mode not supported\n",
353 __func__);
354 break;
356 if ((value & (1 << 15)) && value & (1 << 0)) { /* STT */
357 nack = !!i2c_start_transfer(s->bus, s->addr[1], /* SA */
358 (~value >> 9) & 1); /* TRX */
359 s->stat |= nack << 1; /* NACK */
360 s->control &= ~(1 << 0); /* STT */
361 s->fifo = 0;
362 if (nack)
363 s->control &= ~(1 << 1); /* STP */
364 else {
365 s->count_cur = s->count;
366 omap_i2c_fifo_run(s);
368 omap_i2c_interrupts_update(s);
370 break;
372 case 0x28: /* I2C_OA */
373 s->addr[0] = value & 0x3ff;
374 break;
376 case 0x2c: /* I2C_SA */
377 s->addr[1] = value & 0x3ff;
378 break;
380 case 0x30: /* I2C_PSC */
381 s->divider = value;
382 break;
384 case 0x34: /* I2C_SCLL */
385 s->times[0] = value;
386 break;
388 case 0x38: /* I2C_SCLH */
389 s->times[1] = value;
390 break;
392 case 0x3c: /* I2C_SYSTEST */
393 s->test = value & 0xf80f;
394 if (value & (1 << 11)) /* SBB */
395 if (s->revision >= OMAP2_INTR_REV) {
396 s->stat |= 0x3f;
397 omap_i2c_interrupts_update(s);
399 if (value & (1 << 15)) { /* ST_EN */
400 qemu_log_mask(LOG_UNIMP,
401 "%s: System Test not supported\n", __func__);
403 break;
405 default:
406 OMAP_BAD_REG(addr);
407 return;
411 static void omap_i2c_writeb(void *opaque, hwaddr addr,
412 uint32_t value)
414 OMAPI2CState *s = opaque;
415 int offset = addr & OMAP_MPUI_REG_MASK;
417 switch (offset) {
418 case 0x1c: /* I2C_DATA */
419 if (s->txlen > 2) {
420 /* XXX: remote access (qualifier) error - what's that? */
421 break;
423 s->fifo <<= 8;
424 s->txlen += 1;
425 s->fifo |= value & 0xff;
426 s->stat &= ~(1 << 10); /* XUDF */
427 if (s->txlen > 2)
428 s->stat &= ~(1 << 4); /* XRDY */
429 omap_i2c_fifo_run(s);
430 omap_i2c_interrupts_update(s);
431 break;
433 default:
434 OMAP_BAD_REG(addr);
435 return;
439 static uint64_t omap_i2c_readfn(void *opaque, hwaddr addr,
440 unsigned size)
442 switch (size) {
443 case 2:
444 return omap_i2c_read(opaque, addr);
445 default:
446 return omap_badwidth_read16(opaque, addr);
450 static void omap_i2c_writefn(void *opaque, hwaddr addr,
451 uint64_t value, unsigned size)
453 switch (size) {
454 case 1:
455 /* Only the last fifo write can be 8 bit. */
456 omap_i2c_writeb(opaque, addr, value);
457 break;
458 case 2:
459 omap_i2c_write(opaque, addr, value);
460 break;
461 default:
462 omap_badwidth_write16(opaque, addr, value);
463 break;
467 static const MemoryRegionOps omap_i2c_ops = {
468 .read = omap_i2c_readfn,
469 .write = omap_i2c_writefn,
470 .valid.min_access_size = 1,
471 .valid.max_access_size = 4,
472 .endianness = DEVICE_NATIVE_ENDIAN,
475 static void omap_i2c_init(Object *obj)
477 DeviceState *dev = DEVICE(obj);
478 OMAPI2CState *s = OMAP_I2C(obj);
479 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
481 sysbus_init_irq(sbd, &s->irq);
482 sysbus_init_irq(sbd, &s->drq[0]);
483 sysbus_init_irq(sbd, &s->drq[1]);
484 sysbus_init_mmio(sbd, &s->iomem);
485 s->bus = i2c_init_bus(dev, NULL);
488 static void omap_i2c_realize(DeviceState *dev, Error **errp)
490 OMAPI2CState *s = OMAP_I2C(dev);
492 memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
493 (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
495 if (!s->fclk) {
496 error_setg(errp, "omap_i2c: fclk not connected");
497 return;
499 if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
500 /* Note that OMAP1 doesn't have a separate interface clock */
501 error_setg(errp, "omap_i2c: iclk not connected");
502 return;
506 static Property omap_i2c_properties[] = {
507 DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
508 DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
509 DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
510 DEFINE_PROP_END_OF_LIST(),
513 static void omap_i2c_class_init(ObjectClass *klass, void *data)
515 DeviceClass *dc = DEVICE_CLASS(klass);
517 dc->props = omap_i2c_properties;
518 dc->reset = omap_i2c_reset;
519 /* Reason: pointer properties "iclk", "fclk" */
520 dc->user_creatable = false;
521 dc->realize = omap_i2c_realize;
524 static const TypeInfo omap_i2c_info = {
525 .name = TYPE_OMAP_I2C,
526 .parent = TYPE_SYS_BUS_DEVICE,
527 .instance_size = sizeof(OMAPI2CState),
528 .instance_init = omap_i2c_init,
529 .class_init = omap_i2c_class_init,
532 static void omap_i2c_register_types(void)
534 type_register_static(&omap_i2c_info);
537 I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
539 OMAPI2CState *s = OMAP_I2C(omap_i2c);
540 return s->bus;
543 type_init(omap_i2c_register_types)