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