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