]> Git Repo - qemu.git/blob - hw/i2c/omap_i2c.c
hw/usb/tusb6010: Convert away from old_mmio
[qemu.git] / hw / i2c / omap_i2c.c
1 /*
2  * TI OMAP on-chip I2C controller.  Only "new I2C" mode supported.
3  *
4  * Copyright (C) 2007 Andrzej Zaborowski  <[email protected]>
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 #include "qemu/osdep.h"
20 #include "hw/hw.h"
21 #include "hw/i2c/i2c.h"
22 #include "hw/arm/omap.h"
23 #include "hw/sysbus.h"
24 #include "qemu/error-report.h"
25 #include "qapi/error.h"
26
27 #define TYPE_OMAP_I2C "omap_i2c"
28 #define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
29
30 typedef struct OMAPI2CState {
31     SysBusDevice parent_obj;
32
33     MemoryRegion iomem;
34     qemu_irq irq;
35     qemu_irq drq[2];
36     I2CBus *bus;
37
38     uint8_t revision;
39     void *iclk;
40     void *fclk;
41
42     uint8_t mask;
43     uint16_t stat;
44     uint16_t dma;
45     uint16_t count;
46     int count_cur;
47     uint32_t fifo;
48     int rxlen;
49     int txlen;
50     uint16_t control;
51     uint16_t addr[2];
52     uint8_t divider;
53     uint8_t times[2];
54     uint16_t test;
55 } OMAPI2CState;
56
57 #define OMAP2_INTR_REV  0x34
58 #define OMAP2_GC_REV    0x34
59
60 static void omap_i2c_interrupts_update(OMAPI2CState *s)
61 {
62     qemu_set_irq(s->irq, s->stat & s->mask);
63     if ((s->dma >> 15) & 1)                                     /* RDMA_EN */
64         qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);            /* RRDY */
65     if ((s->dma >> 7) & 1)                                      /* XDMA_EN */
66         qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);            /* XRDY */
67 }
68
69 static void omap_i2c_fifo_run(OMAPI2CState *s)
70 {
71     int ack = 1;
72
73     if (!i2c_bus_busy(s->bus))
74         return;
75
76     if ((s->control >> 2) & 1) {                                /* RM */
77         if ((s->control >> 1) & 1) {                            /* STP */
78             i2c_end_transfer(s->bus);
79             s->control &= ~(1 << 1);                            /* STP */
80             s->count_cur = s->count;
81             s->txlen = 0;
82         } else if ((s->control >> 9) & 1) {                     /* TRX */
83             while (ack && s->txlen)
84                 ack = (i2c_send(s->bus,
85                                         (s->fifo >> ((-- s->txlen) << 3)) &
86                                         0xff) >= 0);
87             s->stat |= 1 << 4;                                  /* XRDY */
88         } else {
89             while (s->rxlen < 4)
90                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
91             s->stat |= 1 << 3;                                  /* RRDY */
92         }
93     } else {
94         if ((s->control >> 9) & 1) {                            /* TRX */
95             while (ack && s->count_cur && s->txlen) {
96                 ack = (i2c_send(s->bus,
97                                         (s->fifo >> ((-- s->txlen) << 3)) &
98                                         0xff) >= 0);
99                 s->count_cur --;
100             }
101             if (ack && s->count_cur)
102                 s->stat |= 1 << 4;                              /* XRDY */
103             else
104                 s->stat &= ~(1 << 4);                           /* XRDY */
105             if (!s->count_cur) {
106                 s->stat |= 1 << 2;                              /* ARDY */
107                 s->control &= ~(1 << 10);                       /* MST */
108             }
109         } else {
110             while (s->count_cur && s->rxlen < 4) {
111                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
112                 s->count_cur --;
113             }
114             if (s->rxlen)
115                 s->stat |= 1 << 3;                              /* RRDY */
116             else
117                 s->stat &= ~(1 << 3);                           /* RRDY */
118         }
119         if (!s->count_cur) {
120             if ((s->control >> 1) & 1) {                        /* STP */
121                 i2c_end_transfer(s->bus);
122                 s->control &= ~(1 << 1);                        /* STP */
123                 s->count_cur = s->count;
124                 s->txlen = 0;
125             } else {
126                 s->stat |= 1 << 2;                              /* ARDY */
127                 s->control &= ~(1 << 10);                       /* MST */
128             }
129         }
130     }
131
132     s->stat |= (!ack) << 1;                                     /* NACK */
133     if (!ack)
134         s->control &= ~(1 << 1);                                /* STP */
135 }
136
137 static void omap_i2c_reset(DeviceState *dev)
138 {
139     OMAPI2CState *s = OMAP_I2C(dev);
140
141     s->mask = 0;
142     s->stat = 0;
143     s->dma = 0;
144     s->count = 0;
145     s->count_cur = 0;
146     s->fifo = 0;
147     s->rxlen = 0;
148     s->txlen = 0;
149     s->control = 0;
150     s->addr[0] = 0;
151     s->addr[1] = 0;
152     s->divider = 0;
153     s->times[0] = 0;
154     s->times[1] = 0;
155     s->test = 0;
156 }
157
158 static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
159 {
160     OMAPI2CState *s = opaque;
161     int offset = addr & OMAP_MPUI_REG_MASK;
162     uint16_t ret;
163
164     switch (offset) {
165     case 0x00:  /* I2C_REV */
166         return s->revision;                                     /* REV */
167
168     case 0x04:  /* I2C_IE */
169         return s->mask;
170
171     case 0x08:  /* I2C_STAT */
172         return s->stat | (i2c_bus_busy(s->bus) << 12);
173
174     case 0x0c:  /* I2C_IV */
175         if (s->revision >= OMAP2_INTR_REV)
176             break;
177         ret = ctz32(s->stat & s->mask);
178         if (ret != 32) {
179             s->stat ^= 1 << ret;
180             ret++;
181         } else {
182             ret = 0;
183         }
184         omap_i2c_interrupts_update(s);
185         return ret;
186
187     case 0x10:  /* I2C_SYSS */
188         return (s->control >> 15) & 1;                          /* I2C_EN */
189
190     case 0x14:  /* I2C_BUF */
191         return s->dma;
192
193     case 0x18:  /* I2C_CNT */
194         return s->count_cur;                                    /* DCOUNT */
195
196     case 0x1c:  /* I2C_DATA */
197         ret = 0;
198         if (s->control & (1 << 14)) {                           /* BE */
199             ret |= ((s->fifo >> 0) & 0xff) << 8;
200             ret |= ((s->fifo >> 8) & 0xff) << 0;
201         } else {
202             ret |= ((s->fifo >> 8) & 0xff) << 8;
203             ret |= ((s->fifo >> 0) & 0xff) << 0;
204         }
205         if (s->rxlen == 1) {
206             s->stat |= 1 << 15;                                 /* SBD */
207             s->rxlen = 0;
208         } else if (s->rxlen > 1) {
209             if (s->rxlen > 2)
210                 s->fifo >>= 16;
211             s->rxlen -= 2;
212         } else {
213             /* XXX: remote access (qualifier) error - what's that?  */
214         }
215         if (!s->rxlen) {
216             s->stat &= ~(1 << 3);                               /* RRDY */
217             if (((s->control >> 10) & 1) &&                     /* MST */
218                             ((~s->control >> 9) & 1)) {         /* TRX */
219                 s->stat |= 1 << 2;                              /* ARDY */
220                 s->control &= ~(1 << 10);                       /* MST */
221             }
222         }
223         s->stat &= ~(1 << 11);                                  /* ROVR */
224         omap_i2c_fifo_run(s);
225         omap_i2c_interrupts_update(s);
226         return ret;
227
228     case 0x20:  /* I2C_SYSC */
229         return 0;
230
231     case 0x24:  /* I2C_CON */
232         return s->control;
233
234     case 0x28:  /* I2C_OA */
235         return s->addr[0];
236
237     case 0x2c:  /* I2C_SA */
238         return s->addr[1];
239
240     case 0x30:  /* I2C_PSC */
241         return s->divider;
242
243     case 0x34:  /* I2C_SCLL */
244         return s->times[0];
245
246     case 0x38:  /* I2C_SCLH */
247         return s->times[1];
248
249     case 0x3c:  /* I2C_SYSTEST */
250         if (s->test & (1 << 15)) {                              /* ST_EN */
251             s->test ^= 0xa;
252             return s->test;
253         } else
254             return s->test & ~0x300f;
255     }
256
257     OMAP_BAD_REG(addr);
258     return 0;
259 }
260
261 static void omap_i2c_write(void *opaque, hwaddr addr,
262                 uint32_t value)
263 {
264     OMAPI2CState *s = opaque;
265     int offset = addr & OMAP_MPUI_REG_MASK;
266     int nack;
267
268     switch (offset) {
269     case 0x00:  /* I2C_REV */
270     case 0x0c:  /* I2C_IV */
271     case 0x10:  /* I2C_SYSS */
272         OMAP_RO_REG(addr);
273         return;
274
275     case 0x04:  /* I2C_IE */
276         s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
277         break;
278
279     case 0x08:  /* I2C_STAT */
280         if (s->revision < OMAP2_INTR_REV) {
281             OMAP_RO_REG(addr);
282             return;
283         }
284
285         /* RRDY and XRDY are reset by hardware. (in all versions???) */
286         s->stat &= ~(value & 0x27);
287         omap_i2c_interrupts_update(s);
288         break;
289
290     case 0x14:  /* I2C_BUF */
291         s->dma = value & 0x8080;
292         if (value & (1 << 15))                                  /* RDMA_EN */
293             s->mask &= ~(1 << 3);                               /* RRDY_IE */
294         if (value & (1 << 7))                                   /* XDMA_EN */
295             s->mask &= ~(1 << 4);                               /* XRDY_IE */
296         break;
297
298     case 0x18:  /* I2C_CNT */
299         s->count = value;                                       /* DCOUNT */
300         break;
301
302     case 0x1c:  /* I2C_DATA */
303         if (s->txlen > 2) {
304             /* XXX: remote access (qualifier) error - what's that?  */
305             break;
306         }
307         s->fifo <<= 16;
308         s->txlen += 2;
309         if (s->control & (1 << 14)) {                           /* BE */
310             s->fifo |= ((value >> 8) & 0xff) << 8;
311             s->fifo |= ((value >> 0) & 0xff) << 0;
312         } else {
313             s->fifo |= ((value >> 0) & 0xff) << 8;
314             s->fifo |= ((value >> 8) & 0xff) << 0;
315         }
316         s->stat &= ~(1 << 10);                                  /* XUDF */
317         if (s->txlen > 2)
318             s->stat &= ~(1 << 4);                               /* XRDY */
319         omap_i2c_fifo_run(s);
320         omap_i2c_interrupts_update(s);
321         break;
322
323     case 0x20:  /* I2C_SYSC */
324         if (s->revision < OMAP2_INTR_REV) {
325             OMAP_BAD_REG(addr);
326             return;
327         }
328
329         if (value & 2) {
330             omap_i2c_reset(DEVICE(s));
331         }
332         break;
333
334     case 0x24:  /* I2C_CON */
335         s->control = value & 0xcf87;
336         if (~value & (1 << 15)) {                               /* I2C_EN */
337             if (s->revision < OMAP2_INTR_REV) {
338                 omap_i2c_reset(DEVICE(s));
339             }
340             break;
341         }
342         if ((value & (1 << 15)) && !(value & (1 << 10))) {      /* MST */
343             fprintf(stderr, "%s: I^2C slave mode not supported\n",
344                             __func__);
345             break;
346         }
347         if ((value & (1 << 15)) && value & (1 << 8)) {          /* XA */
348             fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
349                             __func__);
350             break;
351         }
352         if ((value & (1 << 15)) && value & (1 << 0)) {          /* STT */
353             nack = !!i2c_start_transfer(s->bus, s->addr[1],     /* SA */
354                             (~value >> 9) & 1);                 /* TRX */
355             s->stat |= nack << 1;                               /* NACK */
356             s->control &= ~(1 << 0);                            /* STT */
357             s->fifo = 0;
358             if (nack)
359                 s->control &= ~(1 << 1);                        /* STP */
360             else {
361                 s->count_cur = s->count;
362                 omap_i2c_fifo_run(s);
363             }
364             omap_i2c_interrupts_update(s);
365         }
366         break;
367
368     case 0x28:  /* I2C_OA */
369         s->addr[0] = value & 0x3ff;
370         break;
371
372     case 0x2c:  /* I2C_SA */
373         s->addr[1] = value & 0x3ff;
374         break;
375
376     case 0x30:  /* I2C_PSC */
377         s->divider = value;
378         break;
379
380     case 0x34:  /* I2C_SCLL */
381         s->times[0] = value;
382         break;
383
384     case 0x38:  /* I2C_SCLH */
385         s->times[1] = value;
386         break;
387
388     case 0x3c:  /* I2C_SYSTEST */
389         s->test = value & 0xf80f;
390         if (value & (1 << 11))                                  /* SBB */
391             if (s->revision >= OMAP2_INTR_REV) {
392                 s->stat |= 0x3f;
393                 omap_i2c_interrupts_update(s);
394             }
395         if (value & (1 << 15))                                  /* ST_EN */
396             fprintf(stderr, "%s: System Test not supported\n", __func__);
397         break;
398
399     default:
400         OMAP_BAD_REG(addr);
401         return;
402     }
403 }
404
405 static void omap_i2c_writeb(void *opaque, hwaddr addr,
406                 uint32_t value)
407 {
408     OMAPI2CState *s = opaque;
409     int offset = addr & OMAP_MPUI_REG_MASK;
410
411     switch (offset) {
412     case 0x1c:  /* I2C_DATA */
413         if (s->txlen > 2) {
414             /* XXX: remote access (qualifier) error - what's that?  */
415             break;
416         }
417         s->fifo <<= 8;
418         s->txlen += 1;
419         s->fifo |= value & 0xff;
420         s->stat &= ~(1 << 10);                                  /* XUDF */
421         if (s->txlen > 2)
422             s->stat &= ~(1 << 4);                               /* XRDY */
423         omap_i2c_fifo_run(s);
424         omap_i2c_interrupts_update(s);
425         break;
426
427     default:
428         OMAP_BAD_REG(addr);
429         return;
430     }
431 }
432
433 static uint64_t omap_i2c_readfn(void *opaque, hwaddr addr,
434                                 unsigned size)
435 {
436     switch (size) {
437     case 2:
438         return omap_i2c_read(opaque, addr);
439     default:
440         return omap_badwidth_read16(opaque, addr);
441     }
442 }
443
444 static void omap_i2c_writefn(void *opaque, hwaddr addr,
445                              uint64_t value, unsigned size)
446 {
447     switch (size) {
448     case 1:
449         /* Only the last fifo write can be 8 bit. */
450         omap_i2c_writeb(opaque, addr, value);
451         break;
452     case 2:
453         omap_i2c_write(opaque, addr, value);
454         break;
455     default:
456         omap_badwidth_write16(opaque, addr, value);
457         break;
458     }
459 }
460
461 static const MemoryRegionOps omap_i2c_ops = {
462     .read = omap_i2c_readfn,
463     .write = omap_i2c_writefn,
464     .valid.min_access_size = 1,
465     .valid.max_access_size = 4,
466     .endianness = DEVICE_NATIVE_ENDIAN,
467 };
468
469 static void omap_i2c_init(Object *obj)
470 {
471     DeviceState *dev = DEVICE(obj);
472     OMAPI2CState *s = OMAP_I2C(obj);
473     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
474
475     sysbus_init_irq(sbd, &s->irq);
476     sysbus_init_irq(sbd, &s->drq[0]);
477     sysbus_init_irq(sbd, &s->drq[1]);
478     sysbus_init_mmio(sbd, &s->iomem);
479     s->bus = i2c_init_bus(dev, NULL);
480 }
481
482 static void omap_i2c_realize(DeviceState *dev, Error **errp)
483 {
484     OMAPI2CState *s = OMAP_I2C(dev);
485
486     memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
487                           (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
488
489     if (!s->fclk) {
490         error_setg(errp, "omap_i2c: fclk not connected");
491         return;
492     }
493     if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
494         /* Note that OMAP1 doesn't have a separate interface clock */
495         error_setg(errp, "omap_i2c: iclk not connected");
496         return;
497     }
498 }
499
500 static Property omap_i2c_properties[] = {
501     DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
502     DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
503     DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
504     DEFINE_PROP_END_OF_LIST(),
505 };
506
507 static void omap_i2c_class_init(ObjectClass *klass, void *data)
508 {
509     DeviceClass *dc = DEVICE_CLASS(klass);
510
511     dc->props = omap_i2c_properties;
512     dc->reset = omap_i2c_reset;
513     /* Reason: pointer properties "iclk", "fclk" */
514     dc->user_creatable = false;
515     dc->realize = omap_i2c_realize;
516 }
517
518 static const TypeInfo omap_i2c_info = {
519     .name = TYPE_OMAP_I2C,
520     .parent = TYPE_SYS_BUS_DEVICE,
521     .instance_size = sizeof(OMAPI2CState),
522     .instance_init = omap_i2c_init,
523     .class_init = omap_i2c_class_init,
524 };
525
526 static void omap_i2c_register_types(void)
527 {
528     type_register_static(&omap_i2c_info);
529 }
530
531 I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
532 {
533     OMAPI2CState *s = OMAP_I2C(omap_i2c);
534     return s->bus;
535 }
536
537 type_init(omap_i2c_register_types)
This page took 0.053482 seconds and 4 git commands to generate.