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