2 * Arm PrimeCell PL181 MultiMedia Card Interface
4 * Copyright (c) 2007 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licensed under the GPL.
14 //#define DEBUG_PL181 1
17 #define DPRINTF(fmt, ...) \
18 do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
20 #define DPRINTF(fmt, ...) do {} while(0)
23 #define PL181_FIFO_LEN 16
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
49 uint32_t fifo
[PL181_FIFO_LEN
];
51 /* GPIO outputs for 'card is readonly' and 'card inserted' */
52 qemu_irq cardstatus
[2];
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)
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)
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)
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)
100 static const unsigned char pl181_id
[] =
101 { 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
103 static void pl181_update(pl181_state
*s
)
106 for (i
= 0; i
< 2; i
++) {
107 qemu_set_irq(s
->irq
[i
], (s
->status
& s
->mask
[i
]) != 0);
111 static void pl181_fifo_push(pl181_state
*s
, uint32_t value
)
115 if (s
->fifo_len
== PL181_FIFO_LEN
) {
116 fprintf(stderr
, "pl181: FIFO overflow\n");
119 n
= (s
->fifo_pos
+ s
->fifo_len
) & (PL181_FIFO_LEN
- 1);
122 DPRINTF("FIFO push %08x\n", (int)value
);
125 static uint32_t pl181_fifo_pop(pl181_state
*s
)
129 if (s
->fifo_len
== 0) {
130 fprintf(stderr
, "pl181: FIFO underflow\n");
133 value
= s
->fifo
[s
->fifo_pos
];
135 s
->fifo_pos
= (s
->fifo_pos
+ 1) & (PL181_FIFO_LEN
- 1);
136 DPRINTF("FIFO pop %08x\n", (int)value
);
140 static void pl181_send_command(pl181_state
*s
)
143 uint8_t response
[16];
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
);
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
)))
157 if (rlen
!= 4 && rlen
!= 16)
159 s
->response
[0] = RWORD(0);
161 s
->response
[1] = s
->response
[2] = s
->response
[3] = 0;
163 s
->response
[1] = RWORD(4);
164 s
->response
[2] = RWORD(8);
165 s
->response
[3] = RWORD(12) & ~1;
167 DPRINTF("Response received\n");
168 s
->status
|= PL181_STATUS_CMDRESPEND
;
171 DPRINTF("Command sent\n");
172 s
->status
|= PL181_STATUS_CMDSENT
;
177 DPRINTF("Timeout\n");
178 s
->status
|= PL181_STATUS_CMDTIMEOUT
;
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. */
185 static void pl181_fifo_run(pl181_state
*s
)
192 is_read
= (s
->datactrl
& PL181_DATA_DIRECTION
) != 0;
193 if (s
->datacnt
!= 0 && (!is_read
|| sd_data_ready(s
->card
))
197 while (s
->datacnt
&& s
->fifo_len
< PL181_FIFO_LEN
) {
198 value
|= (uint32_t)sd_read_data(s
->card
) << (n
* 8);
202 pl181_fifo_push(s
, value
);
208 pl181_fifo_push(s
, value
);
212 while (s
->datacnt
> 0 && (s
->fifo_len
> 0 || n
> 0)) {
214 value
= pl181_fifo_pop(s
);
219 sd_write_data(s
->card
, value
& 0xff);
224 s
->status
&= ~(PL181_STATUS_RX_FIFO
| PL181_STATUS_TX_FIFO
);
225 if (s
->datacnt
== 0) {
226 s
->status
|= PL181_STATUS_DATAEND
;
228 s
->status
|= PL181_STATUS_DATABLOCKEND
;
229 DPRINTF("Transfer Complete\n");
231 if (s
->datacnt
== 0 && s
->fifo_len
== 0) {
232 s
->datactrl
&= ~PL181_DATA_ENABLE
;
233 DPRINTF("Data engine idle\n");
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
;
241 bits
|= PL181_STATUS_TXDATAAVLBL
;
242 bits
|= PL181_STATUS_RXDATAAVLBL
;
244 if (s
->fifo_len
== 16) {
245 bits
|= PL181_STATUS_TXFIFOFULL
;
246 bits
|= PL181_STATUS_RXFIFOFULL
;
248 if (s
->fifo_len
<= 8) {
249 bits
|= PL181_STATUS_TXFIFOHALFEMPTY
;
251 if (s
->fifo_len
>= 8) {
252 bits
|= PL181_STATUS_RXFIFOHALFFULL
;
254 if (s
->datactrl
& PL181_DATA_DIRECTION
) {
255 bits
&= PL181_STATUS_RX_FIFO
;
257 bits
&= PL181_STATUS_TX_FIFO
;
263 static uint64_t pl181_read(void *opaque
, target_phys_addr_t offset
,
266 pl181_state
*s
= (pl181_state
*)opaque
;
269 if (offset
>= 0xfe0 && offset
< 0x1000) {
270 return pl181_id
[(offset
- 0xfe0) >> 2];
273 case 0x00: /* Power */
275 case 0x04: /* Clock */
277 case 0x08: /* Argument */
279 case 0x0c: /* Command */
281 case 0x10: /* 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 */
293 case 0x28: /* DataLength */
294 return s
->datalength
;
295 case 0x2c: /* DataCtrl */
297 case 0x30: /* DataCnt */
299 case 0x34: /* Status */
307 case 0x3c: /* Mask0 */
309 case 0x40: /* Mask1 */
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;
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");
334 value
= pl181_fifo_pop(s
);
341 hw_error("pl181_read: Bad offset %x\n", (int)offset
);
346 static void pl181_write(void *opaque
, target_phys_addr_t offset
,
347 uint64_t value
, unsigned size
)
349 pl181_state
*s
= (pl181_state
*)opaque
;
352 case 0x00: /* Power */
353 s
->power
= value
& 0xff;
355 case 0x04: /* Clock */
356 s
->clock
= value
& 0xff;
358 case 0x08: /* Argument */
361 case 0x0c: /* Command */
363 if (s
->cmd
& PL181_CMD_ENABLE
) {
364 if (s
->cmd
& PL181_CMD_INTERRUPT
) {
365 fprintf(stderr
, "pl181: Interrupt mode not implemented\n");
367 } if (s
->cmd
& PL181_CMD_PENDING
) {
368 fprintf(stderr
, "pl181: Pending commands not implemented\n");
371 pl181_send_command(s
);
374 /* The command has completed one way or the other. */
375 s
->cmd
&= ~PL181_CMD_ENABLE
;
378 case 0x24: /* DataTimer */
379 s
->datatimer
= value
;
381 case 0x28: /* DataLength */
382 s
->datalength
= value
& 0xffff;
384 case 0x2c: /* DataCtrl */
385 s
->datactrl
= value
& 0xff;
386 if (value
& PL181_DATA_ENABLE
) {
387 s
->datacnt
= s
->datalength
;
391 case 0x38: /* Clear */
392 s
->status
&= ~(value
& 0x7ff);
394 case 0x3c: /* Mask0 */
397 case 0x40: /* Mask1 */
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");
407 pl181_fifo_push(s
, value
);
412 hw_error("pl181_write: Bad offset %x\n", (int)offset
);
417 static const MemoryRegionOps pl181_ops
= {
419 .write
= pl181_write
,
420 .endianness
= DEVICE_NATIVE_ENDIAN
,
423 static void pl181_reset(void *opaque
)
425 pl181_state
*s
= (pl181_state
*)opaque
;
446 /* We can assume our GPIO outputs have been wired up now */
447 sd_set_cb(s
->card
, s
->cardstatus
[0], s
->cardstatus
[1]);
450 static int pl181_init(SysBusDevice
*dev
)
452 pl181_state
*s
= FROM_SYSBUS(pl181_state
, dev
);
455 memory_region_init_io(&s
->iomem
, &pl181_ops
, s
, "pl181", 0x1000);
456 sysbus_init_mmio(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
);
464 /* ??? Save/restore. */
468 static void pl181_register_devices(void)
470 sysbus_register_dev("pl181", sizeof(pl181_state
), pl181_init
);
473 device_init(pl181_register_devices
)