1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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"
29
30#define TYPE_OMAP_I2C "omap_i2c"
31#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
32
33typedef struct OMAPI2CState {
34 SysBusDevice parent_obj;
35
36 MemoryRegion iomem;
37 qemu_irq irq;
38 qemu_irq drq[2];
39 I2CBus *bus;
40
41 uint8_t revision;
42 void *iclk;
43 void *fclk;
44
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;
59
60#define OMAP2_INTR_REV 0x34
61#define OMAP2_GC_REV 0x34
62
63static void omap_i2c_interrupts_update(OMAPI2CState *s)
64{
65 qemu_set_irq(s->irq, s->stat & s->mask);
66 if ((s->dma >> 15) & 1)
67 qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);
68 if ((s->dma >> 7) & 1)
69 qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);
70}
71
72static void omap_i2c_fifo_run(OMAPI2CState *s)
73{
74 int ack = 1;
75
76 if (!i2c_bus_busy(s->bus))
77 return;
78
79 if ((s->control >> 2) & 1) {
80 if ((s->control >> 1) & 1) {
81 i2c_end_transfer(s->bus);
82 s->control &= ~(1 << 1);
83 s->count_cur = s->count;
84 s->txlen = 0;
85 } else if ((s->control >> 9) & 1) {
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;
91 } else {
92 while (s->rxlen < 4)
93 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
94 s->stat |= 1 << 3;
95 }
96 } else {
97 if ((s->control >> 9) & 1) {
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 --;
103 }
104 if (ack && s->count_cur)
105 s->stat |= 1 << 4;
106 else
107 s->stat &= ~(1 << 4);
108 if (!s->count_cur) {
109 s->stat |= 1 << 2;
110 s->control &= ~(1 << 10);
111 }
112 } else {
113 while (s->count_cur && s->rxlen < 4) {
114 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
115 s->count_cur --;
116 }
117 if (s->rxlen)
118 s->stat |= 1 << 3;
119 else
120 s->stat &= ~(1 << 3);
121 }
122 if (!s->count_cur) {
123 if ((s->control >> 1) & 1) {
124 i2c_end_transfer(s->bus);
125 s->control &= ~(1 << 1);
126 s->count_cur = s->count;
127 s->txlen = 0;
128 } else {
129 s->stat |= 1 << 2;
130 s->control &= ~(1 << 10);
131 }
132 }
133 }
134
135 s->stat |= (!ack) << 1;
136 if (!ack)
137 s->control &= ~(1 << 1);
138}
139
140static void omap_i2c_reset(DeviceState *dev)
141{
142 OMAPI2CState *s = OMAP_I2C(dev);
143
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;
159}
160
161static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
162{
163 OMAPI2CState *s = opaque;
164 int offset = addr & OMAP_MPUI_REG_MASK;
165 uint16_t ret;
166
167 switch (offset) {
168 case 0x00:
169 return s->revision;
170
171 case 0x04:
172 return s->mask;
173
174 case 0x08:
175 return s->stat | (i2c_bus_busy(s->bus) << 12);
176
177 case 0x0c:
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;
186 }
187 omap_i2c_interrupts_update(s);
188 return ret;
189
190 case 0x10:
191 return (s->control >> 15) & 1;
192
193 case 0x14:
194 return s->dma;
195
196 case 0x18:
197 return s->count_cur;
198
199 case 0x1c:
200 ret = 0;
201 if (s->control & (1 << 14)) {
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;
207 }
208 if (s->rxlen == 1) {
209 s->stat |= 1 << 15;
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
217 }
218 if (!s->rxlen) {
219 s->stat &= ~(1 << 3);
220 if (((s->control >> 10) & 1) &&
221 ((~s->control >> 9) & 1)) {
222 s->stat |= 1 << 2;
223 s->control &= ~(1 << 10);
224 }
225 }
226 s->stat &= ~(1 << 11);
227 omap_i2c_fifo_run(s);
228 omap_i2c_interrupts_update(s);
229 return ret;
230
231 case 0x20:
232 return 0;
233
234 case 0x24:
235 return s->control;
236
237 case 0x28:
238 return s->addr[0];
239
240 case 0x2c:
241 return s->addr[1];
242
243 case 0x30:
244 return s->divider;
245
246 case 0x34:
247 return s->times[0];
248
249 case 0x38:
250 return s->times[1];
251
252 case 0x3c:
253 if (s->test & (1 << 15)) {
254 s->test ^= 0xa;
255 return s->test;
256 } else
257 return s->test & ~0x300f;
258 }
259
260 OMAP_BAD_REG(addr);
261 return 0;
262}
263
264static void omap_i2c_write(void *opaque, hwaddr addr,
265 uint32_t value)
266{
267 OMAPI2CState *s = opaque;
268 int offset = addr & OMAP_MPUI_REG_MASK;
269 int nack;
270
271 switch (offset) {
272 case 0x00:
273 case 0x0c:
274 case 0x10:
275 OMAP_RO_REG(addr);
276 return;
277
278 case 0x04:
279 s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
280 break;
281
282 case 0x08:
283 if (s->revision < OMAP2_INTR_REV) {
284 OMAP_RO_REG(addr);
285 return;
286 }
287
288
289 s->stat &= ~(value & 0x27);
290 omap_i2c_interrupts_update(s);
291 break;
292
293 case 0x14:
294 s->dma = value & 0x8080;
295 if (value & (1 << 15))
296 s->mask &= ~(1 << 3);
297 if (value & (1 << 7))
298 s->mask &= ~(1 << 4);
299 break;
300
301 case 0x18:
302 s->count = value;
303 break;
304
305 case 0x1c:
306 if (s->txlen > 2) {
307
308 break;
309 }
310 s->fifo <<= 16;
311 s->txlen += 2;
312 if (s->control & (1 << 14)) {
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;
318 }
319 s->stat &= ~(1 << 10);
320 if (s->txlen > 2)
321 s->stat &= ~(1 << 4);
322 omap_i2c_fifo_run(s);
323 omap_i2c_interrupts_update(s);
324 break;
325
326 case 0x20:
327 if (s->revision < OMAP2_INTR_REV) {
328 OMAP_BAD_REG(addr);
329 return;
330 }
331
332 if (value & 2) {
333 omap_i2c_reset(DEVICE(s));
334 }
335 break;
336
337 case 0x24:
338 s->control = value & 0xcf87;
339 if (~value & (1 << 15)) {
340 if (s->revision < OMAP2_INTR_REV) {
341 omap_i2c_reset(DEVICE(s));
342 }
343 break;
344 }
345 if ((value & (1 << 15)) && !(value & (1 << 10))) {
346 qemu_log_mask(LOG_UNIMP, "%s: I^2C slave mode not supported\n",
347 __func__);
348 break;
349 }
350 if ((value & (1 << 15)) && value & (1 << 8)) {
351 qemu_log_mask(LOG_UNIMP,
352 "%s: 10-bit addressing mode not supported\n",
353 __func__);
354 break;
355 }
356 if ((value & (1 << 15)) && value & (1 << 0)) {
357 nack = !!i2c_start_transfer(s->bus, s->addr[1],
358 (~value >> 9) & 1);
359 s->stat |= nack << 1;
360 s->control &= ~(1 << 0);
361 s->fifo = 0;
362 if (nack)
363 s->control &= ~(1 << 1);
364 else {
365 s->count_cur = s->count;
366 omap_i2c_fifo_run(s);
367 }
368 omap_i2c_interrupts_update(s);
369 }
370 break;
371
372 case 0x28:
373 s->addr[0] = value & 0x3ff;
374 break;
375
376 case 0x2c:
377 s->addr[1] = value & 0x3ff;
378 break;
379
380 case 0x30:
381 s->divider = value;
382 break;
383
384 case 0x34:
385 s->times[0] = value;
386 break;
387
388 case 0x38:
389 s->times[1] = value;
390 break;
391
392 case 0x3c:
393 s->test = value & 0xf80f;
394 if (value & (1 << 11))
395 if (s->revision >= OMAP2_INTR_REV) {
396 s->stat |= 0x3f;
397 omap_i2c_interrupts_update(s);
398 }
399 if (value & (1 << 15)) {
400 qemu_log_mask(LOG_UNIMP,
401 "%s: System Test not supported\n", __func__);
402 }
403 break;
404
405 default:
406 OMAP_BAD_REG(addr);
407 return;
408 }
409}
410
411static void omap_i2c_writeb(void *opaque, hwaddr addr,
412 uint32_t value)
413{
414 OMAPI2CState *s = opaque;
415 int offset = addr & OMAP_MPUI_REG_MASK;
416
417 switch (offset) {
418 case 0x1c:
419 if (s->txlen > 2) {
420
421 break;
422 }
423 s->fifo <<= 8;
424 s->txlen += 1;
425 s->fifo |= value & 0xff;
426 s->stat &= ~(1 << 10);
427 if (s->txlen > 2)
428 s->stat &= ~(1 << 4);
429 omap_i2c_fifo_run(s);
430 omap_i2c_interrupts_update(s);
431 break;
432
433 default:
434 OMAP_BAD_REG(addr);
435 return;
436 }
437}
438
439static uint64_t omap_i2c_readfn(void *opaque, hwaddr addr,
440 unsigned size)
441{
442 switch (size) {
443 case 2:
444 return omap_i2c_read(opaque, addr);
445 default:
446 return omap_badwidth_read16(opaque, addr);
447 }
448}
449
450static void omap_i2c_writefn(void *opaque, hwaddr addr,
451 uint64_t value, unsigned size)
452{
453 switch (size) {
454 case 1:
455
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;
464 }
465}
466
467static 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,
473};
474
475static void omap_i2c_init(Object *obj)
476{
477 DeviceState *dev = DEVICE(obj);
478 OMAPI2CState *s = OMAP_I2C(obj);
479 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
480
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);
486}
487
488static void omap_i2c_realize(DeviceState *dev, Error **errp)
489{
490 OMAPI2CState *s = OMAP_I2C(dev);
491
492 memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
493 (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
494
495 if (!s->fclk) {
496 error_setg(errp, "omap_i2c: fclk not connected");
497 return;
498 }
499 if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
500
501 error_setg(errp, "omap_i2c: iclk not connected");
502 return;
503 }
504}
505
506static 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(),
511};
512
513static void omap_i2c_class_init(ObjectClass *klass, void *data)
514{
515 DeviceClass *dc = DEVICE_CLASS(klass);
516
517 dc->props = omap_i2c_properties;
518 dc->reset = omap_i2c_reset;
519
520 dc->user_creatable = false;
521 dc->realize = omap_i2c_realize;
522}
523
524static 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,
530};
531
532static void omap_i2c_register_types(void)
533{
534 type_register_static(&omap_i2c_info);
535}
536
537I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
538{
539 OMAPI2CState *s = OMAP_I2C(omap_i2c);
540 return s->bus;
541}
542
543type_init(omap_i2c_register_types)
544