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