xref: /openbmc/qemu/hw/i2c/omap_i2c.c (revision b8bcf811)
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 = ffs(s->stat & s->mask);
175         if (ret)
176             s->stat ^= 1 << (ret - 1);
177         omap_i2c_interrupts_update(s);
178         return ret;
179 
180     case 0x10:	/* I2C_SYSS */
181         return (s->control >> 15) & 1;				/* I2C_EN */
182 
183     case 0x14:	/* I2C_BUF */
184         return s->dma;
185 
186     case 0x18:	/* I2C_CNT */
187         return s->count_cur;					/* DCOUNT */
188 
189     case 0x1c:	/* I2C_DATA */
190         ret = 0;
191         if (s->control & (1 << 14)) {				/* BE */
192             ret |= ((s->fifo >> 0) & 0xff) << 8;
193             ret |= ((s->fifo >> 8) & 0xff) << 0;
194         } else {
195             ret |= ((s->fifo >> 8) & 0xff) << 8;
196             ret |= ((s->fifo >> 0) & 0xff) << 0;
197         }
198         if (s->rxlen == 1) {
199             s->stat |= 1 << 15;					/* SBD */
200             s->rxlen = 0;
201         } else if (s->rxlen > 1) {
202             if (s->rxlen > 2)
203                 s->fifo >>= 16;
204             s->rxlen -= 2;
205         } else {
206             /* XXX: remote access (qualifier) error - what's that?  */
207         }
208         if (!s->rxlen) {
209             s->stat &= ~(1 << 3);				/* RRDY */
210             if (((s->control >> 10) & 1) &&			/* MST */
211                             ((~s->control >> 9) & 1)) {		/* TRX */
212                 s->stat |= 1 << 2;				/* ARDY */
213                 s->control &= ~(1 << 10);			/* MST */
214             }
215         }
216         s->stat &= ~(1 << 11);					/* ROVR */
217         omap_i2c_fifo_run(s);
218         omap_i2c_interrupts_update(s);
219         return ret;
220 
221     case 0x20:	/* I2C_SYSC */
222         return 0;
223 
224     case 0x24:	/* I2C_CON */
225         return s->control;
226 
227     case 0x28:	/* I2C_OA */
228         return s->addr[0];
229 
230     case 0x2c:	/* I2C_SA */
231         return s->addr[1];
232 
233     case 0x30:	/* I2C_PSC */
234         return s->divider;
235 
236     case 0x34:	/* I2C_SCLL */
237         return s->times[0];
238 
239     case 0x38:	/* I2C_SCLH */
240         return s->times[1];
241 
242     case 0x3c:	/* I2C_SYSTEST */
243         if (s->test & (1 << 15)) {				/* ST_EN */
244             s->test ^= 0xa;
245             return s->test;
246         } else
247             return s->test & ~0x300f;
248     }
249 
250     OMAP_BAD_REG(addr);
251     return 0;
252 }
253 
254 static void omap_i2c_write(void *opaque, hwaddr addr,
255                 uint32_t value)
256 {
257     OMAPI2CState *s = opaque;
258     int offset = addr & OMAP_MPUI_REG_MASK;
259     int nack;
260 
261     switch (offset) {
262     case 0x00:	/* I2C_REV */
263     case 0x0c:	/* I2C_IV */
264     case 0x10:	/* I2C_SYSS */
265         OMAP_RO_REG(addr);
266         return;
267 
268     case 0x04:	/* I2C_IE */
269         s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
270         break;
271 
272     case 0x08:	/* I2C_STAT */
273         if (s->revision < OMAP2_INTR_REV) {
274             OMAP_RO_REG(addr);
275             return;
276         }
277 
278         /* RRDY and XRDY are reset by hardware. (in all versions???) */
279         s->stat &= ~(value & 0x27);
280         omap_i2c_interrupts_update(s);
281         break;
282 
283     case 0x14:	/* I2C_BUF */
284         s->dma = value & 0x8080;
285         if (value & (1 << 15))					/* RDMA_EN */
286             s->mask &= ~(1 << 3);				/* RRDY_IE */
287         if (value & (1 << 7))					/* XDMA_EN */
288             s->mask &= ~(1 << 4);				/* XRDY_IE */
289         break;
290 
291     case 0x18:	/* I2C_CNT */
292         s->count = value;					/* DCOUNT */
293         break;
294 
295     case 0x1c:	/* I2C_DATA */
296         if (s->txlen > 2) {
297             /* XXX: remote access (qualifier) error - what's that?  */
298             break;
299         }
300         s->fifo <<= 16;
301         s->txlen += 2;
302         if (s->control & (1 << 14)) {				/* BE */
303             s->fifo |= ((value >> 8) & 0xff) << 8;
304             s->fifo |= ((value >> 0) & 0xff) << 0;
305         } else {
306             s->fifo |= ((value >> 0) & 0xff) << 8;
307             s->fifo |= ((value >> 8) & 0xff) << 0;
308         }
309         s->stat &= ~(1 << 10);					/* XUDF */
310         if (s->txlen > 2)
311             s->stat &= ~(1 << 4);				/* XRDY */
312         omap_i2c_fifo_run(s);
313         omap_i2c_interrupts_update(s);
314         break;
315 
316     case 0x20:	/* I2C_SYSC */
317         if (s->revision < OMAP2_INTR_REV) {
318             OMAP_BAD_REG(addr);
319             return;
320         }
321 
322         if (value & 2) {
323             omap_i2c_reset(DEVICE(s));
324         }
325         break;
326 
327     case 0x24:	/* I2C_CON */
328         s->control = value & 0xcf87;
329         if (~value & (1 << 15)) {				/* I2C_EN */
330             if (s->revision < OMAP2_INTR_REV) {
331                 omap_i2c_reset(DEVICE(s));
332             }
333             break;
334         }
335         if ((value & (1 << 15)) && !(value & (1 << 10))) {	/* MST */
336             fprintf(stderr, "%s: I^2C slave mode not supported\n",
337                             __FUNCTION__);
338             break;
339         }
340         if ((value & (1 << 15)) && value & (1 << 8)) {		/* XA */
341             fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
342                             __FUNCTION__);
343             break;
344         }
345         if ((value & (1 << 15)) && value & (1 << 0)) {		/* STT */
346             nack = !!i2c_start_transfer(s->bus, s->addr[1],	/* SA */
347                             (~value >> 9) & 1);			/* TRX */
348             s->stat |= nack << 1;				/* NACK */
349             s->control &= ~(1 << 0);				/* STT */
350             s->fifo = 0;
351             if (nack)
352                 s->control &= ~(1 << 1);			/* STP */
353             else {
354                 s->count_cur = s->count;
355                 omap_i2c_fifo_run(s);
356             }
357             omap_i2c_interrupts_update(s);
358         }
359         break;
360 
361     case 0x28:	/* I2C_OA */
362         s->addr[0] = value & 0x3ff;
363         break;
364 
365     case 0x2c:	/* I2C_SA */
366         s->addr[1] = value & 0x3ff;
367         break;
368 
369     case 0x30:	/* I2C_PSC */
370         s->divider = value;
371         break;
372 
373     case 0x34:	/* I2C_SCLL */
374         s->times[0] = value;
375         break;
376 
377     case 0x38:	/* I2C_SCLH */
378         s->times[1] = value;
379         break;
380 
381     case 0x3c:	/* I2C_SYSTEST */
382         s->test = value & 0xf80f;
383         if (value & (1 << 11))					/* SBB */
384             if (s->revision >= OMAP2_INTR_REV) {
385                 s->stat |= 0x3f;
386                 omap_i2c_interrupts_update(s);
387             }
388         if (value & (1 << 15))					/* ST_EN */
389             fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
390         break;
391 
392     default:
393         OMAP_BAD_REG(addr);
394         return;
395     }
396 }
397 
398 static void omap_i2c_writeb(void *opaque, hwaddr addr,
399                 uint32_t value)
400 {
401     OMAPI2CState *s = opaque;
402     int offset = addr & OMAP_MPUI_REG_MASK;
403 
404     switch (offset) {
405     case 0x1c:	/* I2C_DATA */
406         if (s->txlen > 2) {
407             /* XXX: remote access (qualifier) error - what's that?  */
408             break;
409         }
410         s->fifo <<= 8;
411         s->txlen += 1;
412         s->fifo |= value & 0xff;
413         s->stat &= ~(1 << 10);					/* XUDF */
414         if (s->txlen > 2)
415             s->stat &= ~(1 << 4);				/* XRDY */
416         omap_i2c_fifo_run(s);
417         omap_i2c_interrupts_update(s);
418         break;
419 
420     default:
421         OMAP_BAD_REG(addr);
422         return;
423     }
424 }
425 
426 static const MemoryRegionOps omap_i2c_ops = {
427     .old_mmio = {
428         .read = {
429             omap_badwidth_read16,
430             omap_i2c_read,
431             omap_badwidth_read16,
432         },
433         .write = {
434             omap_i2c_writeb, /* Only the last fifo write can be 8 bit.  */
435             omap_i2c_write,
436             omap_badwidth_write16,
437         },
438     },
439     .endianness = DEVICE_NATIVE_ENDIAN,
440 };
441 
442 static int omap_i2c_init(SysBusDevice *sbd)
443 {
444     DeviceState *dev = DEVICE(sbd);
445     OMAPI2CState *s = OMAP_I2C(dev);
446 
447     if (!s->fclk) {
448         hw_error("omap_i2c: fclk not connected\n");
449     }
450     if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
451         /* Note that OMAP1 doesn't have a separate interface clock */
452         hw_error("omap_i2c: iclk not connected\n");
453     }
454     sysbus_init_irq(sbd, &s->irq);
455     sysbus_init_irq(sbd, &s->drq[0]);
456     sysbus_init_irq(sbd, &s->drq[1]);
457     memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
458                           (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
459     sysbus_init_mmio(sbd, &s->iomem);
460     s->bus = i2c_init_bus(dev, NULL);
461     return 0;
462 }
463 
464 static Property omap_i2c_properties[] = {
465     DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
466     DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
467     DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
468     DEFINE_PROP_END_OF_LIST(),
469 };
470 
471 static void omap_i2c_class_init(ObjectClass *klass, void *data)
472 {
473     DeviceClass *dc = DEVICE_CLASS(klass);
474     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
475     k->init = omap_i2c_init;
476     dc->props = omap_i2c_properties;
477     dc->reset = omap_i2c_reset;
478     /* Reason: pointer properties "iclk", "fclk" */
479     dc->cannot_instantiate_with_device_add_yet = true;
480 }
481 
482 static const TypeInfo omap_i2c_info = {
483     .name = TYPE_OMAP_I2C,
484     .parent = TYPE_SYS_BUS_DEVICE,
485     .instance_size = sizeof(OMAPI2CState),
486     .class_init = omap_i2c_class_init,
487 };
488 
489 static void omap_i2c_register_types(void)
490 {
491     type_register_static(&omap_i2c_info);
492 }
493 
494 I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
495 {
496     OMAPI2CState *s = OMAP_I2C(omap_i2c);
497     return s->bus;
498 }
499 
500 type_init(omap_i2c_register_types)
501