xref: /openbmc/qemu/hw/sd/pl181.c (revision 6a0acfff)
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/blockdev.h"
12 #include "hw/sysbus.h"
13 #include "hw/irq.h"
14 #include "hw/sd/sd.h"
15 #include "qemu/log.h"
16 #include "qemu/module.h"
17 #include "qapi/error.h"
18 
19 //#define DEBUG_PL181 1
20 
21 #ifdef DEBUG_PL181
22 #define DPRINTF(fmt, ...) \
23 do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
24 #else
25 #define DPRINTF(fmt, ...) do {} while(0)
26 #endif
27 
28 #define PL181_FIFO_LEN 16
29 
30 #define TYPE_PL181 "pl181"
31 #define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
32 
33 typedef struct PL181State {
34     SysBusDevice parent_obj;
35 
36     MemoryRegion iomem;
37     SDState *card;
38     uint32_t clock;
39     uint32_t power;
40     uint32_t cmdarg;
41     uint32_t cmd;
42     uint32_t datatimer;
43     uint32_t datalength;
44     uint32_t respcmd;
45     uint32_t response[4];
46     uint32_t datactrl;
47     uint32_t datacnt;
48     uint32_t status;
49     uint32_t mask[2];
50     int32_t fifo_pos;
51     int32_t fifo_len;
52     /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives
53        while it is reading the FIFO.  We hack around this by deferring
54        subsequent transfers until after the driver polls the status word.
55        http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
56      */
57     int32_t linux_hack;
58     uint32_t fifo[PL181_FIFO_LEN];
59     qemu_irq irq[2];
60     /* GPIO outputs for 'card is readonly' and 'card inserted' */
61     qemu_irq cardstatus[2];
62 } PL181State;
63 
64 static const VMStateDescription vmstate_pl181 = {
65     .name = "pl181",
66     .version_id = 1,
67     .minimum_version_id = 1,
68     .fields = (VMStateField[]) {
69         VMSTATE_UINT32(clock, PL181State),
70         VMSTATE_UINT32(power, PL181State),
71         VMSTATE_UINT32(cmdarg, PL181State),
72         VMSTATE_UINT32(cmd, PL181State),
73         VMSTATE_UINT32(datatimer, PL181State),
74         VMSTATE_UINT32(datalength, PL181State),
75         VMSTATE_UINT32(respcmd, PL181State),
76         VMSTATE_UINT32_ARRAY(response, PL181State, 4),
77         VMSTATE_UINT32(datactrl, PL181State),
78         VMSTATE_UINT32(datacnt, PL181State),
79         VMSTATE_UINT32(status, PL181State),
80         VMSTATE_UINT32_ARRAY(mask, PL181State, 2),
81         VMSTATE_INT32(fifo_pos, PL181State),
82         VMSTATE_INT32(fifo_len, PL181State),
83         VMSTATE_INT32(linux_hack, PL181State),
84         VMSTATE_UINT32_ARRAY(fifo, PL181State, PL181_FIFO_LEN),
85         VMSTATE_END_OF_LIST()
86     }
87 };
88 
89 #define PL181_CMD_INDEX     0x3f
90 #define PL181_CMD_RESPONSE  (1 << 6)
91 #define PL181_CMD_LONGRESP  (1 << 7)
92 #define PL181_CMD_INTERRUPT (1 << 8)
93 #define PL181_CMD_PENDING   (1 << 9)
94 #define PL181_CMD_ENABLE    (1 << 10)
95 
96 #define PL181_DATA_ENABLE             (1 << 0)
97 #define PL181_DATA_DIRECTION          (1 << 1)
98 #define PL181_DATA_MODE               (1 << 2)
99 #define PL181_DATA_DMAENABLE          (1 << 3)
100 
101 #define PL181_STATUS_CMDCRCFAIL       (1 << 0)
102 #define PL181_STATUS_DATACRCFAIL      (1 << 1)
103 #define PL181_STATUS_CMDTIMEOUT       (1 << 2)
104 #define PL181_STATUS_DATATIMEOUT      (1 << 3)
105 #define PL181_STATUS_TXUNDERRUN       (1 << 4)
106 #define PL181_STATUS_RXOVERRUN        (1 << 5)
107 #define PL181_STATUS_CMDRESPEND       (1 << 6)
108 #define PL181_STATUS_CMDSENT          (1 << 7)
109 #define PL181_STATUS_DATAEND          (1 << 8)
110 #define PL181_STATUS_DATABLOCKEND     (1 << 10)
111 #define PL181_STATUS_CMDACTIVE        (1 << 11)
112 #define PL181_STATUS_TXACTIVE         (1 << 12)
113 #define PL181_STATUS_RXACTIVE         (1 << 13)
114 #define PL181_STATUS_TXFIFOHALFEMPTY  (1 << 14)
115 #define PL181_STATUS_RXFIFOHALFFULL   (1 << 15)
116 #define PL181_STATUS_TXFIFOFULL       (1 << 16)
117 #define PL181_STATUS_RXFIFOFULL       (1 << 17)
118 #define PL181_STATUS_TXFIFOEMPTY      (1 << 18)
119 #define PL181_STATUS_RXFIFOEMPTY      (1 << 19)
120 #define PL181_STATUS_TXDATAAVLBL      (1 << 20)
121 #define PL181_STATUS_RXDATAAVLBL      (1 << 21)
122 
123 #define PL181_STATUS_TX_FIFO (PL181_STATUS_TXACTIVE \
124                              |PL181_STATUS_TXFIFOHALFEMPTY \
125                              |PL181_STATUS_TXFIFOFULL \
126                              |PL181_STATUS_TXFIFOEMPTY \
127                              |PL181_STATUS_TXDATAAVLBL)
128 #define PL181_STATUS_RX_FIFO (PL181_STATUS_RXACTIVE \
129                              |PL181_STATUS_RXFIFOHALFFULL \
130                              |PL181_STATUS_RXFIFOFULL \
131                              |PL181_STATUS_RXFIFOEMPTY \
132                              |PL181_STATUS_RXDATAAVLBL)
133 
134 static const unsigned char pl181_id[] =
135 { 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
136 
137 static void pl181_update(PL181State *s)
138 {
139     int i;
140     for (i = 0; i < 2; i++) {
141         qemu_set_irq(s->irq[i], (s->status & s->mask[i]) != 0);
142     }
143 }
144 
145 static void pl181_fifo_push(PL181State *s, uint32_t value)
146 {
147     int n;
148 
149     if (s->fifo_len == PL181_FIFO_LEN) {
150         fprintf(stderr, "pl181: FIFO overflow\n");
151         return;
152     }
153     n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
154     s->fifo_len++;
155     s->fifo[n] = value;
156     DPRINTF("FIFO push %08x\n", (int)value);
157 }
158 
159 static uint32_t pl181_fifo_pop(PL181State *s)
160 {
161     uint32_t value;
162 
163     if (s->fifo_len == 0) {
164         fprintf(stderr, "pl181: FIFO underflow\n");
165         return 0;
166     }
167     value = s->fifo[s->fifo_pos];
168     s->fifo_len--;
169     s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
170     DPRINTF("FIFO pop %08x\n", (int)value);
171     return value;
172 }
173 
174 static void pl181_send_command(PL181State *s)
175 {
176     SDRequest request;
177     uint8_t response[16];
178     int rlen;
179 
180     request.cmd = s->cmd & PL181_CMD_INDEX;
181     request.arg = s->cmdarg;
182     DPRINTF("Command %d %08x\n", request.cmd, request.arg);
183     rlen = sd_do_command(s->card, &request, response);
184     if (rlen < 0)
185         goto error;
186     if (s->cmd & PL181_CMD_RESPONSE) {
187         if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
188             goto error;
189         if (rlen != 4 && rlen != 16)
190             goto error;
191         s->response[0] = ldl_be_p(&response[0]);
192         if (rlen == 4) {
193             s->response[1] = s->response[2] = s->response[3] = 0;
194         } else {
195             s->response[1] = ldl_be_p(&response[4]);
196             s->response[2] = ldl_be_p(&response[8]);
197             s->response[3] = ldl_be_p(&response[12]) & ~1;
198         }
199         DPRINTF("Response received\n");
200         s->status |= PL181_STATUS_CMDRESPEND;
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     /* Since we're still using the legacy SD API the card is not plugged
482      * into any bus, and we must reset it manually.
483      */
484     device_reset(DEVICE(s->card));
485 }
486 
487 static void pl181_init(Object *obj)
488 {
489     DeviceState *dev = DEVICE(obj);
490     PL181State *s = PL181(obj);
491     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
492 
493     memory_region_init_io(&s->iomem, obj, &pl181_ops, s, "pl181", 0x1000);
494     sysbus_init_mmio(sbd, &s->iomem);
495     sysbus_init_irq(sbd, &s->irq[0]);
496     sysbus_init_irq(sbd, &s->irq[1]);
497     qdev_init_gpio_out(dev, s->cardstatus, 2);
498 }
499 
500 static void pl181_realize(DeviceState *dev, Error **errp)
501 {
502     PL181State *s = PL181(dev);
503     DriveInfo *dinfo;
504 
505     /* FIXME use a qdev drive property instead of drive_get_next() */
506     dinfo = drive_get_next(IF_SD);
507     s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
508     if (s->card == NULL) {
509         error_setg(errp, "sd_init failed");
510     }
511 }
512 
513 static void pl181_class_init(ObjectClass *klass, void *data)
514 {
515     DeviceClass *k = DEVICE_CLASS(klass);
516 
517     k->vmsd = &vmstate_pl181;
518     k->reset = pl181_reset;
519     /* Reason: init() method uses drive_get_next() */
520     k->user_creatable = false;
521     k->realize = pl181_realize;
522 }
523 
524 static const TypeInfo pl181_info = {
525     .name          = TYPE_PL181,
526     .parent        = TYPE_SYS_BUS_DEVICE,
527     .instance_size = sizeof(PL181State),
528     .instance_init = pl181_init,
529     .class_init    = pl181_class_init,
530 };
531 
532 static void pl181_register_types(void)
533 {
534     type_register_static(&pl181_info);
535 }
536 
537 type_init(pl181_register_types)
538