2 * OMAP on-chip MMC/SD host emulation.
4 * Datasheet: TI Multimedia Card (MMC/SD/SDIO) Interface (SPRU765A)
6 * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 or
11 * (at your option) version 3 of the License.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "qemu/osdep.h"
25 #include "hw/arm/omap.h"
26 #include "hw/sd/sdcard_legacy.h"
54 uint16_t blen_counter
;
56 uint16_t nblk_counter
;
71 static void omap_mmc_interrupts_update(struct omap_mmc_s
*s
)
73 qemu_set_irq(s
->irq
, !!(s
->status
& s
->mask
));
76 static void omap_mmc_fifolevel_update(struct omap_mmc_s
*host
)
78 if (!host
->transfer
&& !host
->fifo_len
) {
79 host
->status
&= 0xf3ff;
83 if (host
->fifo_len
> host
->af_level
&& host
->ddir
) {
85 host
->status
&= 0xfbff;
86 qemu_irq_raise(host
->dma
[1]);
88 host
->status
|= 0x0400;
90 host
->status
&= 0xfbff;
91 qemu_irq_lower(host
->dma
[1]);
94 if (host
->fifo_len
< host
->ae_level
&& !host
->ddir
) {
96 host
->status
&= 0xf7ff;
97 qemu_irq_raise(host
->dma
[0]);
99 host
->status
|= 0x0800;
101 qemu_irq_lower(host
->dma
[0]);
102 host
->status
&= 0xf7ff;
107 sd_nore
= 0, /* no response */
108 sd_r1
, /* normal response command */
109 sd_r2
, /* CID, CSD registers */
110 sd_r3
, /* OCR register */
111 sd_r6
= 6, /* Published RCA response */
115 static void omap_mmc_command(struct omap_mmc_s
*host
, int cmd
, int dir
,
116 sd_cmd_type_t type
, int busy
, sd_rsp_type_t resptype
, int init
)
118 uint32_t rspstatus
, mask
;
121 uint8_t response
[16];
123 if (init
&& cmd
== 0) {
124 host
->status
|= 0x0001;
128 if (resptype
== sd_r1
&& busy
)
131 if (type
== sd_adtc
) {
132 host
->fifo_start
= 0;
143 request
.arg
= host
->arg
;
144 request
.crc
= 0; /* FIXME */
146 rsplen
= sd_do_command(host
->card
, &request
, response
);
148 /* TODO: validate CRCs */
162 mask
= OUT_OF_RANGE
| ADDRESS_ERROR
| BLOCK_LEN_ERROR
|
163 ERASE_SEQ_ERROR
| ERASE_PARAM
| WP_VIOLATION
|
164 LOCK_UNLOCK_FAILED
| COM_CRC_ERROR
| ILLEGAL_COMMAND
|
165 CARD_ECC_FAILED
| CC_ERROR
| SD_ERROR
|
167 if (host
->sdio
& (1 << 13))
168 mask
|= AKE_SEQ_ERROR
;
169 rspstatus
= ldl_be_p(response
);
187 rspstatus
= ldl_be_p(response
);
188 if (rspstatus
& 0x80000000)
189 host
->status
&= 0xe000;
191 host
->status
|= 0x1000;
201 mask
= 0xe000 | AKE_SEQ_ERROR
;
202 rspstatus
= (response
[2] << 8) | (response
[3] << 0);
205 if (rspstatus
& mask
)
206 host
->status
|= 0x4000;
208 host
->status
&= 0xb000;
211 for (rsplen
= 0; rsplen
< 8; rsplen
++)
212 host
->rsp
[~rsplen
& 7] = response
[(rsplen
<< 1) | 1] |
213 (response
[(rsplen
<< 1) | 0] << 8);
216 host
->status
|= 0x0080;
218 host
->status
|= 0x0005; /* Makes it more real */
220 host
->status
|= 0x0001;
223 static void omap_mmc_transfer(struct omap_mmc_s
*host
)
232 if (host
->fifo_len
> host
->af_level
)
235 value
= sd_read_byte(host
->card
);
236 host
->fifo
[(host
->fifo_start
+ host
->fifo_len
) & 31] = value
;
237 if (-- host
->blen_counter
) {
238 value
= sd_read_byte(host
->card
);
239 host
->fifo
[(host
->fifo_start
+ host
->fifo_len
) & 31] |=
241 host
->blen_counter
--;
249 value
= host
->fifo
[host
->fifo_start
] & 0xff;
250 sd_write_byte(host
->card
, value
);
251 if (-- host
->blen_counter
) {
252 value
= host
->fifo
[host
->fifo_start
] >> 8;
253 sd_write_byte(host
->card
, value
);
254 host
->blen_counter
--;
259 host
->fifo_start
&= 31;
262 if (host
->blen_counter
== 0) {
263 host
->nblk_counter
--;
264 host
->blen_counter
= host
->blen
;
266 if (host
->nblk_counter
== 0) {
267 host
->nblk_counter
= host
->nblk
;
269 host
->status
|= 0x0008;
276 static void omap_mmc_update(void *opaque
)
278 struct omap_mmc_s
*s
= opaque
;
279 omap_mmc_transfer(s
);
280 omap_mmc_fifolevel_update(s
);
281 omap_mmc_interrupts_update(s
);
284 static void omap_mmc_pseudo_reset(struct omap_mmc_s
*host
)
290 void omap_mmc_reset(struct omap_mmc_s
*host
)
293 memset(host
->rsp
, 0, sizeof(host
->rsp
));
302 host
->blen_counter
= 0;
304 host
->nblk_counter
= 0;
307 host
->ae_level
= 0x00;
308 host
->af_level
= 0x1f;
310 host
->cdet_wakeup
= 0;
311 host
->cdet_enable
= 0;
312 qemu_set_irq(host
->coverswitch
, host
->cdet_state
);
315 omap_mmc_pseudo_reset(host
);
317 /* Since we're still using the legacy SD API the card is not plugged
318 * into any bus, and we must reset it manually. When omap_mmc is
319 * QOMified this must move into the QOM reset function.
321 device_cold_reset(DEVICE(host
->card
));
324 static uint64_t omap_mmc_read(void *opaque
, hwaddr offset
, unsigned size
)
327 struct omap_mmc_s
*s
= opaque
;
330 return omap_badwidth_read16(opaque
, offset
);
334 case 0x00: /* MMC_CMD */
337 case 0x04: /* MMC_ARGL */
338 return s
->arg
& 0x0000ffff;
340 case 0x08: /* MMC_ARGH */
343 case 0x0c: /* MMC_CON */
344 return (s
->dw
<< 15) | (s
->mode
<< 12) | (s
->enable
<< 11) |
345 (s
->be
<< 10) | s
->clkdiv
;
347 case 0x10: /* MMC_STAT */
350 case 0x14: /* MMC_IE */
353 case 0x18: /* MMC_CTO */
356 case 0x1c: /* MMC_DTO */
359 case 0x20: /* MMC_DATA */
360 /* TODO: support 8-bit access */
361 i
= s
->fifo
[s
->fifo_start
];
362 if (s
->fifo_len
== 0) {
363 printf("MMC: FIFO underrun\n");
369 omap_mmc_transfer(s
);
370 omap_mmc_fifolevel_update(s
);
371 omap_mmc_interrupts_update(s
);
374 case 0x24: /* MMC_BLEN */
375 return s
->blen_counter
;
377 case 0x28: /* MMC_NBLK */
378 return s
->nblk_counter
;
380 case 0x2c: /* MMC_BUF */
381 return (s
->rx_dma
<< 15) | (s
->af_level
<< 8) |
382 (s
->tx_dma
<< 7) | s
->ae_level
;
384 case 0x30: /* MMC_SPI */
386 case 0x34: /* MMC_SDIO */
387 return (s
->cdet_wakeup
<< 2) | (s
->cdet_enable
) | s
->sdio
;
388 case 0x38: /* MMC_SYST */
391 case 0x3c: /* MMC_REV */
394 case 0x40: /* MMC_RSP0 */
395 case 0x44: /* MMC_RSP1 */
396 case 0x48: /* MMC_RSP2 */
397 case 0x4c: /* MMC_RSP3 */
398 case 0x50: /* MMC_RSP4 */
399 case 0x54: /* MMC_RSP5 */
400 case 0x58: /* MMC_RSP6 */
401 case 0x5c: /* MMC_RSP7 */
402 return s
->rsp
[(offset
- 0x40) >> 2];
405 case 0x60: /* MMC_IOSR */
406 case 0x64: /* MMC_SYSC */
408 case 0x68: /* MMC_SYSS */
412 OMAP_BAD_REG(offset
);
416 static void omap_mmc_write(void *opaque
, hwaddr offset
,
417 uint64_t value
, unsigned size
)
420 struct omap_mmc_s
*s
= opaque
;
423 omap_badwidth_write16(opaque
, offset
, value
);
428 case 0x00: /* MMC_CMD */
433 for (i
= 0; i
< 8; i
++)
435 omap_mmc_command(s
, value
& 63, (value
>> 15) & 1,
436 (sd_cmd_type_t
) ((value
>> 12) & 3),
438 (sd_rsp_type_t
) ((value
>> 8) & 7),
443 case 0x04: /* MMC_ARGL */
444 s
->arg
&= 0xffff0000;
445 s
->arg
|= 0x0000ffff & value
;
448 case 0x08: /* MMC_ARGH */
449 s
->arg
&= 0x0000ffff;
450 s
->arg
|= value
<< 16;
453 case 0x0c: /* MMC_CON */
454 s
->dw
= (value
>> 15) & 1;
455 s
->mode
= (value
>> 12) & 3;
456 s
->enable
= (value
>> 11) & 1;
457 s
->be
= (value
>> 10) & 1;
458 s
->clkdiv
= (value
>> 0) & (s
->rev
>= 2 ? 0x3ff : 0xff);
460 qemu_log_mask(LOG_UNIMP
,
461 "omap_mmc_wr: mode #%i unimplemented\n", s
->mode
);
464 qemu_log_mask(LOG_UNIMP
,
465 "omap_mmc_wr: Big Endian not implemented\n");
467 if (s
->dw
!= 0 && s
->lines
< 4)
468 printf("4-bit SD bus enabled\n");
470 omap_mmc_pseudo_reset(s
);
473 case 0x10: /* MMC_STAT */
475 omap_mmc_interrupts_update(s
);
478 case 0x14: /* MMC_IE */
479 s
->mask
= value
& 0x7fff;
480 omap_mmc_interrupts_update(s
);
483 case 0x18: /* MMC_CTO */
484 s
->cto
= value
& 0xff;
485 if (s
->cto
> 0xfd && s
->rev
<= 1)
486 printf("MMC: CTO of 0xff and 0xfe cannot be used!\n");
489 case 0x1c: /* MMC_DTO */
490 s
->dto
= value
& 0xffff;
493 case 0x20: /* MMC_DATA */
494 /* TODO: support 8-bit access */
495 if (s
->fifo_len
== 32)
497 s
->fifo
[(s
->fifo_start
+ s
->fifo_len
) & 31] = value
;
499 omap_mmc_transfer(s
);
500 omap_mmc_fifolevel_update(s
);
501 omap_mmc_interrupts_update(s
);
504 case 0x24: /* MMC_BLEN */
505 s
->blen
= (value
& 0x07ff) + 1;
506 s
->blen_counter
= s
->blen
;
509 case 0x28: /* MMC_NBLK */
510 s
->nblk
= (value
& 0x07ff) + 1;
511 s
->nblk_counter
= s
->nblk
;
512 s
->blen_counter
= s
->blen
;
515 case 0x2c: /* MMC_BUF */
516 s
->rx_dma
= (value
>> 15) & 1;
517 s
->af_level
= (value
>> 8) & 0x1f;
518 s
->tx_dma
= (value
>> 7) & 1;
519 s
->ae_level
= value
& 0x1f;
525 omap_mmc_fifolevel_update(s
);
526 omap_mmc_interrupts_update(s
);
529 /* SPI, SDIO and TEST modes unimplemented */
530 case 0x30: /* MMC_SPI (OMAP1 only) */
532 case 0x34: /* MMC_SDIO */
533 s
->sdio
= value
& (s
->rev
>= 2 ? 0xfbf3 : 0x2020);
534 s
->cdet_wakeup
= (value
>> 9) & 1;
535 s
->cdet_enable
= (value
>> 2) & 1;
537 case 0x38: /* MMC_SYST */
540 case 0x3c: /* MMC_REV */
541 case 0x40: /* MMC_RSP0 */
542 case 0x44: /* MMC_RSP1 */
543 case 0x48: /* MMC_RSP2 */
544 case 0x4c: /* MMC_RSP3 */
545 case 0x50: /* MMC_RSP4 */
546 case 0x54: /* MMC_RSP5 */
547 case 0x58: /* MMC_RSP6 */
548 case 0x5c: /* MMC_RSP7 */
553 case 0x60: /* MMC_IOSR */
555 printf("MMC: SDIO bits used!\n");
557 case 0x64: /* MMC_SYSC */
558 if (value
& (1 << 2)) /* SRTS */
561 case 0x68: /* MMC_SYSS */
566 OMAP_BAD_REG(offset
);
570 static const MemoryRegionOps omap_mmc_ops
= {
571 .read
= omap_mmc_read
,
572 .write
= omap_mmc_write
,
573 .endianness
= DEVICE_NATIVE_ENDIAN
,
576 struct omap_mmc_s
*omap_mmc_init(hwaddr base
,
577 MemoryRegion
*sysmem
,
579 qemu_irq irq
, qemu_irq dma
[], omap_clk clk
)
581 struct omap_mmc_s
*s
= g_new0(struct omap_mmc_s
, 1);
586 s
->lines
= 1; /* TODO: needs to be settable per-board */
589 memory_region_init_io(&s
->iomem
, NULL
, &omap_mmc_ops
, s
, "omap.mmc", 0x800);
590 memory_region_add_subregion(sysmem
, base
, &s
->iomem
);
592 /* Instantiate the storage */
593 s
->card
= sd_init(blk
, false);
594 if (s
->card
== NULL
) {