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