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