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