Break up vl.h.
[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 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 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 /* These are only stubs now.  */
57 static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
58 {
59     struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
60
61     if ((~s->control >> 15) & 1)                                /* I2C_EN */
62         return;
63
64     switch (event) {
65     case I2C_START_SEND:
66     case I2C_START_RECV:
67         s->stat |= 1 << 9;                                      /* AAS */
68         break;
69     case I2C_FINISH:
70         s->stat |= 1 << 2;                                      /* ARDY */
71         break;
72     case I2C_NACK:
73         s->stat |= 1 << 1;                                      /* NACK */
74         break;
75     }
76
77     omap_i2c_interrupts_update(s);
78 }
79
80 static int omap_i2c_rx(i2c_slave *i2c)
81 {
82     struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
83     uint8_t ret = 0;
84
85     if ((~s->control >> 15) & 1)                                /* I2C_EN */
86         return -1;
87
88     if (s->txlen)
89         ret = s->fifo >> ((-- s->txlen) << 3) & 0xff;
90     else
91         s->stat |= 1 << 10;                                     /* XUDF */
92     s->stat |= 1 << 4;                                          /* XRDY */
93
94     omap_i2c_interrupts_update(s);
95     return ret;
96 }
97
98 static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
99 {
100     struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
101
102     if ((~s->control >> 15) & 1)                                /* I2C_EN */
103         return 1;
104
105     if (s->rxlen < 4)
106         s->fifo |= data << ((s->rxlen ++) << 3);
107     else
108         s->stat |= 1 << 11;                                     /* ROVR */
109     s->stat |= 1 << 3;                                          /* RRDY */
110
111     omap_i2c_interrupts_update(s);
112     return 1;
113 }
114
115 static void omap_i2c_fifo_run(struct omap_i2c_s *s)
116 {
117     int ack = 1;
118
119     if (!i2c_bus_busy(s->bus))
120         return;
121
122     if ((s->control >> 2) & 1) {                                /* RM */
123         if ((s->control >> 1) & 1) {                            /* STP */
124             i2c_end_transfer(s->bus);
125             s->control &= ~(1 << 1);                            /* STP */
126             s->count_cur = s->count;
127         } else if ((s->control >> 9) & 1) {                     /* TRX */
128             while (ack && s->txlen)
129                 ack = (i2c_send(s->bus,
130                                         (s->fifo >> ((-- s->txlen) << 3)) &
131                                         0xff) >= 0);
132             s->stat |= 1 << 4;                                  /* XRDY */
133         } else {
134             while (s->rxlen < 4)
135                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
136             s->stat |= 1 << 3;                                  /* RRDY */
137         }
138     } else {
139         if ((s->control >> 9) & 1) {                            /* TRX */
140             while (ack && s->count_cur && s->txlen) {
141                 ack = (i2c_send(s->bus,
142                                         (s->fifo >> ((-- s->txlen) << 3)) &
143                                         0xff) >= 0);
144                 s->count_cur --;
145             }
146             if (ack && s->count_cur)
147                 s->stat |= 1 << 4;                              /* XRDY */
148             if (!s->count_cur) {
149                 s->stat |= 1 << 2;                              /* ARDY */
150                 s->control &= ~(1 << 10);                       /* MST */
151             }
152         } else {
153             while (s->count_cur && s->rxlen < 4) {
154                 s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
155                 s->count_cur --;
156             }
157             if (s->rxlen)
158                 s->stat |= 1 << 3;                              /* RRDY */
159         }
160         if (!s->count_cur) {
161             if ((s->control >> 1) & 1) {                        /* STP */
162                 i2c_end_transfer(s->bus);
163                 s->control &= ~(1 << 1);                        /* STP */
164                 s->count_cur = s->count;
165             } else {
166                 s->stat |= 1 << 2;                              /* ARDY */
167                 s->control &= ~(1 << 10);                       /* MST */
168             }
169         }
170     }
171
172     s->stat |= (!ack) << 1;                                     /* NACK */
173     if (!ack)
174         s->control &= ~(1 << 1);                                /* STP */
175 }
176
177 void omap_i2c_reset(struct omap_i2c_s *s)
178 {
179     s->mask = 0;
180     s->stat = 0;
181     s->dma = 0;
182     s->count = 0;
183     s->count_cur = 0;
184     s->fifo = 0;
185     s->rxlen = 0;
186     s->txlen = 0;
187     s->control = 0;
188     s->addr[0] = 0;
189     s->addr[1] = 0;
190     s->divider = 0;
191     s->times[0] = 0;
192     s->times[1] = 0;
193     s->test = 0;
194 }
195
196 static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr)
197 {
198     struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
199     int offset = addr & OMAP_MPUI_REG_MASK;
200     uint16_t ret;
201
202     switch (offset) {
203     case 0x00:  /* I2C_REV */
204         /* TODO: set a value greater or equal to real hardware */
205         return 0x11;                                            /* REV */
206
207     case 0x04:  /* I2C_IE */
208         return s->mask;
209
210     case 0x08:  /* I2C_STAT */
211         return s->stat | (i2c_bus_busy(s->bus) << 12);
212
213     case 0x0c:  /* I2C_IV */
214         ret = ffs(s->stat & s->mask);
215         if (ret)
216             s->stat ^= 1 << (ret - 1);
217         omap_i2c_interrupts_update(s);
218         return ret;
219
220     case 0x14:  /* I2C_BUF */
221         return s->dma;
222
223     case 0x18:  /* I2C_CNT */
224         return s->count_cur;                                    /* DCOUNT */
225
226     case 0x1c:  /* I2C_DATA */
227         ret = 0;
228         if (s->control & (1 << 14)) {                           /* BE */
229             ret |= ((s->fifo >> 0) & 0xff) << 8;
230             ret |= ((s->fifo >> 8) & 0xff) << 0;
231         } else {
232             ret |= ((s->fifo >> 8) & 0xff) << 8;
233             ret |= ((s->fifo >> 0) & 0xff) << 0;
234         }
235         if (s->rxlen == 1) {
236             s->stat |= 1 << 15;                                 /* SBD */
237             s->rxlen = 0;
238         } else if (s->rxlen > 1) {
239             if (s->rxlen > 2)
240                 s->fifo >>= 16;
241             s->rxlen -= 2;
242         } else
243             /* XXX: remote access (qualifier) error - what's that?  */;
244         if (!s->rxlen) {
245             s->stat |= ~(1 << 3);                               /* RRDY */
246             if (((s->control >> 10) & 1) &&                     /* MST */
247                             ((~s->control >> 9) & 1)) {         /* TRX */
248                 s->stat |= 1 << 2;                              /* ARDY */
249                 s->control &= ~(1 << 10);                       /* MST */
250             }
251         }
252         s->stat &= ~(1 << 11);                                  /* ROVR */
253         omap_i2c_fifo_run(s);
254         omap_i2c_interrupts_update(s);
255         return ret;
256
257     case 0x24:  /* I2C_CON */
258         return s->control;
259
260     case 0x28:  /* I2C_OA */
261         return s->addr[0];
262
263     case 0x2c:  /* I2C_SA */
264         return s->addr[1];
265
266     case 0x30:  /* I2C_PSC */
267         return s->divider;
268
269     case 0x34:  /* I2C_SCLL */
270         return s->times[0];
271
272     case 0x38:  /* I2C_SCLH */
273         return s->times[1];
274
275     case 0x3c:  /* I2C_SYSTEST */
276         if (s->test & (1 << 15)) {                              /* ST_EN */
277             s->test ^= 0xa;
278             return s->test;
279         } else
280             return s->test & ~0x300f;
281     }
282
283     OMAP_BAD_REG(addr);
284     return 0;
285 }
286
287 static void omap_i2c_write(void *opaque, target_phys_addr_t addr,
288                 uint32_t value)
289 {
290     struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
291     int offset = addr & OMAP_MPUI_REG_MASK;
292     int nack;
293
294     switch (offset) {
295     case 0x00:  /* I2C_REV */
296     case 0x08:  /* I2C_STAT */
297     case 0x0c:  /* I2C_IV */
298         OMAP_BAD_REG(addr);
299         return;
300
301     case 0x04:  /* I2C_IE */
302         s->mask = value & 0x1f;
303         break;
304
305     case 0x14:  /* I2C_BUF */
306         s->dma = value & 0x8080;
307         if (value & (1 << 15))                                  /* RDMA_EN */
308             s->mask &= ~(1 << 3);                               /* RRDY_IE */
309         if (value & (1 << 7))                                   /* XDMA_EN */
310             s->mask &= ~(1 << 4);                               /* XRDY_IE */
311         break;
312
313     case 0x18:  /* I2C_CNT */
314         s->count = value;                                       /* DCOUNT */
315         break;
316
317     case 0x1c:  /* I2C_DATA */
318         if (s->txlen > 2) {
319             /* XXX: remote access (qualifier) error - what's that?  */
320             break;
321         }
322         s->fifo <<= 16;
323         s->txlen += 2;
324         if (s->control & (1 << 14)) {                           /* BE */
325             s->fifo |= ((value >> 8) & 0xff) << 8;
326             s->fifo |= ((value >> 0) & 0xff) << 0;
327         } else {
328             s->fifo |= ((value >> 0) & 0xff) << 8;
329             s->fifo |= ((value >> 8) & 0xff) << 0;
330         }
331         s->stat &= ~(1 << 10);                                  /* XUDF */
332         if (s->txlen > 2)
333             s->stat &= ~(1 << 4);                               /* XRDY */
334         omap_i2c_fifo_run(s);
335         omap_i2c_interrupts_update(s);
336         break;
337
338     case 0x24:  /* I2C_CON */
339         s->control = value & 0xcf07;
340         if (~value & (1 << 15)) {                               /* I2C_EN */
341             omap_i2c_reset(s);
342             break;
343         }
344         if (~value & (1 << 10)) {                               /* MST */
345             printf("%s: I^2C slave mode not supported\n", __FUNCTION__);
346             break;
347         }
348         if (value & (1 << 9)) {                                 /* XA */
349             printf("%s: 10-bit addressing mode not supported\n", __FUNCTION__);
350             break;
351         }
352         if (value & (1 << 0)) {                                 /* STT */
353             nack = !!i2c_start_transfer(s->bus, s->addr[1],     /* SA */
354                             (~value >> 9) & 1);                 /* TRX */
355             s->stat |= nack << 1;                               /* NACK */
356             s->control &= ~(1 << 0);                            /* STT */
357             if (nack)
358                 s->control &= ~(1 << 1);                        /* STP */
359             else
360                 omap_i2c_fifo_run(s);
361             omap_i2c_interrupts_update(s);
362         }
363         break;
364
365     case 0x28:  /* I2C_OA */
366         s->addr[0] = value & 0x3ff;
367         i2c_set_slave_address(&s->slave, value & 0x7f);
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 & 0xf00f;
388         if (value & (1 << 15))                                  /* ST_EN */
389             printf("%s: System Test not supported\n", __FUNCTION__);
390         break;
391
392     default:
393         OMAP_BAD_REG(addr);
394         return;
395     }
396 }
397
398 static CPUReadMemoryFunc *omap_i2c_readfn[] = {
399     omap_badwidth_read16,
400     omap_i2c_read,
401     omap_badwidth_read16,
402 };
403
404 static CPUWriteMemoryFunc *omap_i2c_writefn[] = {
405     omap_badwidth_write16,
406     omap_i2c_write,
407     omap_i2c_write,     /* TODO: Only the last fifo write can be 8 bit.  */
408 };
409
410 struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
411                 qemu_irq irq, qemu_irq *dma, omap_clk clk)
412 {
413     int iomemtype;
414     struct omap_i2c_s *s = (struct omap_i2c_s *)
415             qemu_mallocz(sizeof(struct omap_i2c_s));
416
417     s->base = base;
418     s->irq = irq;
419     s->drq[0] = dma[0];
420     s->drq[1] = dma[1];
421     s->slave.event = omap_i2c_event;
422     s->slave.recv = omap_i2c_rx;
423     s->slave.send = omap_i2c_tx;
424     s->bus = i2c_init_bus();
425     omap_i2c_reset(s);
426
427     iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
428                     omap_i2c_writefn, s);
429     cpu_register_physical_memory(s->base, 0x800, iomemtype);
430
431     return s;
432 }
433
434 i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
435 {
436     return s->bus;
437 }