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