2 * OMAP3 Multimedia Card/Secure Digital/Secure Digital I/O (MMC/SD/SDIO) Card Interface emulation
4 * Copyright (C) 2008 yajin <yajin@vm-kernel.org>
5 * Copyright (C) 2009 Nokia Corporation
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 1 - print out all commands in processing order
29 2 - dump all register accesses and buffer management */
30 #define MMC_DEBUG_LEVEL 0
33 #define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
35 #define TRACE2(...) TRACE(__VA_ARGS__)
77 uint16_t blen_counter;
78 uint16_t nblk_counter;
88 uint32_t stat_pending;
94 sd_nore = 0, /* no response */
95 sd_136_bits = 1, /* response length 136 bits */
96 sd_48_bits = 2, /* response length 48 bits */
97 sd_48b_bits = 3, /* response length 48 bits with busy after response */
98 } omap3_sd_rsp_type_t;
100 static void omap3_mmc_command(struct omap3_mmc_s *host);
102 static void omap3_mmc_interrupts_update(struct omap3_mmc_s *s)
104 qemu_set_irq(s->irq, !!((s->stat | s->stat_pending) & s->ie & s->ise));
107 static void omap3_mmc_fifolevel_update(struct omap3_mmc_s *host)
109 enum { ongoing, ready, aborted } state = ongoing;
111 if ((host->cmd & (1 << 21))) { /* DP */
113 TRACE2("receive, dma=%d, fifo_len=%d bytes",
114 host->cmd & 1, host->fifo_len * 4);
116 /* omap3_mmc_transfer ensures we always have data in FIFO
117 during receive as long as all data has not been transferred -
118 NOTE that the actual transfer may be finished already (i.e.
119 host->transfer is cleared) but not all data has been read out
121 if (host->fifo_len) {
122 if (host->cmd & 1) { /* DE */
123 if (host->fifo_len * 4 == (host->blk & 0x7ff)) { /* BLEN */
127 qemu_irq_raise(host->dma[1]);
129 qemu_irq_lower(host->dma[1]);
132 && host->fifo_len * 4 == (host->blk & 0x7ff))
135 host->pstate |= 0x0800; /* BRE */
136 host->stat_pending |= 0x20; /* BRR */
141 state = host->stop ? aborted : ready;
143 /* omap3_mmc_transfer keeps FIFO empty during transmit so
144 we just check all blocks have been transferred or not */
145 if (host->transfer) {
146 if (host->cmd & 1) { /* DE */
147 if (host->blen_counter == (host->blk & 0x7ff)) { /* BLEN */
151 qemu_irq_raise(host->dma[0]);
153 qemu_irq_lower(host->dma[0]);
156 && host->blen_counter == (host->blk & 0x7ff))
159 host->pstate |= 0x0400; /* BWE */
160 host->stat_pending |= 0x10; /* BWR */
164 state = host->stop ? aborted : ready;
167 if ((host->cmd & 1) || state != ongoing) { /* DE */
168 host->pstate &= ~0x0c00; /* BRE | BWE */
169 host->stat_pending &= ~0x30; /* BRR | BWR */
170 host->stat &= ~0x30; /* BRR | BWR */
171 if (state != ongoing) {
172 TRACE2("transfer %s",
175 : "aborted --> complete");
176 host->stat_pending |= 0x2; /* TC */
177 if (host->cmd & 0x04) { /* ACEN */
178 host->stop = 0x0cc30000;
181 if (state == aborted) {
182 host->cmd = host->stop;
184 omap3_mmc_command(host);
191 static void omap3_mmc_transfer(struct omap3_mmc_s *host)
195 #if MMC_DEBUG_LEVEL>1
200 /* IF data transfer is inactive
201 OR block count enabled with zero block count
202 OR in receive mode and we have unread data in FIFO
203 OR in transmit mode and we have no data in FIFO,
204 THEN don't do anything */
206 || ((host->cmd & 2) && !host->nblk_counter)
207 || (host->ddir && host->fifo_len)
208 || (!host->ddir && !host->fifo_len))
212 TRACE2("begin, %d blocks (%d bytes/block) left to receive, %d bytes in FIFO",
213 (host->cmd & 2) ? host->nblk_counter : 1,
216 while (host->blen_counter && host->fifo_len < 255) {
217 for (i = 0, x = 0; i < 32 && host->blen_counter; i += 8, host->blen_counter--)
218 x |= sd_read_data(host->card) << i;
219 host->fifo[(host->fifo_start + host->fifo_len) & 0xff] = x;
222 TRACE2("end, %d bytes in FIFO:", host->fifo_len * 4);
223 #if MMC_DEBUG_LEVEL>1
224 for (i = 0; i < host->fifo_len; ) {
225 fprintf(stderr, "%s: [0x%03x] ", __FUNCTION__, i * 4);
227 x = host->fifo[(host->fifo_start + i) & 0xff];
228 for (j = 0; j < 4; j++) {
229 c = (x >> (j * 8)) & 0xff;
230 fprintf(stderr, "%02x ", c);
231 sym[(i & 3) * 4 + j] = (c < 32 || c > 126) ? '.' : c;
233 } while (((++i) & 3));
235 fprintf(stderr, "%s\n", sym);
239 TRACE2("%d bytes left to transmit in current block", host->blen_counter);
240 while (host->blen_counter && host->fifo_len) {
241 for (i = 0; i < 32 && host->blen_counter; i += 8, host->blen_counter--)
242 sd_write_data(host->card, (host->fifo[host->fifo_start] >> i) & 0xff);
245 host->fifo_start &= 0xff;
249 if (!host->blen_counter) {
250 if (host->cmd & 2) /* BCE */
251 host->nblk_counter--;
252 TRACE2("block done, %d blocks left",
253 (host->cmd & (1 << 5)) ? host->nblk_counter : 0);
254 host->blen_counter = host->blk & 0x7ff;
255 if (!(host->cmd & (1 << 5)) /* MSBS */
256 || !host->nblk_counter) {
257 host->nblk_counter = (host->blk >> 16) & 0xffff;
259 host->pstate &= ~0x0306; /* RTA | WTA | DLA | DATI */
264 static void omap3_mmc_command(struct omap3_mmc_s *host)
266 uint32_t rspstatus, mask;
269 uint8_t response[16];
270 int cmd = (host->cmd >> 24) & 0x3f; /* INDX */
272 TRACE("%d type=%d arg=0x%08x blk=0x%08x, fifo=%d/%d",
273 cmd, (host->cmd >> 22) & 3, host->arg, host->blk,
274 host->fifo_start, host->fifo_len);
276 if ((host->con & 2) && !cmd) { /* INIT and CMD0 */
277 host->stat_pending |= 0x1;
278 host->pstate &= 0xfffffffe;
282 if (host->cmd & (1 << 21)) { /* DP */
283 host->fifo_start = 0;
286 host->ddir = (host->cmd >> 4) & 1;
287 /* DLA | DATI | (RTA/WTA) */
288 host->pstate |= 0x6 | (host->ddir ? 0x200 : 0x100);
291 host->pstate &= ~0x306; /* RTA | WTA | DLA | DATI */
299 request.arg = host->arg;
300 request.crc = 0; /* FIXME */
302 rsplen = sd_do_command(host->card, &request, response);
304 switch ((host->cmd >> 16) & 3) { /* RSP_TYPE */
314 host->rsp76 = (response[0] << 24) | (response[1] << 16) |
315 (response[2] << 8) | (response[3] << 0);
316 host->rsp54 = (response[4] << 24) | (response[5] << 16) |
317 (response[6] << 8) | (response[7] << 0);
318 host->rsp32 = (response[8] << 24) | (response[9] << 16) |
319 (response[10] << 8) | (response[11] << 0);
320 host->rsp10 = (response[12] << 24) | (response[13] << 16) |
321 (response[14] << 8) | (response[15] << 0);
330 host->rsp10 = (response[0] << 24) | (response[1] << 16) |
331 (response[2] << 8) | (response[3] << 0);
338 rspstatus = (response[2] << 8) | response[3];
341 mask = OUT_OF_RANGE | ADDRESS_ERROR | BLOCK_LEN_ERROR |
342 ERASE_SEQ_ERROR | ERASE_PARAM | WP_VIOLATION |
343 LOCK_UNLOCK_FAILED | COM_CRC_ERROR | ILLEGAL_COMMAND |
344 CARD_ECC_FAILED | CC_ERROR | SD_ERROR |
345 CID_CSD_OVERWRITE | WP_ERASE_SKIP;
346 rspstatus = (response[0] << 24) | (response[1] << 16) |
347 (response[2] << 8) | (response[3] << 0);
354 if (cmd == 12 || cmd == 52) { /* stop transfer commands */
355 /*host->fifo_start = 0;*/
356 /*host->fifo_len = 0;*/
358 host->pstate &= ~0x0f06; /* BRE | BWE | RTA | WTA | DLA | DATI */
359 host->stat_pending &= ~0x30; /* BRR | BWR */
360 host->stat &= ~0x30; /* BRR | BWR */
361 host->stat_pending |= 0x2; /* TC */
362 qemu_irq_lower(host->dma[0]);
363 qemu_irq_lower(host->dma[1]);
366 if (rspstatus & mask & host->csre) {
367 host->stat_pending |= 1 << 28; /* CERR */
368 host->pstate &= ~0x306; /* RTA | WTA | DLA | DATI */
371 host->stat &= ~(1 << 28); /* CERR */
372 host->stat_pending &= ~(1 << 28); /* CERR */
374 host->stat_pending |= timeout ? (1 << 16) : 0x1; /* CTO : CC */
377 static void omap3_mmc_reset(struct omap3_mmc_s *s)
379 s->sysconfig = 0x00000015;
381 s->pstate = 0x00040000;
382 s->capa = 0x00e10080;
390 static uint32_t omap3_mmc_read(void *opaque, target_phys_addr_t addr)
392 struct omap3_mmc_s *s = (struct omap3_mmc_s *) opaque;
397 TRACE2("SYSCONFIG = %08x", s->sysconfig);
400 TRACE2("SYSSTATUS = %08x", s->sysstatus | 0x1);
401 return s->sysstatus | 0x1; /*reset completed */
403 TRACE2("CSRE = %08x", s->csre);
406 TRACE2("SYSTEST = %08x", s->systest);
408 case 0x2c: /* MMCHS_CON */
409 TRACE2("CON = %08x", s->con);
412 TRACE2("PWCNT = %08x", s->pwcnt);
414 case 0x104: /* MMCHS_BLK */
415 TRACE2("BLK = %08x", s->blk);
417 case 0x108: /* MMCHS_ARG */
418 TRACE2("ARG = %08x", s->arg);
421 TRACE2("CMD = %08x", s->cmd);
424 TRACE2("RSP10 = %08x", s->rsp10);
427 TRACE2("RSP32 = %08x", s->rsp32);
430 TRACE2("RSP54 = %08x", s->rsp54);
433 TRACE2("RSP76 = %08x", s->rsp76);
436 /* in PIO mode, access allowed only when BRE is set */
437 if (!(s->cmd & 1) && !(s->pstate & 0x0800)) {
438 s->stat_pending |= 1 << 29; /* BADA */
441 i = s->fifo[s->fifo_start];
442 s->fifo[s->fifo_start] = 0;
443 if (s->fifo_len == 0) {
444 fprintf(stderr, "%s: FIFO underrun\n", __FUNCTION__);
449 s->fifo_start &= 255;
450 omap3_mmc_transfer(s);
451 omap3_mmc_fifolevel_update(s);
453 omap3_mmc_interrupts_update(s);
455 case 0x124: /* MMCHS_PSTATE */
456 TRACE2("PSTATE = %08x", s->pstate);
459 TRACE2("HCTL = %08x", s->hctl);
461 case 0x12c: /* MMCHS_SYSCTL */
462 TRACE2("SYSCTL = %08x", s->sysctl);
464 case 0x130: /* MMCHS_STAT */
465 s->stat |= s->stat_pending;
466 if (s->stat & 0xffff0000)
467 s->stat |= 1 << 15; /* ERRI */
469 s->stat &= ~(1 << 15); /* ERRI */
471 TRACE2("STAT = %08x", s->stat);
474 TRACE2("IE = %08x", s->ie);
477 TRACE2("ISE = %08x", s->ise);
480 TRACE2("AC12 = %08x", s->ac12);
482 case 0x140: /* MMCHS_CAPA */
483 TRACE2("CAPA = %08x", s->capa);
486 TRACE2("CUR_CAPA = %08x", s->cur_capa);
489 TRACE2("REV = %08x", s->rev);
498 static void omap3_mmc_write(void *opaque, target_phys_addr_t addr,
501 struct omap3_mmc_s *s = (struct omap3_mmc_s *) opaque;
515 TRACE2("SYSCONFIG = %08x", value);
518 s->sysconfig = value & 0x31d;
521 TRACE2("CSRE = %08x", value);
525 TRACE2("SYSTEST = %08x", value);
528 case 0x02c: /* MMCHS_CON */
529 TRACE2("CON = %08x", value);
530 if (value & 0x10) /* MODE */
531 fprintf(stderr, "%s: SYSTEST mode is not supported\n",
533 if (value & 0x20) /* DW8 */
534 fprintf(stderr, "%s: 8-bit data width is not supported\n",
536 if (value & 0x1000) /* CEATA */
537 fprintf(stderr, "%s: CE-ATA control mode not supported\n",
539 s->con = value & 0x1ffff;
542 TRACE2("PWCNT = %08x", value);
545 case 0x104: /* MMCHS_BLK */
546 TRACE2("BLK = %08x", value);
547 s->blk = value & 0xffff07ff;
548 s->blen_counter = value & 0x7ff;
549 s->nblk_counter = (value >> 16) & 0xffff;
551 case 0x108: /* MMCHS_ARG */
552 TRACE2("ARG = %08x", value);
555 case 0x10c: /* MMCHS_CMD */
556 TRACE2("CMD = %08x", value);
558 s->stat_pending |= (1 << 16); /* CTO */
560 /* TODO: writing to bits 0-15 should have no effect during
561 an active data transfer */
563 && (((value >> 24) & 0x3f) == 12
564 || ((value >> 24) & 0x3f) == 52)) {
565 s->stop = value & 0x3ffb0037;
567 s->cmd = value & 0x3ffb0037;
568 omap3_mmc_command(s);
570 omap3_mmc_transfer(s);
571 omap3_mmc_fifolevel_update(s);
573 omap3_mmc_interrupts_update(s);
576 /* in PIO mode, access allowed only when BWE is set */
577 if (!(s->cmd & 1) && !(s->pstate & 0x0400)) {
578 s->stat_pending |= 1 << 29; /* BADA */
580 if (s->fifo_len == 256) {
581 fprintf(stderr, "%s: FIFO overrun\n", __FUNCTION__);
584 s->fifo[(s->fifo_start + s->fifo_len) & 255] = value;
586 omap3_mmc_transfer(s);
587 omap3_mmc_fifolevel_update(s);
589 omap3_mmc_interrupts_update(s);
591 case 0x128: /* MMCHS_HCTL */
592 TRACE2("HCTL = %08x", value);
593 s->hctl = value & 0xf0f0f02;
594 if (s->hctl & (1 << 16)) /* SBGR */
595 fprintf(stderr, "%s: Stop at block gap feature not implemented!\n", __FUNCTION__);
597 case 0x12c: /* MMCHS_SYSCTL */
598 TRACE2("SYSCTL = %08x", value);
599 if (value & 0x04000000) { /* SRD */
601 s->pstate &= ~0x00000f06; /* BRE, BWE, RTA, WTA, DLA, DATI */
602 s->hctl &= ~0x00030000; /* SGBR, CR */
603 s->stat &= ~0x00000034; /* BRR, BWR, BGE */
604 s->stat_pending &= ~0x00000034;
608 if (value & 0x02000000) { /* SRC */
609 s->pstate &= ~0x00000001; /* CMDI */
611 if (value & 0x01000000) { /* SRA */
612 uint32_t capa = s->capa;
613 uint32_t cur_capa = s->cur_capa;
616 s->cur_capa = cur_capa;
618 value = (value & ~2) | ((value & 1) << 1); /* copy ICE directly to ICS */
619 s->sysctl = value & 0x000fffc7;
622 TRACE2("STAT = %08x", value);
623 value = value & 0x317f0237;
625 /* stat_pending is NOT cleared */
626 omap3_mmc_interrupts_update(s);
628 case 0x134: /* MMCHS_IE */
629 TRACE2("IE = %08x", value);
630 if (!(s->con & 0x4000)) /* if CON:OBIE is clear, ignore write to OBI_ENABLE */
631 value = (value & ~0x200) | (s->ie & 0x200);
632 s->ie = value & 0x317f0337;
633 if (!(s->ie & 0x100)) {
635 s->stat_pending &= ~0x100;
637 omap3_mmc_interrupts_update(s);
640 TRACE2("ISE = %08x", value);
641 s->ise = value & 0x317f0337;
642 omap3_mmc_interrupts_update(s);
644 case 0x140: /* MMCHS_CAPA */
645 TRACE2("CAPA = %08x", value);
646 s->capa &= ~0x07000000;
647 s->capa |= value & 0x07000000;
650 TRACE2("CUR_CAPA = %08x", value);
651 s->cur_capa = value & 0xffffff;
659 static CPUReadMemoryFunc *omap3_mmc_readfn[] = {
660 omap_badwidth_read32,
661 omap_badwidth_read32,
665 static CPUWriteMemoryFunc *omap3_mmc_writefn[] = {
666 omap_badwidth_write32,
667 omap_badwidth_write32,
671 static void omap3_mmc_save_state(QEMUFile *f, void *opaque)
673 struct omap3_mmc_s *s = (struct omap3_mmc_s *)opaque;
676 qemu_put_be32(f, s->sysconfig);
677 qemu_put_be32(f, s->sysstatus);
678 qemu_put_be32(f, s->csre);
679 qemu_put_be32(f, s->systest);
680 qemu_put_be32(f, s->con);
681 qemu_put_be32(f, s->pwcnt);
682 qemu_put_be32(f, s->blk);
683 qemu_put_be32(f, s->arg);
684 qemu_put_be32(f, s->cmd);
685 qemu_put_be32(f, s->rsp10);
686 qemu_put_be32(f, s->rsp32);
687 qemu_put_be32(f, s->rsp54);
688 qemu_put_be32(f, s->rsp76);
689 qemu_put_be32(f, s->data);
690 qemu_put_be32(f, s->pstate);
691 qemu_put_be32(f, s->hctl);
692 qemu_put_be32(f, s->sysctl);
693 qemu_put_be32(f, s->stat);
694 qemu_put_be32(f, s->ie);
695 qemu_put_be32(f, s->ise);
696 qemu_put_be32(f, s->ac12);
697 qemu_put_be32(f, s->capa);
698 qemu_put_be32(f, s->cur_capa);
699 qemu_put_be32(f, s->rev);
700 qemu_put_be16(f, s->blen_counter);
701 qemu_put_be16(f, s->nblk_counter);
702 for (i = 0; i < sizeof(s->fifo)/sizeof(uint32_t); i++)
703 qemu_put_be32(f, s->fifo[i]);
704 qemu_put_sbe32(f, s->fifo_start);
705 qemu_put_sbe32(f, s->fifo_len);
706 qemu_put_sbe32(f, s->ddir);
707 qemu_put_sbe32(f, s->transfer);
708 qemu_put_sbe32(f, s->stop);
709 qemu_put_be32(f, s->stat_pending);
712 static int omap3_mmc_load_state(QEMUFile *f, void *opaque, int version_id)
714 struct omap3_mmc_s *s = (struct omap3_mmc_s *)opaque;
720 s->sysconfig = qemu_get_be32(f);
721 s->sysstatus = qemu_get_be32(f);
722 s->csre = qemu_get_be32(f);
723 s->systest = qemu_get_be32(f);
724 s->con = qemu_get_be32(f);
725 s->pwcnt = qemu_get_be32(f);
726 s->blk = qemu_get_be32(f);
727 s->arg = qemu_get_be32(f);
728 s->cmd = qemu_get_be32(f);
729 s->rsp10 = qemu_get_be32(f);
730 s->rsp32 = qemu_get_be32(f);
731 s->rsp54 = qemu_get_be32(f);
732 s->rsp76 = qemu_get_be32(f);
733 s->data = qemu_get_be32(f);
734 s->pstate = qemu_get_be32(f);
735 s->hctl = qemu_get_be32(f);
736 s->sysctl = qemu_get_be32(f);
737 s->stat = qemu_get_be32(f);
738 s->ie = qemu_get_be32(f);
739 s->ise = qemu_get_be32(f);
740 s->ac12 = qemu_get_be32(f);
741 s->capa = qemu_get_be32(f);
742 s->cur_capa = qemu_get_be32(f);
743 s->rev = qemu_get_be32(f);
744 s->blen_counter = qemu_get_be16(f);
745 s->nblk_counter = qemu_get_be16(f);
746 for (i = 0; i < sizeof(s->fifo)/sizeof(uint32_t); i++)
747 s->fifo[i] = qemu_get_be32(f);
748 s->fifo_start = qemu_get_sbe32(f);
749 s->fifo_len = qemu_get_sbe32(f);
750 s->ddir = qemu_get_sbe32(f);
751 s->transfer = qemu_get_sbe32(f);
752 s->stop = qemu_get_sbe32(f);
753 s->stat_pending = qemu_get_be32(f);
755 omap3_mmc_fifolevel_update(s);
756 omap3_mmc_interrupts_update(s);
761 struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
762 qemu_irq irq, qemu_irq dma[],
763 omap_clk fclk, omap_clk iclk)
766 struct omap3_mmc_s *s = (struct omap3_mmc_s *)
767 qemu_mallocz(sizeof(struct omap3_mmc_s));
775 iomemtype = l4_register_io_memory(0, omap3_mmc_readfn,
776 omap3_mmc_writefn, s);
777 omap_l4_attach(ta, 0, iomemtype);
779 register_savevm("omap3_mmc", (ta->base >> 12) & 0xff, 0,
780 omap3_mmc_save_state, omap3_mmc_load_state, s);
784 void omap3_mmc_attach(struct omap3_mmc_s *s,
785 BlockDriverState *bd)
788 fprintf(stderr, "%s: SD card already attached!\n", __FUNCTION__);
791 s->card = sd_init(bd, 0);
792 sd_enable(s->card, 1);