xref: /openbmc/qemu/hw/i2c/omap_i2c.c (revision d38ea87a)
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)
510