Remove most uses of phys_ram_base (initial patch by Ian Jackson)
[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     target_phys_addr_t base;
27     qemu_irq irq;
28     qemu_irq drq[2];
29     i2c_slave slave;
30     i2c_bus *bus;
31
32     uint8_t revision;
33     uint8_t mask;
34     uint16_t stat;
35     uint16_t dma;
36     uint16_t count;
37     int count_cur;
38     uint32_t fifo;
39     int rxlen;
40     int txlen;
41     uint16_t control;
42     uint16_t addr[2];
43     uint8_t divider;
44     uint8_t times[2];
45     uint16_t test;
46 };
47
48 #define OMAP2_INTR_REV  0x34
49 #define OMAP2_GC_REV    0x34
50
51 static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
52 {
53     qemu_set_irq(s->irq, s->stat & s->mask);
54     if ((s->dma >> 15) & 1)                                     /* RDMA_EN */
55         qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);            /* RRDY */
56     if ((s->dma >> 7) & 1)                                      /* XDMA_EN */
57         qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);            /* XRDY */
58 }
59
60 /* These are only stubs now.  */
61 static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
62 {
63     struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
64
65     if ((~s->control >> 15) & 1)                                /* I2C_EN */
66         return;
67
68     switch (event) {
69     case I2C_START_SEND:
70     case I2C_START_RECV:
71         s->stat |= 1 << 9;                                      /* AAS */
72         break;
73     case I2C_FINISH:
74         s->stat |= 1 << 2;                                      /* ARDY */
75         break;
76     case I2C_NACK:
77         s->stat |= 1 << 1;                                      /* NACK */
78         break;
79     }
80
81     omap_i2c_interrupts_update(s);
82 }
83
84 static int omap_i2c_rx(i2c_slave *i2c)
85 {
86     struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
87     uint8_t ret = 0;
88
89     if ((~s->control >> 15) & 1)                                /* I2C_EN */
90         return -1;
91
92     if (s->txlen)
93         ret = s->fifo >> ((-- s->txlen) << 3) & 0xff;
94     else
95         s->stat |= 1 << 10;                                     /* XUDF */
96     s->stat |= 1 << 4;                                          /* XRDY */
97
98     omap_i2c_interrupts_update(s);
99     return ret;
100 }
101
102 static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
103 {
104     struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
105
106     if ((~s->control >> 15) & 1)                                /* I2C_EN */
107         return 1;
108
109     if (s->rxlen < 4)
110         s->fifo |= data << ((s->rxlen ++) << 3);
111     else
112         s->stat |= 1 << 11;                                     /* ROVR */
113     s->stat |= 1 << 3;                                          /* RRDY */
114
115     omap_i2c_interrupts_update(s);
116     return 1;
117 }
118
119 static void omap_i2c_fifo_run(struct omap_i2c_s *s)
120 {
121     int ack = 1;
122
123     if (!i2c_bus_busy(s->bus))
124         return;
125
126     if ((s->control >> 2) & 1) {                                /* RM */
127         if ((s->control >> 1) & 1) {                            /* STP */
128             i2c_end_transfer(s->bus);
129             s->control &= ~(1 << 1);                            /* STP */
130             s->count_cur = s->count;
131             s->txlen = 0;
132         } else if ((s->control >> 9) & 1) {                     /* TRX */
133             while (ack && s->txlen)
134                 ack = (i2c_send(s->bus,
135                                         (s->fifo >> ((-- s->txlen) << 3)) &
136                                         0xff) >= 0);
137             s->stat |= 1 << 4;                                  /* XRDY */
138         } else {
139             while (s->rxlen < 4)
140                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
141             s->stat |= 1 << 3;                                  /* RRDY */
142         }
143     } else {
144         if ((s->control >> 9) & 1) {                            /* TRX */
145             while (ack && s->count_cur && s->txlen) {
146                 ack = (i2c_send(s->bus,
147                                         (s->fifo >> ((-- s->txlen) << 3)) &
148                                         0xff) >= 0);
149                 s->count_cur --;
150             }
151             if (ack && s->count_cur)
152                 s->stat |= 1 << 4;                              /* XRDY */
153             else
154                 s->stat &= ~(1 << 4);                           /* XRDY */
155             if (!s->count_cur) {
156                 s->stat |= 1 << 2;                              /* ARDY */
157                 s->control &= ~(1 << 10);                       /* MST */
158             }
159         } else {
160             while (s->count_cur && s->rxlen < 4) {
161                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
162                 s->count_cur --;
163             }
164             if (s->rxlen)
165                 s->stat |= 1 << 3;                              /* RRDY */
166             else
167                 s->stat &= ~(1 << 3);                           /* RRDY */
168         }
169         if (!s->count_cur) {
170             if ((s->control >> 1) & 1) {                        /* STP */
171                 i2c_end_transfer(s->bus);
172                 s->control &= ~(1 << 1);                        /* STP */
173                 s->count_cur = s->count;
174                 s->txlen = 0;
175             } else {
176                 s->stat |= 1 << 2;                              /* ARDY */
177                 s->control &= ~(1 << 10);                       /* MST */
178             }
179         }
180     }
181
182     s->stat |= (!ack) << 1;                                     /* NACK */
183     if (!ack)
184         s->control &= ~(1 << 1);                                /* STP */
185 }
186
187 void omap_i2c_reset(struct omap_i2c_s *s)
188 {
189     s->mask = 0;
190     s->stat = 0;
191     s->dma = 0;
192     s->count = 0;
193     s->count_cur = 0;
194     s->fifo = 0;
195     s->rxlen = 0;
196     s->txlen = 0;
197     s->control = 0;
198     s->addr[0] = 0;
199     s->addr[1] = 0;
200     s->divider = 0;
201     s->times[0] = 0;
202     s->times[1] = 0;
203     s->test = 0;
204 }
205
206 static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
207 {
208     struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
209     int offset = addr & OMAP_MPUI_REG_MASK;
210     uint16_t ret;
211
212     switch (offset) {
213     case 0x00:  /* I2C_REV */
214         return s->revision;                                     /* REV */
215
216     case 0x04:  /* I2C_IE */
217         return s->mask;
218
219     case 0x08:  /* I2C_STAT */
220         return s->stat | (i2c_bus_busy(s->bus) << 12);
221
222     case 0x0c:  /* I2C_IV */
223         if (s->revision >= OMAP2_INTR_REV)
224             break;
225         ret = ffs(s->stat & s->mask);
226         if (ret)
227             s->stat ^= 1 << (ret - 1);
228         omap_i2c_interrupts_update(s);
229         return ret;
230
231     case 0x10:  /* I2C_SYSS */
232         return (s->control >> 15) & 1;                          /* I2C_EN */
233
234     case 0x14:  /* I2C_BUF */
235         return s->dma;
236
237     case 0x18:  /* I2C_CNT */
238         return s->count_cur;                                    /* DCOUNT */
239
240     case 0x1c:  /* I2C_DATA */
241         ret = 0;
242         if (s->control & (1 << 14)) {                           /* BE */
243             ret |= ((s->fifo >> 0) & 0xff) << 8;
244             ret |= ((s->fifo >> 8) & 0xff) << 0;
245         } else {
246             ret |= ((s->fifo >> 8) & 0xff) << 8;
247             ret |= ((s->fifo >> 0) & 0xff) << 0;
248         }
249         if (s->rxlen == 1) {
250             s->stat |= 1 << 15;                                 /* SBD */
251             s->rxlen = 0;
252         } else if (s->rxlen > 1) {
253             if (s->rxlen > 2)
254                 s->fifo >>= 16;
255             s->rxlen -= 2;
256         } else
257             /* XXX: remote access (qualifier) error - what's that?  */;
258         if (!s->rxlen) {
259             s->stat &= ~(1 << 3);                               /* RRDY */
260             if (((s->control >> 10) & 1) &&                     /* MST */
261                             ((~s->control >> 9) & 1)) {         /* TRX */
262                 s->stat |= 1 << 2;                              /* ARDY */
263                 s->control &= ~(1 << 10);                       /* MST */
264             }
265         }
266         s->stat &= ~(1 << 11);                                  /* ROVR */
267         omap_i2c_fifo_run(s);
268         omap_i2c_interrupts_update(s);
269         return ret;
270
271     case 0x20:  /* I2C_SYSC */
272         return 0;
273
274     case 0x24:  /* I2C_CON */
275         return s->control;
276
277     case 0x28:  /* I2C_OA */
278         return s->addr[0];
279
280     case 0x2c:  /* I2C_SA */
281         return s->addr[1];
282
283     case 0x30:  /* I2C_PSC */
284         return s->divider;
285
286     case 0x34:  /* I2C_SCLL */
287         return s->times[0];
288
289     case 0x38:  /* I2C_SCLH */
290         return s->times[1];
291
292     case 0x3c:  /* I2C_SYSTEST */
293         if (s->test & (1 << 15)) {                              /* ST_EN */
294             s->test ^= 0xa;
295             return s->test;
296         } else
297             return s->test & ~0x300f;
298     }
299
300     OMAP_BAD_REG(addr);
301     return 0;
302 }
303
304 static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
305                 uint32_t value)
306 {
307     struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
308     int offset = addr & OMAP_MPUI_REG_MASK;
309     int nack;
310
311     switch (offset) {
312     case 0x00:  /* I2C_REV */
313     case 0x0c:  /* I2C_IV */
314     case 0x10:  /* I2C_SYSS */
315         OMAP_RO_REG(addr);
316         return;
317
318     case 0x04:  /* I2C_IE */
319         s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
320         break;
321
322     case 0x08:  /* I2C_STAT */
323         if (s->revision < OMAP2_INTR_REV) {
324             OMAP_RO_REG(addr);
325             return;
326         }
327
328         /* RRDY and XRDY are reset by hardware. (in all versions???) */
329         s->stat &= ~(value & 0x27);
330         omap_i2c_interrupts_update(s);
331         break;
332
333     case 0x14:  /* I2C_BUF */
334         s->dma = value & 0x8080;
335         if (value & (1 << 15))                                  /* RDMA_EN */
336             s->mask &= ~(1 << 3);                               /* RRDY_IE */
337         if (value & (1 << 7))                                   /* XDMA_EN */
338             s->mask &= ~(1 << 4);                               /* XRDY_IE */
339         break;
340
341     case 0x18:  /* I2C_CNT */
342         s->count = value;                                       /* DCOUNT */
343         break;
344
345     case 0x1c:  /* I2C_DATA */
346         if (s->txlen > 2) {
347             /* XXX: remote access (qualifier) error - what's that?  */
348             break;
349         }
350         s->fifo <<= 16;
351         s->txlen += 2;
352         if (s->control & (1 << 14)) {                           /* BE */
353             s->fifo |= ((value >> 8) & 0xff) << 8;
354             s->fifo |= ((value >> 0) & 0xff) << 0;
355         } else {
356             s->fifo |= ((value >> 0) & 0xff) << 8;
357             s->fifo |= ((value >> 8) & 0xff) << 0;
358         }
359         s->stat &= ~(1 << 10);                                  /* XUDF */
360         if (s->txlen > 2)
361             s->stat &= ~(1 << 4);                               /* XRDY */
362         omap_i2c_fifo_run(s);
363         omap_i2c_interrupts_update(s);
364         break;
365
366     case 0x20:  /* I2C_SYSC */
367         if (s->revision < OMAP2_INTR_REV) {
368             OMAP_BAD_REG(addr);
369             return;
370         }
371
372         if (value & 2)
373             omap_i2c_reset(s);
374         break;
375
376     case 0x24:  /* I2C_CON */
377         s->control = value & 0xcf87;
378         if (~value & (1 << 15)) {                               /* I2C_EN */
379             if (s->revision < OMAP2_INTR_REV)
380                 omap_i2c_reset(s);
381             break;
382         }
383         if ((value & (1 << 15)) && !(value & (1 << 10))) {      /* MST */
384             fprintf(stderr, "%s: I^2C slave mode not supported\n",
385                             __FUNCTION__);
386             break;
387         }
388         if ((value & (1 << 15)) && value & (1 << 8)) {          /* XA */
389             fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
390                             __FUNCTION__);
391             break;
392         }
393         if ((value & (1 << 15)) && value & (1 << 0)) {          /* STT */
394             nack = !!i2c_start_transfer(s->bus, s->addr[1],     /* SA */
395                             (~value >> 9) & 1);                 /* TRX */
396             s->stat |= nack << 1;                               /* NACK */
397             s->control &= ~(1 << 0);                            /* STT */
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->base = base;
496     s->irq = irq;
497     s->drq[0] = dma[0];
498     s->drq[1] = dma[1];
499     s->slave.event = omap_i2c_event;
500     s->slave.recv = omap_i2c_rx;
501     s->slave.send = omap_i2c_tx;
502     s->bus = i2c_init_bus();
503     omap_i2c_reset(s);
504
505     iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
506                     omap_i2c_writefn, s);
507     cpu_register_physical_memory(s->base, 0x800, iomemtype);
508
509     return s;
510 }
511
512 struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta,
513                 qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk)
514 {
515     int iomemtype;
516     struct omap_i2c_s *s = (struct omap_i2c_s *)
517             qemu_mallocz(sizeof(struct omap_i2c_s));
518
519     s->revision = 0x34;
520     s->irq = irq;
521     s->drq[0] = dma[0];
522     s->drq[1] = dma[1];
523     s->slave.event = omap_i2c_event;
524     s->slave.recv = omap_i2c_rx;
525     s->slave.send = omap_i2c_tx;
526     s->bus = i2c_init_bus();
527     omap_i2c_reset(s);
528
529     iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
530                     omap_i2c_writefn, s);
531     s->base = omap_l4_attach(ta, 0, iomemtype);
532
533     return s;
534 }
535
536 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
537 {
538     return s->bus;
539 }