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