virtio-blk: add SGI_IO passthru support
[qemu] / hw / pl181.c
1 /*
2  * Arm PrimeCell PL181 MultiMedia Card Interface
3  *
4  * Copyright (c) 2007 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licenced under the GPL.
8  */
9
10 #include "hw.h"
11 #include "primecell.h"
12 #include "sd.h"
13
14 //#define DEBUG_PL181 1
15
16 #ifdef DEBUG_PL181
17 #define DPRINTF(fmt, args...) \
18 do { printf("pl181: " fmt , ##args); } while (0)
19 #else
20 #define DPRINTF(fmt, args...) do {} while(0)
21 #endif
22
23 #define PL181_FIFO_LEN 16
24
25 typedef struct {
26     SDState *card;
27     uint32_t clock;
28     uint32_t power;
29     uint32_t cmdarg;
30     uint32_t cmd;
31     uint32_t datatimer;
32     uint32_t datalength;
33     uint32_t respcmd;
34     uint32_t response[4];
35     uint32_t datactrl;
36     uint32_t datacnt;
37     uint32_t status;
38     uint32_t mask[2];
39     int fifo_pos;
40     int fifo_len;
41     /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives
42        while it is reading the FIFO.  We hack around this be defering
43        subsequent transfers until after the driver polls the status word.
44        http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
45      */
46     int linux_hack;
47     uint32_t fifo[PL181_FIFO_LEN];
48     qemu_irq irq[2];
49 } pl181_state;
50
51 #define PL181_CMD_INDEX     0x3f
52 #define PL181_CMD_RESPONSE  (1 << 6)
53 #define PL181_CMD_LONGRESP  (1 << 7)
54 #define PL181_CMD_INTERRUPT (1 << 8)
55 #define PL181_CMD_PENDING   (1 << 9)
56 #define PL181_CMD_ENABLE    (1 << 10)
57
58 #define PL181_DATA_ENABLE             (1 << 0)
59 #define PL181_DATA_DIRECTION          (1 << 1)
60 #define PL181_DATA_MODE               (1 << 2)
61 #define PL181_DATA_DMAENABLE          (1 << 3)
62
63 #define PL181_STATUS_CMDCRCFAIL       (1 << 0)
64 #define PL181_STATUS_DATACRCFAIL      (1 << 1)
65 #define PL181_STATUS_CMDTIMEOUT       (1 << 2)
66 #define PL181_STATUS_DATATIMEOUT      (1 << 3)
67 #define PL181_STATUS_TXUNDERRUN       (1 << 4)
68 #define PL181_STATUS_RXOVERRUN        (1 << 5)
69 #define PL181_STATUS_CMDRESPEND       (1 << 6)
70 #define PL181_STATUS_CMDSENT          (1 << 7)
71 #define PL181_STATUS_DATAEND          (1 << 8)
72 #define PL181_STATUS_DATABLOCKEND     (1 << 10)
73 #define PL181_STATUS_CMDACTIVE        (1 << 11)
74 #define PL181_STATUS_TXACTIVE         (1 << 12)
75 #define PL181_STATUS_RXACTIVE         (1 << 13)
76 #define PL181_STATUS_TXFIFOHALFEMPTY  (1 << 14)
77 #define PL181_STATUS_RXFIFOHALFFULL   (1 << 15)
78 #define PL181_STATUS_TXFIFOFULL       (1 << 16)
79 #define PL181_STATUS_RXFIFOFULL       (1 << 17)
80 #define PL181_STATUS_TXFIFOEMPTY      (1 << 18)
81 #define PL181_STATUS_RXFIFOEMPTY      (1 << 19)
82 #define PL181_STATUS_TXDATAAVLBL      (1 << 20)
83 #define PL181_STATUS_RXDATAAVLBL      (1 << 21)
84
85 #define PL181_STATUS_TX_FIFO (PL181_STATUS_TXACTIVE \
86                              |PL181_STATUS_TXFIFOHALFEMPTY \
87                              |PL181_STATUS_TXFIFOFULL \
88                              |PL181_STATUS_TXFIFOEMPTY \
89                              |PL181_STATUS_TXDATAAVLBL)
90 #define PL181_STATUS_RX_FIFO (PL181_STATUS_RXACTIVE \
91                              |PL181_STATUS_RXFIFOHALFFULL \
92                              |PL181_STATUS_RXFIFOFULL \
93                              |PL181_STATUS_RXFIFOEMPTY \
94                              |PL181_STATUS_RXDATAAVLBL)
95
96 static const unsigned char pl181_id[] =
97 { 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
98
99 static void pl181_update(pl181_state *s)
100 {
101     int i;
102     for (i = 0; i < 2; i++) {
103         qemu_set_irq(s->irq[i], (s->status & s->mask[i]) != 0);
104     }
105 }
106
107 static void pl181_fifo_push(pl181_state *s, uint32_t value)
108 {
109     int n;
110
111     if (s->fifo_len == PL181_FIFO_LEN) {
112         fprintf(stderr, "pl181: FIFO overflow\n");
113         return;
114     }
115     n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
116     s->fifo_len++;
117     s->fifo[n] = value;
118     DPRINTF("FIFO push %08x\n", (int)value);
119 }
120
121 static uint32_t pl181_fifo_pop(pl181_state *s)
122 {
123     uint32_t value;
124
125     if (s->fifo_len == 0) {
126         fprintf(stderr, "pl181: FIFO underflow\n");
127         return 0;
128     }
129     value = s->fifo[s->fifo_pos];
130     s->fifo_len--;
131     s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
132     DPRINTF("FIFO pop %08x\n", (int)value);
133     return value;
134 }
135
136 static void pl181_send_command(pl181_state *s)
137 {
138     struct sd_request_s request;
139     uint8_t response[16];
140     int rlen;
141
142     request.cmd = s->cmd & PL181_CMD_INDEX;
143     request.arg = s->cmdarg;
144     DPRINTF("Command %d %08x\n", request.cmd, request.arg);
145     rlen = sd_do_command(s->card, &request, response);
146     if (rlen < 0)
147         goto error;
148     if (s->cmd & PL181_CMD_RESPONSE) {
149 #define RWORD(n) ((response[n] << 24) | (response[n + 1] << 16) \
150                   | (response[n + 2] << 8) | response[n + 3])
151         if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
152             goto error;
153         if (rlen != 4 && rlen != 16)
154             goto error;
155         s->response[0] = RWORD(0);
156         if (rlen == 4) {
157             s->response[1] = s->response[2] = s->response[3] = 0;
158         } else {
159             s->response[1] = RWORD(4);
160             s->response[2] = RWORD(8);
161             s->response[3] = RWORD(12) & ~1;
162         }
163         DPRINTF("Response received\n");
164         s->status |= PL181_STATUS_CMDRESPEND;
165 #undef RWORD
166     } else {
167         DPRINTF("Command sent\n");
168         s->status |= PL181_STATUS_CMDSENT;
169     }
170     return;
171
172 error:
173     DPRINTF("Timeout\n");
174     s->status |= PL181_STATUS_CMDTIMEOUT;
175 }
176
177 /* Transfer data between the card and the FIFO.  This is complicated by
178    the FIFO holding 32-bit words and the card taking data in single byte
179    chunks.  FIFO bytes are transferred in little-endian order.  */
180
181 static void pl181_fifo_run(pl181_state *s)
182 {
183     uint32_t bits;
184     uint32_t value;
185     int n;
186     int limit;
187     int is_read;
188
189     is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
190     if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
191             && !s->linux_hack) {
192         limit = is_read ? PL181_FIFO_LEN : 0;
193         n = 0;
194         value = 0;
195         while (s->datacnt && s->fifo_len != limit) {
196             if (is_read) {
197                 value |= (uint32_t)sd_read_data(s->card) << (n * 8);
198                 n++;
199                 if (n == 4) {
200                     pl181_fifo_push(s, value);
201                     value = 0;
202                     n = 0;
203                 }
204             } else {
205                 if (n == 0) {
206                     value = pl181_fifo_pop(s);
207                     n = 4;
208                 }
209                 sd_write_data(s->card, value & 0xff);
210                 value >>= 8;
211                 n--;
212             }
213             s->datacnt--;
214         }
215         if (n && is_read) {
216             pl181_fifo_push(s, value);
217         }
218     }
219     s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
220     if (s->datacnt == 0) {
221         s->status |= PL181_STATUS_DATAEND;
222         /* HACK: */
223         s->status |= PL181_STATUS_DATABLOCKEND;
224         DPRINTF("Transfer Complete\n");
225     }
226     if (s->datacnt == 0 && s->fifo_len == 0) {
227         s->datactrl &= ~PL181_DATA_ENABLE;
228         DPRINTF("Data engine idle\n");
229     } else {
230         /* Update FIFO bits.  */
231         bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
232         if (s->fifo_len == 0) {
233             bits |= PL181_STATUS_TXFIFOEMPTY;
234             bits |= PL181_STATUS_RXFIFOEMPTY;
235         } else {
236             bits |= PL181_STATUS_TXDATAAVLBL;
237             bits |= PL181_STATUS_RXDATAAVLBL;
238         }
239         if (s->fifo_len == 16) {
240             bits |= PL181_STATUS_TXFIFOFULL;
241             bits |= PL181_STATUS_RXFIFOFULL;
242         }
243         if (s->fifo_len <= 8) {
244             bits |= PL181_STATUS_TXFIFOHALFEMPTY;
245         }
246         if (s->fifo_len >= 8) {
247             bits |= PL181_STATUS_RXFIFOHALFFULL;
248         }
249         if (s->datactrl & PL181_DATA_DIRECTION) {
250             bits &= PL181_STATUS_RX_FIFO;
251         } else {
252             bits &= PL181_STATUS_TX_FIFO;
253         }
254         s->status |= bits;
255     }
256 }
257
258 static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
259 {
260     pl181_state *s = (pl181_state *)opaque;
261     uint32_t tmp;
262
263     if (offset >= 0xfe0 && offset < 0x1000) {
264         return pl181_id[(offset - 0xfe0) >> 2];
265     }
266     switch (offset) {
267     case 0x00: /* Power */
268         return s->power;
269     case 0x04: /* Clock */
270         return s->clock;
271     case 0x08: /* Argument */
272         return s->cmdarg;
273     case 0x0c: /* Command */
274         return s->cmd;
275     case 0x10: /* RespCmd */
276         return s->respcmd;
277     case 0x14: /* Response0 */
278         return s->response[0];
279     case 0x18: /* Response1 */
280         return s->response[1];
281     case 0x1c: /* Response2 */
282         return s->response[2];
283     case 0x20: /* Response3 */
284         return s->response[3];
285     case 0x24: /* DataTimer */
286         return s->datatimer;
287     case 0x28: /* DataLength */
288         return s->datalength;
289     case 0x2c: /* DataCtrl */
290         return s->datactrl;
291     case 0x30: /* DataCnt */
292         return s->datacnt;
293     case 0x34: /* Status */
294         tmp = s->status;
295         if (s->linux_hack) {
296             s->linux_hack = 0;
297             pl181_fifo_run(s);
298             pl181_update(s);
299         }
300         return tmp;
301     case 0x3c: /* Mask0 */
302         return s->mask[0];
303     case 0x40: /* Mask1 */
304         return s->mask[1];
305     case 0x48: /* FifoCnt */
306         /* The documentation is somewhat vague about exactly what FifoCnt
307            does.  On real hardware it appears to be when decrememnted
308            when a word is transfered between the FIFO and the serial
309            data engine.  DataCnt is decremented after each byte is
310            transfered between the serial engine and the card.
311            We don't emulate this level of detail, so both can be the same.  */
312         tmp = (s->datacnt + 3) >> 2;
313         if (s->linux_hack) {
314             s->linux_hack = 0;
315             pl181_fifo_run(s);
316             pl181_update(s);
317         }
318         return tmp;
319     case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
320     case 0x90: case 0x94: case 0x98: case 0x9c:
321     case 0xa0: case 0xa4: case 0xa8: case 0xac:
322     case 0xb0: case 0xb4: case 0xb8: case 0xbc:
323         if (s->fifo_len == 0) {
324             fprintf(stderr, "pl181: Unexpected FIFO read\n");
325             return 0;
326         } else {
327             uint32_t value;
328             value = pl181_fifo_pop(s);
329             s->linux_hack = 1;
330             pl181_fifo_run(s);
331             pl181_update(s);
332             return value;
333         }
334     default:
335         cpu_abort (cpu_single_env, "pl181_read: Bad offset %x\n", (int)offset);
336         return 0;
337     }
338 }
339
340 static void pl181_write(void *opaque, target_phys_addr_t offset,
341                           uint32_t value)
342 {
343     pl181_state *s = (pl181_state *)opaque;
344
345     switch (offset) {
346     case 0x00: /* Power */
347         s->power = value & 0xff;
348         break;
349     case 0x04: /* Clock */
350         s->clock = value & 0xff;
351         break;
352     case 0x08: /* Argument */
353         s->cmdarg = value;
354         break;
355     case 0x0c: /* Command */
356         s->cmd = value;
357         if (s->cmd & PL181_CMD_ENABLE) {
358             if (s->cmd & PL181_CMD_INTERRUPT) {
359                 fprintf(stderr, "pl181: Interrupt mode not implemented\n");
360                 abort();
361             } if (s->cmd & PL181_CMD_PENDING) {
362                 fprintf(stderr, "pl181: Pending commands not implemented\n");
363                 abort();
364             } else {
365                 pl181_send_command(s);
366                 pl181_fifo_run(s);
367             }
368             /* The command has completed one way or the other.  */
369             s->cmd &= ~PL181_CMD_ENABLE;
370         }
371         break;
372     case 0x24: /* DataTimer */
373         s->datatimer = value;
374         break;
375     case 0x28: /* DataLength */
376         s->datalength = value & 0xffff;
377         break;
378     case 0x2c: /* DataCtrl */
379         s->datactrl = value & 0xff;
380         if (value & PL181_DATA_ENABLE) {
381             s->datacnt = s->datalength;
382             pl181_fifo_run(s);
383         }
384         break;
385     case 0x38: /* Clear */
386         s->status &= ~(value & 0x7ff);
387         break;
388     case 0x3c: /* Mask0 */
389         s->mask[0] = value;
390         break;
391     case 0x40: /* Mask1 */
392         s->mask[1] = value;
393         break;
394     case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
395     case 0x90: case 0x94: case 0x98: case 0x9c:
396     case 0xa0: case 0xa4: case 0xa8: case 0xac:
397     case 0xb0: case 0xb4: case 0xb8: case 0xbc:
398         if (s->datacnt == 0) {
399             fprintf(stderr, "pl181: Unexpected FIFO write\n");
400         } else {
401             pl181_fifo_push(s, value);
402             pl181_fifo_run(s);
403         }
404         break;
405     default:
406         cpu_abort (cpu_single_env, "pl181_write: Bad offset %x\n", (int)offset);
407     }
408     pl181_update(s);
409 }
410
411 static CPUReadMemoryFunc *pl181_readfn[] = {
412    pl181_read,
413    pl181_read,
414    pl181_read
415 };
416
417 static CPUWriteMemoryFunc *pl181_writefn[] = {
418    pl181_write,
419    pl181_write,
420    pl181_write
421 };
422
423 static void pl181_reset(void *opaque)
424 {
425     pl181_state *s = (pl181_state *)opaque;
426
427     s->power = 0;
428     s->cmdarg = 0;
429     s->cmd = 0;
430     s->datatimer = 0;
431     s->datalength = 0;
432     s->respcmd = 0;
433     s->response[0] = 0;
434     s->response[1] = 0;
435     s->response[2] = 0;
436     s->response[3] = 0;
437     s->datatimer = 0;
438     s->datalength = 0;
439     s->datactrl = 0;
440     s->datacnt = 0;
441     s->status = 0;
442     s->linux_hack = 0;
443     s->mask[0] = 0;
444     s->mask[1] = 0;
445 }
446
447 void pl181_init(uint32_t base, BlockDriverState *bd,
448                 qemu_irq irq0, qemu_irq irq1)
449 {
450     int iomemtype;
451     pl181_state *s;
452
453     s = (pl181_state *)qemu_mallocz(sizeof(pl181_state));
454     iomemtype = cpu_register_io_memory(0, pl181_readfn,
455                                        pl181_writefn, s);
456     cpu_register_physical_memory(base, 0x00001000, iomemtype);
457     s->card = sd_init(bd, 0);
458     s->irq[0] = irq0;
459     s->irq[1] = irq1;
460     qemu_register_reset(pl181_reset, s);
461     pl181_reset(s);
462     /* ??? Save/restore.  */
463 }