xref: /openbmc/qemu/hw/sd/pl181.c (revision 0807162e)
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 "migration/vmstate.h"
14 #include "hw/irq.h"
15 #include "hw/sd/sd.h"
16 #include "qemu/log.h"
17 #include "qemu/module.h"
18 #include "qemu/error-report.h"
19 #include "qapi/error.h"
20 #include "trace.h"
21 
22 #define PL181_FIFO_LEN 16
23 
24 #define TYPE_PL181 "pl181"
25 #define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
26 
27 #define TYPE_PL181_BUS "pl181-bus"
28 
29 typedef struct PL181State {
30     SysBusDevice parent_obj;
31 
32     MemoryRegion iomem;
33     SDBus sdbus;
34     uint32_t clock;
35     uint32_t power;
36     uint32_t cmdarg;
37     uint32_t cmd;
38     uint32_t datatimer;
39     uint32_t datalength;
40     uint32_t respcmd;
41     uint32_t response[4];
42     uint32_t datactrl;
43     uint32_t datacnt;
44     uint32_t status;
45     uint32_t mask[2];
46     int32_t fifo_pos;
47     int32_t fifo_len;
48     /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives
49        while it is reading the FIFO.  We hack around this by deferring
50        subsequent transfers until after the driver polls the status word.
51        http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
52      */
53     int32_t linux_hack;
54     uint32_t fifo[PL181_FIFO_LEN]; /* TODO use Fifo32 */
55     qemu_irq irq[2];
56     /* GPIO outputs for 'card is readonly' and 'card inserted' */
57     qemu_irq card_readonly;
58     qemu_irq card_inserted;
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         error_report("%s: FIFO overflow", __func__);
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     trace_pl181_fifo_push(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         error_report("%s: FIFO underflow", __func__);
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     trace_pl181_fifo_pop(value);
168     return value;
169 }
170 
171 static void pl181_do_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     trace_pl181_command_send(request.cmd, request.arg);
180     rlen = sdbus_do_command(&s->sdbus, &request, response);
181     if (rlen < 0)
182         goto error;
183     if (s->cmd & PL181_CMD_RESPONSE) {
184         if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
185             goto error;
186         if (rlen != 4 && rlen != 16)
187             goto error;
188         s->response[0] = ldl_be_p(&response[0]);
189         if (rlen == 4) {
190             s->response[1] = s->response[2] = s->response[3] = 0;
191         } else {
192             s->response[1] = ldl_be_p(&response[4]);
193             s->response[2] = ldl_be_p(&response[8]);
194             s->response[3] = ldl_be_p(&response[12]) & ~1;
195         }
196         trace_pl181_command_response_pending();
197         s->status |= PL181_STATUS_CMDRESPEND;
198     } else {
199         trace_pl181_command_sent();
200         s->status |= PL181_STATUS_CMDSENT;
201     }
202     return;
203 
204 error:
205     trace_pl181_command_timeout();
206     s->status |= PL181_STATUS_CMDTIMEOUT;
207 }
208 
209 /* Transfer data between the card and the FIFO.  This is complicated by
210    the FIFO holding 32-bit words and the card taking data in single byte
211    chunks.  FIFO bytes are transferred in little-endian order.  */
212 
213 static void pl181_fifo_run(PL181State *s)
214 {
215     uint32_t bits;
216     uint32_t value = 0;
217     int n;
218     int is_read;
219 
220     is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
221     if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))
222             && !s->linux_hack) {
223         if (is_read) {
224             n = 0;
225             while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
226                 value |= (uint32_t)sdbus_read_byte(&s->sdbus) << (n * 8);
227                 s->datacnt--;
228                 n++;
229                 if (n == 4) {
230                     pl181_fifo_push(s, value);
231                     n = 0;
232                     value = 0;
233                 }
234             }
235             if (n != 0) {
236                 pl181_fifo_push(s, value);
237             }
238         } else { /* write */
239             n = 0;
240             while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
241                 if (n == 0) {
242                     value = pl181_fifo_pop(s);
243                     n = 4;
244                 }
245                 n--;
246                 s->datacnt--;
247                 sdbus_write_byte(&s->sdbus, value & 0xff);
248                 value >>= 8;
249             }
250         }
251     }
252     s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
253     if (s->datacnt == 0) {
254         s->status |= PL181_STATUS_DATAEND;
255         /* HACK: */
256         s->status |= PL181_STATUS_DATABLOCKEND;
257         trace_pl181_fifo_transfer_complete();
258     }
259     if (s->datacnt == 0 && s->fifo_len == 0) {
260         s->datactrl &= ~PL181_DATA_ENABLE;
261         trace_pl181_data_engine_idle();
262     } else {
263         /* Update FIFO bits.  */
264         bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
265         if (s->fifo_len == 0) {
266             bits |= PL181_STATUS_TXFIFOEMPTY;
267             bits |= PL181_STATUS_RXFIFOEMPTY;
268         } else {
269             bits |= PL181_STATUS_TXDATAAVLBL;
270             bits |= PL181_STATUS_RXDATAAVLBL;
271         }
272         if (s->fifo_len == 16) {
273             bits |= PL181_STATUS_TXFIFOFULL;
274             bits |= PL181_STATUS_RXFIFOFULL;
275         }
276         if (s->fifo_len <= 8) {
277             bits |= PL181_STATUS_TXFIFOHALFEMPTY;
278         }
279         if (s->fifo_len >= 8) {
280             bits |= PL181_STATUS_RXFIFOHALFFULL;
281         }
282         if (s->datactrl & PL181_DATA_DIRECTION) {
283             bits &= PL181_STATUS_RX_FIFO;
284         } else {
285             bits &= PL181_STATUS_TX_FIFO;
286         }
287         s->status |= bits;
288     }
289 }
290 
291 static uint64_t pl181_read(void *opaque, hwaddr offset,
292                            unsigned size)
293 {
294     PL181State *s = (PL181State *)opaque;
295     uint32_t tmp;
296 
297     if (offset >= 0xfe0 && offset < 0x1000) {
298         return pl181_id[(offset - 0xfe0) >> 2];
299     }
300     switch (offset) {
301     case 0x00: /* Power */
302         return s->power;
303     case 0x04: /* Clock */
304         return s->clock;
305     case 0x08: /* Argument */
306         return s->cmdarg;
307     case 0x0c: /* Command */
308         return s->cmd;
309     case 0x10: /* RespCmd */
310         return s->respcmd;
311     case 0x14: /* Response0 */
312         return s->response[0];
313     case 0x18: /* Response1 */
314         return s->response[1];
315     case 0x1c: /* Response2 */
316         return s->response[2];
317     case 0x20: /* Response3 */
318         return s->response[3];
319     case 0x24: /* DataTimer */
320         return s->datatimer;
321     case 0x28: /* DataLength */
322         return s->datalength;
323     case 0x2c: /* DataCtrl */
324         return s->datactrl;
325     case 0x30: /* DataCnt */
326         return s->datacnt;
327     case 0x34: /* Status */
328         tmp = s->status;
329         if (s->linux_hack) {
330             s->linux_hack = 0;
331             pl181_fifo_run(s);
332             pl181_update(s);
333         }
334         return tmp;
335     case 0x3c: /* Mask0 */
336         return s->mask[0];
337     case 0x40: /* Mask1 */
338         return s->mask[1];
339     case 0x48: /* FifoCnt */
340         /* The documentation is somewhat vague about exactly what FifoCnt
341            does.  On real hardware it appears to be when decrememnted
342            when a word is transferred between the FIFO and the serial
343            data engine.  DataCnt is decremented after each byte is
344            transferred between the serial engine and the card.
345            We don't emulate this level of detail, so both can be the same.  */
346         tmp = (s->datacnt + 3) >> 2;
347         if (s->linux_hack) {
348             s->linux_hack = 0;
349             pl181_fifo_run(s);
350             pl181_update(s);
351         }
352         return tmp;
353     case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
354     case 0x90: case 0x94: case 0x98: case 0x9c:
355     case 0xa0: case 0xa4: case 0xa8: case 0xac:
356     case 0xb0: case 0xb4: case 0xb8: case 0xbc:
357         if (s->fifo_len == 0) {
358             qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO read\n");
359             return 0;
360         } else {
361             uint32_t value;
362             value = pl181_fifo_pop(s);
363             s->linux_hack = 1;
364             pl181_fifo_run(s);
365             pl181_update(s);
366             return value;
367         }
368     default:
369         qemu_log_mask(LOG_GUEST_ERROR,
370                       "pl181_read: Bad offset %x\n", (int)offset);
371         return 0;
372     }
373 }
374 
375 static void pl181_write(void *opaque, hwaddr offset,
376                         uint64_t value, unsigned size)
377 {
378     PL181State *s = (PL181State *)opaque;
379 
380     switch (offset) {
381     case 0x00: /* Power */
382         s->power = value & 0xff;
383         break;
384     case 0x04: /* Clock */
385         s->clock = value & 0xff;
386         break;
387     case 0x08: /* Argument */
388         s->cmdarg = value;
389         break;
390     case 0x0c: /* Command */
391         s->cmd = value;
392         if (s->cmd & PL181_CMD_ENABLE) {
393             if (s->cmd & PL181_CMD_INTERRUPT) {
394                 qemu_log_mask(LOG_UNIMP,
395                               "pl181: Interrupt mode not implemented\n");
396             } if (s->cmd & PL181_CMD_PENDING) {
397                 qemu_log_mask(LOG_UNIMP,
398                               "pl181: Pending commands not implemented\n");
399             } else {
400                 pl181_do_command(s);
401                 pl181_fifo_run(s);
402             }
403             /* The command has completed one way or the other.  */
404             s->cmd &= ~PL181_CMD_ENABLE;
405         }
406         break;
407     case 0x24: /* DataTimer */
408         s->datatimer = value;
409         break;
410     case 0x28: /* DataLength */
411         s->datalength = value & 0xffff;
412         break;
413     case 0x2c: /* DataCtrl */
414         s->datactrl = value & 0xff;
415         if (value & PL181_DATA_ENABLE) {
416             s->datacnt = s->datalength;
417             pl181_fifo_run(s);
418         }
419         break;
420     case 0x38: /* Clear */
421         s->status &= ~(value & 0x7ff);
422         break;
423     case 0x3c: /* Mask0 */
424         s->mask[0] = value;
425         break;
426     case 0x40: /* Mask1 */
427         s->mask[1] = value;
428         break;
429     case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
430     case 0x90: case 0x94: case 0x98: case 0x9c:
431     case 0xa0: case 0xa4: case 0xa8: case 0xac:
432     case 0xb0: case 0xb4: case 0xb8: case 0xbc:
433         if (s->datacnt == 0) {
434             qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO write\n");
435         } else {
436             pl181_fifo_push(s, value);
437             pl181_fifo_run(s);
438         }
439         break;
440     default:
441         qemu_log_mask(LOG_GUEST_ERROR,
442                       "pl181_write: Bad offset %x\n", (int)offset);
443     }
444     pl181_update(s);
445 }
446 
447 static const MemoryRegionOps pl181_ops = {
448     .read = pl181_read,
449     .write = pl181_write,
450     .endianness = DEVICE_NATIVE_ENDIAN,
451 };
452 
453 static void pl181_set_readonly(DeviceState *dev, bool level)
454 {
455     PL181State *s = (PL181State *)dev;
456 
457     qemu_set_irq(s->card_readonly, level);
458 }
459 
460 static void pl181_set_inserted(DeviceState *dev, bool level)
461 {
462     PL181State *s = (PL181State *)dev;
463 
464     qemu_set_irq(s->card_inserted, level);
465 }
466 
467 static void pl181_reset(DeviceState *d)
468 {
469     PL181State *s = PL181(d);
470 
471     s->power = 0;
472     s->cmdarg = 0;
473     s->cmd = 0;
474     s->datatimer = 0;
475     s->datalength = 0;
476     s->respcmd = 0;
477     s->response[0] = 0;
478     s->response[1] = 0;
479     s->response[2] = 0;
480     s->response[3] = 0;
481     s->datatimer = 0;
482     s->datalength = 0;
483     s->datactrl = 0;
484     s->datacnt = 0;
485     s->status = 0;
486     s->linux_hack = 0;
487     s->mask[0] = 0;
488     s->mask[1] = 0;
489 
490     /* Reset other state based on current card insertion/readonly status */
491     pl181_set_inserted(DEVICE(s), sdbus_get_inserted(&s->sdbus));
492     pl181_set_readonly(DEVICE(s), sdbus_get_readonly(&s->sdbus));
493 }
494 
495 static void pl181_init(Object *obj)
496 {
497     DeviceState *dev = DEVICE(obj);
498     PL181State *s = PL181(obj);
499     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
500 
501     memory_region_init_io(&s->iomem, obj, &pl181_ops, s, "pl181", 0x1000);
502     sysbus_init_mmio(sbd, &s->iomem);
503     sysbus_init_irq(sbd, &s->irq[0]);
504     sysbus_init_irq(sbd, &s->irq[1]);
505     qdev_init_gpio_out_named(dev, &s->card_readonly, "card-read-only", 1);
506     qdev_init_gpio_out_named(dev, &s->card_inserted, "card-inserted", 1);
507 
508     qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
509                         TYPE_PL181_BUS, dev, "sd-bus");
510 }
511 
512 static void pl181_class_init(ObjectClass *klass, void *data)
513 {
514     DeviceClass *k = DEVICE_CLASS(klass);
515 
516     k->vmsd = &vmstate_pl181;
517     k->reset = pl181_reset;
518     /* Reason: output IRQs should be wired up */
519     k->user_creatable = false;
520 }
521 
522 static const TypeInfo pl181_info = {
523     .name          = TYPE_PL181,
524     .parent        = TYPE_SYS_BUS_DEVICE,
525     .instance_size = sizeof(PL181State),
526     .instance_init = pl181_init,
527     .class_init    = pl181_class_init,
528 };
529 
530 static void pl181_bus_class_init(ObjectClass *klass, void *data)
531 {
532     SDBusClass *sbc = SD_BUS_CLASS(klass);
533 
534     sbc->set_inserted = pl181_set_inserted;
535     sbc->set_readonly = pl181_set_readonly;
536 }
537 
538 static const TypeInfo pl181_bus_info = {
539     .name = TYPE_PL181_BUS,
540     .parent = TYPE_SD_BUS,
541     .instance_size = sizeof(SDBus),
542     .class_init = pl181_bus_class_init,
543 };
544 
545 static void pl181_register_types(void)
546 {
547     type_register_static(&pl181_info);
548     type_register_static(&pl181_bus_info);
549 }
550 
551 type_init(pl181_register_types)
552