xref: /openbmc/qemu/hw/i2c/omap_i2c.c (revision 1ef8185a)
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                             __func__);
345             break;
346         }
347         if ((value & (1 << 15)) && value & (1 << 8)) {		/* XA */
348             fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
349                             __func__);
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", __func__);
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 uint64_t omap_i2c_readfn(void *opaque, hwaddr addr,
434                                 unsigned size)
435 {
436     switch (size) {
437     case 2:
438         return omap_i2c_read(opaque, addr);
439     default:
440         return omap_badwidth_read16(opaque, addr);
441     }
442 }
443 
444 static void omap_i2c_writefn(void *opaque, hwaddr addr,
445                              uint64_t value, unsigned size)
446 {
447     switch (size) {
448     case 1:
449         /* Only the last fifo write can be 8 bit. */
450         omap_i2c_writeb(opaque, addr, value);
451         break;
452     case 2:
453         omap_i2c_write(opaque, addr, value);
454         break;
455     default:
456         omap_badwidth_write16(opaque, addr, value);
457         break;
458     }
459 }
460 
461 static const MemoryRegionOps omap_i2c_ops = {
462     .read = omap_i2c_readfn,
463     .write = omap_i2c_writefn,
464     .valid.min_access_size = 1,
465     .valid.max_access_size = 4,
466     .endianness = DEVICE_NATIVE_ENDIAN,
467 };
468 
469 static void omap_i2c_init(Object *obj)
470 {
471     DeviceState *dev = DEVICE(obj);
472     OMAPI2CState *s = OMAP_I2C(obj);
473     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
474 
475     sysbus_init_irq(sbd, &s->irq);
476     sysbus_init_irq(sbd, &s->drq[0]);
477     sysbus_init_irq(sbd, &s->drq[1]);
478     sysbus_init_mmio(sbd, &s->iomem);
479     s->bus = i2c_init_bus(dev, NULL);
480 }
481 
482 static void omap_i2c_realize(DeviceState *dev, Error **errp)
483 {
484     OMAPI2CState *s = OMAP_I2C(dev);
485 
486     memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
487                           (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
488 
489     if (!s->fclk) {
490         error_setg(errp, "omap_i2c: fclk not connected");
491         return;
492     }
493     if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
494         /* Note that OMAP1 doesn't have a separate interface clock */
495         error_setg(errp, "omap_i2c: iclk not connected");
496         return;
497     }
498 }
499 
500 static Property omap_i2c_properties[] = {
501     DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
502     DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
503     DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
504     DEFINE_PROP_END_OF_LIST(),
505 };
506 
507 static void omap_i2c_class_init(ObjectClass *klass, void *data)
508 {
509     DeviceClass *dc = DEVICE_CLASS(klass);
510 
511     dc->props = omap_i2c_properties;
512     dc->reset = omap_i2c_reset;
513     /* Reason: pointer properties "iclk", "fclk" */
514     dc->user_creatable = false;
515     dc->realize = omap_i2c_realize;
516 }
517 
518 static const TypeInfo omap_i2c_info = {
519     .name = TYPE_OMAP_I2C,
520     .parent = TYPE_SYS_BUS_DEVICE,
521     .instance_size = sizeof(OMAPI2CState),
522     .instance_init = omap_i2c_init,
523     .class_init = omap_i2c_class_init,
524 };
525 
526 static void omap_i2c_register_types(void)
527 {
528     type_register_static(&omap_i2c_info);
529 }
530 
531 I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
532 {
533     OMAPI2CState *s = OMAP_I2C(omap_i2c);
534     return s->bus;
535 }
536 
537 type_init(omap_i2c_register_types)
538