|
|
1.1 root 1: /*
2: * Intel XScale PXA255/270 MultiMediaCard/SD/SDIO Controller emulation.
3: *
4: * Copyright (c) 2006 Openedhand Ltd.
5: * Written by Andrzej Zaborowski <[email protected]>
6: *
7: * This code is licensed under the GPLv2.
1.1.1.9 ! root 8: *
! 9: * Contributions after 2012-01-13 are licensed under the terms of the
! 10: * GNU GPL, version 2 or (at your option) any later version.
1.1 root 11: */
12:
13: #include "hw.h"
14: #include "pxa.h"
15: #include "sd.h"
1.1.1.7 root 16: #include "qdev.h"
1.1 root 17:
1.1.1.3 root 18: struct PXA2xxMMCIState {
1.1.1.9 ! root 19: MemoryRegion iomem;
1.1 root 20: qemu_irq irq;
1.1.1.7 root 21: qemu_irq rx_dma;
22: qemu_irq tx_dma;
1.1 root 23:
24: SDState *card;
25:
26: uint32_t status;
27: uint32_t clkrt;
28: uint32_t spi;
29: uint32_t cmdat;
30: uint32_t resp_tout;
31: uint32_t read_tout;
32: int blklen;
33: int numblk;
34: uint32_t intmask;
35: uint32_t intreq;
36: int cmd;
37: uint32_t arg;
38:
39: int active;
40: int bytesleft;
41: uint8_t tx_fifo[64];
42: int tx_start;
43: int tx_len;
44: uint8_t rx_fifo[32];
45: int rx_start;
46: int rx_len;
47: uint16_t resp_fifo[9];
48: int resp_len;
49:
50: int cmdreq;
51: int ac_width;
52: };
53:
54: #define MMC_STRPCL 0x00 /* MMC Clock Start/Stop register */
55: #define MMC_STAT 0x04 /* MMC Status register */
56: #define MMC_CLKRT 0x08 /* MMC Clock Rate register */
57: #define MMC_SPI 0x0c /* MMC SPI Mode register */
58: #define MMC_CMDAT 0x10 /* MMC Command/Data register */
59: #define MMC_RESTO 0x14 /* MMC Response Time-Out register */
60: #define MMC_RDTO 0x18 /* MMC Read Time-Out register */
61: #define MMC_BLKLEN 0x1c /* MMC Block Length register */
62: #define MMC_NUMBLK 0x20 /* MMC Number of Blocks register */
63: #define MMC_PRTBUF 0x24 /* MMC Buffer Partly Full register */
64: #define MMC_I_MASK 0x28 /* MMC Interrupt Mask register */
65: #define MMC_I_REG 0x2c /* MMC Interrupt Request register */
66: #define MMC_CMD 0x30 /* MMC Command register */
67: #define MMC_ARGH 0x34 /* MMC Argument High register */
68: #define MMC_ARGL 0x38 /* MMC Argument Low register */
69: #define MMC_RES 0x3c /* MMC Response FIFO */
70: #define MMC_RXFIFO 0x40 /* MMC Receive FIFO */
71: #define MMC_TXFIFO 0x44 /* MMC Transmit FIFO */
72: #define MMC_RDWAIT 0x48 /* MMC RD_WAIT register */
73: #define MMC_BLKS_REM 0x4c /* MMC Blocks Remaining register */
74:
75: /* Bitfield masks */
76: #define STRPCL_STOP_CLK (1 << 0)
77: #define STRPCL_STRT_CLK (1 << 1)
78: #define STAT_TOUT_RES (1 << 1)
79: #define STAT_CLK_EN (1 << 8)
80: #define STAT_DATA_DONE (1 << 11)
81: #define STAT_PRG_DONE (1 << 12)
82: #define STAT_END_CMDRES (1 << 13)
83: #define SPI_SPI_MODE (1 << 0)
84: #define CMDAT_RES_TYPE (3 << 0)
85: #define CMDAT_DATA_EN (1 << 2)
86: #define CMDAT_WR_RD (1 << 3)
87: #define CMDAT_DMA_EN (1 << 7)
88: #define CMDAT_STOP_TRAN (1 << 10)
89: #define INT_DATA_DONE (1 << 0)
90: #define INT_PRG_DONE (1 << 1)
91: #define INT_END_CMD (1 << 2)
92: #define INT_STOP_CMD (1 << 3)
93: #define INT_CLK_OFF (1 << 4)
94: #define INT_RXFIFO_REQ (1 << 5)
95: #define INT_TXFIFO_REQ (1 << 6)
96: #define INT_TINT (1 << 7)
97: #define INT_DAT_ERR (1 << 8)
98: #define INT_RES_ERR (1 << 9)
99: #define INT_RD_STALLED (1 << 10)
100: #define INT_SDIO_INT (1 << 11)
101: #define INT_SDIO_SACK (1 << 12)
102: #define PRTBUF_PRT_BUF (1 << 0)
103:
104: /* Route internal interrupt lines to the global IC and DMA */
1.1.1.3 root 105: static void pxa2xx_mmci_int_update(PXA2xxMMCIState *s)
1.1 root 106: {
107: uint32_t mask = s->intmask;
108: if (s->cmdat & CMDAT_DMA_EN) {
109: mask |= INT_RXFIFO_REQ | INT_TXFIFO_REQ;
110:
1.1.1.7 root 111: qemu_set_irq(s->rx_dma, !!(s->intreq & INT_RXFIFO_REQ));
112: qemu_set_irq(s->tx_dma, !!(s->intreq & INT_TXFIFO_REQ));
1.1 root 113: }
114:
115: qemu_set_irq(s->irq, !!(s->intreq & ~mask));
116: }
117:
1.1.1.3 root 118: static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s)
1.1 root 119: {
120: if (!s->active)
121: return;
122:
123: if (s->cmdat & CMDAT_WR_RD) {
124: while (s->bytesleft && s->tx_len) {
125: sd_write_data(s->card, s->tx_fifo[s->tx_start ++]);
126: s->tx_start &= 0x1f;
127: s->tx_len --;
128: s->bytesleft --;
129: }
130: if (s->bytesleft)
131: s->intreq |= INT_TXFIFO_REQ;
132: } else
133: while (s->bytesleft && s->rx_len < 32) {
134: s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] =
135: sd_read_data(s->card);
136: s->bytesleft --;
137: s->intreq |= INT_RXFIFO_REQ;
138: }
139:
140: if (!s->bytesleft) {
141: s->active = 0;
142: s->intreq |= INT_DATA_DONE;
143: s->status |= STAT_DATA_DONE;
144:
145: if (s->cmdat & CMDAT_WR_RD) {
146: s->intreq |= INT_PRG_DONE;
147: s->status |= STAT_PRG_DONE;
148: }
149: }
150:
151: pxa2xx_mmci_int_update(s);
152: }
153:
1.1.1.3 root 154: static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s)
1.1 root 155: {
156: int rsplen, i;
1.1.1.3 root 157: SDRequest request;
1.1 root 158: uint8_t response[16];
159:
160: s->active = 1;
161: s->rx_len = 0;
162: s->tx_len = 0;
163: s->cmdreq = 0;
164:
165: request.cmd = s->cmd;
166: request.arg = s->arg;
167: request.crc = 0; /* FIXME */
168:
169: rsplen = sd_do_command(s->card, &request, response);
170: s->intreq |= INT_END_CMD;
171:
172: memset(s->resp_fifo, 0, sizeof(s->resp_fifo));
173: switch (s->cmdat & CMDAT_RES_TYPE) {
174: #define PXAMMCI_RESP(wd, value0, value1) \
175: s->resp_fifo[(wd) + 0] |= (value0); \
176: s->resp_fifo[(wd) + 1] |= (value1) << 8;
177: case 0: /* No response */
178: goto complete;
179:
180: case 1: /* R1, R4, R5 or R6 */
181: if (rsplen < 4)
182: goto timeout;
183: goto complete;
184:
185: case 2: /* R2 */
186: if (rsplen < 16)
187: goto timeout;
188: goto complete;
189:
190: case 3: /* R3 */
191: if (rsplen < 4)
192: goto timeout;
193: goto complete;
194:
195: complete:
196: for (i = 0; rsplen > 0; i ++, rsplen -= 2) {
197: PXAMMCI_RESP(i, response[i * 2], response[i * 2 + 1]);
198: }
199: s->status |= STAT_END_CMDRES;
200:
201: if (!(s->cmdat & CMDAT_DATA_EN))
202: s->active = 0;
203: else
204: s->bytesleft = s->numblk * s->blklen;
205:
206: s->resp_len = 0;
207: break;
208:
209: timeout:
210: s->active = 0;
211: s->status |= STAT_TOUT_RES;
212: break;
213: }
214:
215: pxa2xx_mmci_fifo_update(s);
216: }
217:
218: static uint32_t pxa2xx_mmci_read(void *opaque, target_phys_addr_t offset)
219: {
1.1.1.3 root 220: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 221: uint32_t ret;
222:
223: switch (offset) {
224: case MMC_STRPCL:
225: return 0;
226: case MMC_STAT:
227: return s->status;
228: case MMC_CLKRT:
229: return s->clkrt;
230: case MMC_SPI:
231: return s->spi;
232: case MMC_CMDAT:
233: return s->cmdat;
234: case MMC_RESTO:
235: return s->resp_tout;
236: case MMC_RDTO:
237: return s->read_tout;
238: case MMC_BLKLEN:
239: return s->blklen;
240: case MMC_NUMBLK:
241: return s->numblk;
242: case MMC_PRTBUF:
243: return 0;
244: case MMC_I_MASK:
245: return s->intmask;
246: case MMC_I_REG:
247: return s->intreq;
248: case MMC_CMD:
249: return s->cmd | 0x40;
250: case MMC_ARGH:
251: return s->arg >> 16;
252: case MMC_ARGL:
253: return s->arg & 0xffff;
254: case MMC_RES:
255: if (s->resp_len < 9)
256: return s->resp_fifo[s->resp_len ++];
257: return 0;
258: case MMC_RXFIFO:
259: ret = 0;
260: while (s->ac_width -- && s->rx_len) {
261: ret |= s->rx_fifo[s->rx_start ++] << (s->ac_width << 3);
262: s->rx_start &= 0x1f;
263: s->rx_len --;
264: }
265: s->intreq &= ~INT_RXFIFO_REQ;
266: pxa2xx_mmci_fifo_update(s);
267: return ret;
268: case MMC_RDWAIT:
269: return 0;
270: case MMC_BLKS_REM:
271: return s->numblk;
272: default:
1.1.1.3 root 273: hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
1.1 root 274: }
275:
276: return 0;
277: }
278:
279: static void pxa2xx_mmci_write(void *opaque,
280: target_phys_addr_t offset, uint32_t value)
281: {
1.1.1.3 root 282: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 283:
284: switch (offset) {
285: case MMC_STRPCL:
286: if (value & STRPCL_STRT_CLK) {
287: s->status |= STAT_CLK_EN;
288: s->intreq &= ~INT_CLK_OFF;
289:
290: if (s->cmdreq && !(s->cmdat & CMDAT_STOP_TRAN)) {
291: s->status &= STAT_CLK_EN;
292: pxa2xx_mmci_wakequeues(s);
293: }
294: }
295:
296: if (value & STRPCL_STOP_CLK) {
297: s->status &= ~STAT_CLK_EN;
298: s->intreq |= INT_CLK_OFF;
299: s->active = 0;
300: }
301:
302: pxa2xx_mmci_int_update(s);
303: break;
304:
305: case MMC_CLKRT:
306: s->clkrt = value & 7;
307: break;
308:
309: case MMC_SPI:
310: s->spi = value & 0xf;
311: if (value & SPI_SPI_MODE)
312: printf("%s: attempted to use card in SPI mode\n", __FUNCTION__);
313: break;
314:
315: case MMC_CMDAT:
316: s->cmdat = value & 0x3dff;
317: s->active = 0;
318: s->cmdreq = 1;
319: if (!(value & CMDAT_STOP_TRAN)) {
320: s->status &= STAT_CLK_EN;
321:
322: if (s->status & STAT_CLK_EN)
323: pxa2xx_mmci_wakequeues(s);
324: }
325:
326: pxa2xx_mmci_int_update(s);
327: break;
328:
329: case MMC_RESTO:
330: s->resp_tout = value & 0x7f;
331: break;
332:
333: case MMC_RDTO:
334: s->read_tout = value & 0xffff;
335: break;
336:
337: case MMC_BLKLEN:
338: s->blklen = value & 0xfff;
339: break;
340:
341: case MMC_NUMBLK:
342: s->numblk = value & 0xffff;
343: break;
344:
345: case MMC_PRTBUF:
346: if (value & PRTBUF_PRT_BUF) {
347: s->tx_start ^= 32;
348: s->tx_len = 0;
349: }
350: pxa2xx_mmci_fifo_update(s);
351: break;
352:
353: case MMC_I_MASK:
354: s->intmask = value & 0x1fff;
355: pxa2xx_mmci_int_update(s);
356: break;
357:
358: case MMC_CMD:
359: s->cmd = value & 0x3f;
360: break;
361:
362: case MMC_ARGH:
363: s->arg &= 0x0000ffff;
364: s->arg |= value << 16;
365: break;
366:
367: case MMC_ARGL:
368: s->arg &= 0xffff0000;
369: s->arg |= value & 0x0000ffff;
370: break;
371:
372: case MMC_TXFIFO:
373: while (s->ac_width -- && s->tx_len < 0x20)
374: s->tx_fifo[(s->tx_start + (s->tx_len ++)) & 0x1f] =
375: (value >> (s->ac_width << 3)) & 0xff;
376: s->intreq &= ~INT_TXFIFO_REQ;
377: pxa2xx_mmci_fifo_update(s);
378: break;
379:
380: case MMC_RDWAIT:
381: case MMC_BLKS_REM:
382: break;
383:
384: default:
1.1.1.3 root 385: hw_error("%s: Bad offset " REG_FMT "\n", __FUNCTION__, offset);
1.1 root 386: }
387: }
388:
389: static uint32_t pxa2xx_mmci_readb(void *opaque, target_phys_addr_t offset)
390: {
1.1.1.3 root 391: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 392: s->ac_width = 1;
393: return pxa2xx_mmci_read(opaque, offset);
394: }
395:
396: static uint32_t pxa2xx_mmci_readh(void *opaque, target_phys_addr_t offset)
397: {
1.1.1.3 root 398: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 399: s->ac_width = 2;
400: return pxa2xx_mmci_read(opaque, offset);
401: }
402:
403: static uint32_t pxa2xx_mmci_readw(void *opaque, target_phys_addr_t offset)
404: {
1.1.1.3 root 405: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 406: s->ac_width = 4;
407: return pxa2xx_mmci_read(opaque, offset);
408: }
409:
410: static void pxa2xx_mmci_writeb(void *opaque,
411: target_phys_addr_t offset, uint32_t value)
412: {
1.1.1.3 root 413: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 414: s->ac_width = 1;
415: pxa2xx_mmci_write(opaque, offset, value);
416: }
417:
418: static void pxa2xx_mmci_writeh(void *opaque,
419: target_phys_addr_t offset, uint32_t value)
420: {
1.1.1.3 root 421: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 422: s->ac_width = 2;
423: pxa2xx_mmci_write(opaque, offset, value);
424: }
425:
426: static void pxa2xx_mmci_writew(void *opaque,
427: target_phys_addr_t offset, uint32_t value)
428: {
1.1.1.3 root 429: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 430: s->ac_width = 4;
431: pxa2xx_mmci_write(opaque, offset, value);
432: }
433:
1.1.1.9 ! root 434: static const MemoryRegionOps pxa2xx_mmci_ops = {
! 435: .old_mmio = {
! 436: .read = { pxa2xx_mmci_readb,
! 437: pxa2xx_mmci_readh,
! 438: pxa2xx_mmci_readw, },
! 439: .write = { pxa2xx_mmci_writeb,
! 440: pxa2xx_mmci_writeh,
! 441: pxa2xx_mmci_writew, },
! 442: },
! 443: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 444: };
445:
446: static void pxa2xx_mmci_save(QEMUFile *f, void *opaque)
447: {
1.1.1.3 root 448: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 449: int i;
450:
451: qemu_put_be32s(f, &s->status);
452: qemu_put_be32s(f, &s->clkrt);
453: qemu_put_be32s(f, &s->spi);
454: qemu_put_be32s(f, &s->cmdat);
455: qemu_put_be32s(f, &s->resp_tout);
456: qemu_put_be32s(f, &s->read_tout);
457: qemu_put_be32(f, s->blklen);
458: qemu_put_be32(f, s->numblk);
459: qemu_put_be32s(f, &s->intmask);
460: qemu_put_be32s(f, &s->intreq);
461: qemu_put_be32(f, s->cmd);
462: qemu_put_be32s(f, &s->arg);
463: qemu_put_be32(f, s->cmdreq);
464: qemu_put_be32(f, s->active);
465: qemu_put_be32(f, s->bytesleft);
466:
467: qemu_put_byte(f, s->tx_len);
468: for (i = 0; i < s->tx_len; i ++)
469: qemu_put_byte(f, s->tx_fifo[(s->tx_start + i) & 63]);
470:
471: qemu_put_byte(f, s->rx_len);
472: for (i = 0; i < s->rx_len; i ++)
473: qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 31]);
474:
475: qemu_put_byte(f, s->resp_len);
476: for (i = s->resp_len; i < 9; i ++)
477: qemu_put_be16s(f, &s->resp_fifo[i]);
478: }
479:
480: static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id)
481: {
1.1.1.3 root 482: PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
1.1 root 483: int i;
484:
485: qemu_get_be32s(f, &s->status);
486: qemu_get_be32s(f, &s->clkrt);
487: qemu_get_be32s(f, &s->spi);
488: qemu_get_be32s(f, &s->cmdat);
489: qemu_get_be32s(f, &s->resp_tout);
490: qemu_get_be32s(f, &s->read_tout);
491: s->blklen = qemu_get_be32(f);
492: s->numblk = qemu_get_be32(f);
493: qemu_get_be32s(f, &s->intmask);
494: qemu_get_be32s(f, &s->intreq);
495: s->cmd = qemu_get_be32(f);
496: qemu_get_be32s(f, &s->arg);
497: s->cmdreq = qemu_get_be32(f);
498: s->active = qemu_get_be32(f);
499: s->bytesleft = qemu_get_be32(f);
500:
501: s->tx_len = qemu_get_byte(f);
502: s->tx_start = 0;
503: if (s->tx_len >= sizeof(s->tx_fifo) || s->tx_len < 0)
504: return -EINVAL;
505: for (i = 0; i < s->tx_len; i ++)
506: s->tx_fifo[i] = qemu_get_byte(f);
507:
508: s->rx_len = qemu_get_byte(f);
509: s->rx_start = 0;
510: if (s->rx_len >= sizeof(s->rx_fifo) || s->rx_len < 0)
511: return -EINVAL;
512: for (i = 0; i < s->rx_len; i ++)
513: s->rx_fifo[i] = qemu_get_byte(f);
514:
515: s->resp_len = qemu_get_byte(f);
516: if (s->resp_len > 9 || s->resp_len < 0)
517: return -EINVAL;
518: for (i = s->resp_len; i < 9; i ++)
519: qemu_get_be16s(f, &s->resp_fifo[i]);
520:
521: return 0;
522: }
523:
1.1.1.9 ! root 524: PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
! 525: target_phys_addr_t base,
1.1.1.7 root 526: BlockDriverState *bd, qemu_irq irq,
527: qemu_irq rx_dma, qemu_irq tx_dma)
1.1 root 528: {
1.1.1.3 root 529: PXA2xxMMCIState *s;
1.1 root 530:
1.1.1.8 root 531: s = (PXA2xxMMCIState *) g_malloc0(sizeof(PXA2xxMMCIState));
1.1 root 532: s->irq = irq;
1.1.1.7 root 533: s->rx_dma = rx_dma;
534: s->tx_dma = tx_dma;
1.1 root 535:
1.1.1.9 ! root 536: memory_region_init_io(&s->iomem, &pxa2xx_mmci_ops, s,
! 537: "pxa2xx-mmci", 0x00100000);
! 538: memory_region_add_subregion(sysmem, base, &s->iomem);
1.1 root 539:
540: /* Instantiate the actual storage */
541: s->card = sd_init(bd, 0);
542:
1.1.1.5 root 543: register_savevm(NULL, "pxa2xx_mmci", 0, 0,
1.1 root 544: pxa2xx_mmci_save, pxa2xx_mmci_load, s);
545:
546: return s;
547: }
548:
1.1.1.3 root 549: void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
1.1 root 550: qemu_irq coverswitch)
551: {
552: sd_set_cb(s->card, readonly, coverswitch);
553: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.