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