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