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