2 * OMAP on-chip MMC/SD host emulation.
4 * Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 or
9 * (at your option) version 3 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
50 uint16_t blen_counter
;
52 uint16_t nblk_counter
;
67 static void omap_mmc_interrupts_update(struct omap_mmc_s
*s
)
69 qemu_set_irq(s
->irq
, !!(s
->status
& s
->mask
));
72 static void omap_mmc_fifolevel_update(struct omap_mmc_s
*host
)
74 if (!host
->transfer
&& !host
->fifo_len
) {
75 host
->status
&= 0xf3ff;
79 if (host
->fifo_len
> host
->af_level
&& host
->ddir
) {
81 host
->status
&= 0xfbff;
82 qemu_irq_raise(host
->dma
[1]);
84 host
->status
|= 0x0400;
86 host
->status
&= 0xfbff;
87 qemu_irq_lower(host
->dma
[1]);
90 if (host
->fifo_len
< host
->ae_level
&& !host
->ddir
) {
92 host
->status
&= 0xf7ff;
93 qemu_irq_raise(host
->dma
[0]);
95 host
->status
|= 0x0800;
97 qemu_irq_lower(host
->dma
[0]);
98 host
->status
&= 0xf7ff;
103 sd_nore
= 0, /* no response */
104 sd_r1
, /* normal response command */
105 sd_r2
, /* CID, CSD registers */
106 sd_r3
, /* OCR register */
107 sd_r6
= 6, /* Published RCA response */
111 static void omap_mmc_command(struct omap_mmc_s
*host
, int cmd
, int dir
,
112 sd_cmd_type_t type
, int busy
, sd_rsp_type_t resptype
, int init
)
114 uint32_t rspstatus
, mask
;
116 struct sd_request_s request
;
117 uint8_t response
[16];
119 if (init
&& cmd
== 0) {
120 host
->status
|= 0x0001;
124 if (resptype
== sd_r1
&& busy
)
127 if (type
== sd_adtc
) {
128 host
->fifo_start
= 0;
139 request
.arg
= host
->arg
;
140 request
.crc
= 0; /* FIXME */
142 rsplen
= sd_do_command(host
->card
, &request
, response
);
144 /* TODO: validate CRCs */
158 mask
= OUT_OF_RANGE
| ADDRESS_ERROR
| BLOCK_LEN_ERROR
|
159 ERASE_SEQ_ERROR
| ERASE_PARAM
| WP_VIOLATION
|
160 LOCK_UNLOCK_FAILED
| COM_CRC_ERROR
| ILLEGAL_COMMAND
|
161 CARD_ECC_FAILED
| CC_ERROR
| SD_ERROR
|
163 if (host
->sdio
& (1 << 13))
164 mask
|= AKE_SEQ_ERROR
;
165 rspstatus
= (response
[0] << 24) | (response
[1] << 16) |
166 (response
[2] << 8) | (response
[3] << 0);
184 rspstatus
= (response
[0] << 24) | (response
[1] << 16) |
185 (response
[2] << 8) | (response
[3] << 0);
186 if (rspstatus
& 0x80000000)
187 host
->status
&= 0xe000;
189 host
->status
|= 0x1000;
199 mask
= 0xe000 | AKE_SEQ_ERROR
;
200 rspstatus
= (response
[2] << 8) | (response
[3] << 0);
203 if (rspstatus
& mask
)
204 host
->status
|= 0x4000;
206 host
->status
&= 0xb000;
209 for (rsplen
= 0; rsplen
< 8; rsplen
++)
210 host
->rsp
[~rsplen
& 7] = response
[(rsplen
<< 1) | 1] |
211 (response
[(rsplen
<< 1) | 0] << 8);
214 host
->status
|= 0x0080;
216 host
->status
|= 0x0005; /* Makes it more real */
218 host
->status
|= 0x0001;
221 static void omap_mmc_transfer(struct omap_mmc_s
*host
)
230 if (host
->fifo_len
> host
->af_level
)
233 value
= sd_read_data(host
->card
);
234 host
->fifo
[(host
->fifo_start
+ host
->fifo_len
) & 31] = value
;
235 if (-- host
->blen_counter
) {
236 value
= sd_read_data(host
->card
);
237 host
->fifo
[(host
->fifo_start
+ host
->fifo_len
) & 31] |=
239 host
->blen_counter
--;
247 value
= host
->fifo
[host
->fifo_start
] & 0xff;
248 sd_write_data(host
->card
, value
);
249 if (-- host
->blen_counter
) {
250 value
= host
->fifo
[host
->fifo_start
] >> 8;
251 sd_write_data(host
->card
, value
);
252 host
->blen_counter
--;
257 host
->fifo_start
&= 31;
260 if (host
->blen_counter
== 0) {
261 host
->nblk_counter
--;
262 host
->blen_counter
= host
->blen
;
264 if (host
->nblk_counter
== 0) {
265 host
->nblk_counter
= host
->nblk
;
267 host
->status
|= 0x0008;
274 static void omap_mmc_update(void *opaque
)
276 struct omap_mmc_s
*s
= opaque
;
277 omap_mmc_transfer(s
);
278 omap_mmc_fifolevel_update(s
);
279 omap_mmc_interrupts_update(s
);
282 void omap_mmc_reset(struct omap_mmc_s
*host
)
285 memset(host
->rsp
, 0, sizeof(host
->rsp
));
296 host
->blen_counter
= 0;
298 host
->nblk_counter
= 0;
301 host
->ae_level
= 0x00;
302 host
->af_level
= 0x1f;
304 host
->cdet_wakeup
= 0;
305 host
->cdet_enable
= 0;
306 qemu_set_irq(host
->coverswitch
, host
->cdet_state
);
310 static uint32_t omap_mmc_read(void *opaque
, target_phys_addr_t offset
)
313 struct omap_mmc_s
*s
= (struct omap_mmc_s
*) opaque
;
314 offset
&= OMAP_MPUI_REG_MASK
;
317 case 0x00: /* MMC_CMD */
320 case 0x04: /* MMC_ARGL */
321 return s
->arg
& 0x0000ffff;
323 case 0x08: /* MMC_ARGH */
326 case 0x0c: /* MMC_CON */
327 return (s
->dw
<< 15) | (s
->mode
<< 12) | (s
->enable
<< 11) |
328 (s
->be
<< 10) | s
->clkdiv
;
330 case 0x10: /* MMC_STAT */
333 case 0x14: /* MMC_IE */
336 case 0x18: /* MMC_CTO */
339 case 0x1c: /* MMC_DTO */
342 case 0x20: /* MMC_DATA */
343 /* TODO: support 8-bit access */
344 i
= s
->fifo
[s
->fifo_start
];
345 if (s
->fifo_len
== 0) {
346 printf("MMC: FIFO underrun\n");
352 omap_mmc_transfer(s
);
353 omap_mmc_fifolevel_update(s
);
354 omap_mmc_interrupts_update(s
);
357 case 0x24: /* MMC_BLEN */
358 return s
->blen_counter
;
360 case 0x28: /* MMC_NBLK */
361 return s
->nblk_counter
;
363 case 0x2c: /* MMC_BUF */
364 return (s
->rx_dma
<< 15) | (s
->af_level
<< 8) |
365 (s
->tx_dma
<< 7) | s
->ae_level
;
367 case 0x30: /* MMC_SPI */
369 case 0x34: /* MMC_SDIO */
370 return (s
->cdet_wakeup
<< 2) | (s
->cdet_enable
) | s
->sdio
;
371 case 0x38: /* MMC_SYST */
374 case 0x3c: /* MMC_REV */
377 case 0x40: /* MMC_RSP0 */
378 case 0x44: /* MMC_RSP1 */
379 case 0x48: /* MMC_RSP2 */
380 case 0x4c: /* MMC_RSP3 */
381 case 0x50: /* MMC_RSP4 */
382 case 0x54: /* MMC_RSP5 */
383 case 0x58: /* MMC_RSP6 */
384 case 0x5c: /* MMC_RSP7 */
385 return s
->rsp
[(offset
- 0x40) >> 2];
388 case 0x60: /* MMC_IOSR */
389 case 0x64: /* MMC_SYSC */
391 case 0x68: /* MMC_SYSS */
395 OMAP_BAD_REG(offset
);
399 static void omap_mmc_write(void *opaque
, target_phys_addr_t offset
,
403 struct omap_mmc_s
*s
= (struct omap_mmc_s
*) opaque
;
404 offset
&= OMAP_MPUI_REG_MASK
;
407 case 0x00: /* MMC_CMD */
412 for (i
= 0; i
< 8; i
++)
414 omap_mmc_command(s
, value
& 63, (value
>> 15) & 1,
415 (sd_cmd_type_t
) ((value
>> 12) & 3),
417 (sd_rsp_type_t
) ((value
>> 8) & 7),
422 case 0x04: /* MMC_ARGL */
423 s
->arg
&= 0xffff0000;
424 s
->arg
|= 0x0000ffff & value
;
427 case 0x08: /* MMC_ARGH */
428 s
->arg
&= 0x0000ffff;
429 s
->arg
|= value
<< 16;
432 case 0x0c: /* MMC_CON */
433 s
->dw
= (value
>> 15) & 1;
434 s
->mode
= (value
>> 12) & 3;
435 s
->enable
= (value
>> 11) & 1;
436 s
->be
= (value
>> 10) & 1;
437 s
->clkdiv
= (value
>> 0) & (s
->rev
>= 2 ? 0x3ff : 0xff);
439 printf("SD mode %i unimplemented!\n", s
->mode
);
441 printf("SD FIFO byte sex unimplemented!\n");
442 if (s
->dw
!= 0 && s
->lines
< 4)
443 printf("4-bit SD bus enabled\n");
448 case 0x10: /* MMC_STAT */
450 omap_mmc_interrupts_update(s
);
453 case 0x14: /* MMC_IE */
454 s
->mask
= value
& 0x7fff;
455 omap_mmc_interrupts_update(s
);
458 case 0x18: /* MMC_CTO */
459 s
->cto
= value
& 0xff;
460 if (s
->cto
> 0xfd && s
->rev
<= 1)
461 printf("MMC: CTO of 0xff and 0xfe cannot be used!\n");
464 case 0x1c: /* MMC_DTO */
465 s
->dto
= value
& 0xffff;
468 case 0x20: /* MMC_DATA */
469 /* TODO: support 8-bit access */
470 if (s
->fifo_len
== 32)
472 s
->fifo
[(s
->fifo_start
+ s
->fifo_len
) & 31] = value
;
474 omap_mmc_transfer(s
);
475 omap_mmc_fifolevel_update(s
);
476 omap_mmc_interrupts_update(s
);
479 case 0x24: /* MMC_BLEN */
480 s
->blen
= (value
& 0x07ff) + 1;
481 s
->blen_counter
= s
->blen
;
484 case 0x28: /* MMC_NBLK */
485 s
->nblk
= (value
& 0x07ff) + 1;
486 s
->nblk_counter
= s
->nblk
;
487 s
->blen_counter
= s
->blen
;
490 case 0x2c: /* MMC_BUF */
491 s
->rx_dma
= (value
>> 15) & 1;
492 s
->af_level
= (value
>> 8) & 0x1f;
493 s
->tx_dma
= (value
>> 7) & 1;
494 s
->ae_level
= value
& 0x1f;
500 omap_mmc_fifolevel_update(s
);
501 omap_mmc_interrupts_update(s
);
504 /* SPI, SDIO and TEST modes unimplemented */
505 case 0x30: /* MMC_SPI (OMAP1 only) */
507 case 0x34: /* MMC_SDIO */
508 s
->sdio
= value
& (s
->rev
>= 2 ? 0xfbf3 : 0x2020);
509 s
->cdet_wakeup
= (value
>> 9) & 1;
510 s
->cdet_enable
= (value
>> 2) & 1;
512 case 0x38: /* MMC_SYST */
515 case 0x3c: /* MMC_REV */
516 case 0x40: /* MMC_RSP0 */
517 case 0x44: /* MMC_RSP1 */
518 case 0x48: /* MMC_RSP2 */
519 case 0x4c: /* MMC_RSP3 */
520 case 0x50: /* MMC_RSP4 */
521 case 0x54: /* MMC_RSP5 */
522 case 0x58: /* MMC_RSP6 */
523 case 0x5c: /* MMC_RSP7 */
528 case 0x60: /* MMC_IOSR */
530 printf("MMC: SDIO bits used!\n");
532 case 0x64: /* MMC_SYSC */
533 if (value
& (1 << 2)) /* SRTS */
536 case 0x68: /* MMC_SYSS */
541 OMAP_BAD_REG(offset
);
545 static CPUReadMemoryFunc
*omap_mmc_readfn
[] = {
546 omap_badwidth_read16
,
548 omap_badwidth_read16
,
551 static CPUWriteMemoryFunc
*omap_mmc_writefn
[] = {
552 omap_badwidth_write16
,
554 omap_badwidth_write16
,
557 static void omap_mmc_cover_cb(void *opaque
, int line
, int level
)
559 struct omap_mmc_s
*host
= (struct omap_mmc_s
*) opaque
;
561 if (!host
->cdet_state
&& level
) {
562 host
->status
|= 0x0002;
563 omap_mmc_interrupts_update(host
);
564 if (host
->cdet_wakeup
)
565 /* TODO: Assert wake-up */;
568 if (host
->cdet_state
!= level
) {
569 qemu_set_irq(host
->coverswitch
, level
);
570 host
->cdet_state
= level
;
574 struct omap_mmc_s
*omap_mmc_init(target_phys_addr_t base
,
575 BlockDriverState
*bd
,
576 qemu_irq irq
, qemu_irq dma
[], omap_clk clk
)
579 struct omap_mmc_s
*s
= (struct omap_mmc_s
*)
580 qemu_mallocz(sizeof(struct omap_mmc_s
));
585 s
->lines
= 1; /* TODO: needs to be settable per-board */
590 iomemtype
= cpu_register_io_memory(0, omap_mmc_readfn
,
591 omap_mmc_writefn
, s
);
592 cpu_register_physical_memory(base
, 0x800, iomemtype
);
594 /* Instantiate the storage */
595 s
->card
= sd_init(bd
, 0);
600 struct omap_mmc_s
*omap2_mmc_init(struct omap_target_agent_s
*ta
,
601 BlockDriverState
*bd
, qemu_irq irq
, qemu_irq dma
[],
602 omap_clk fclk
, omap_clk iclk
)
605 struct omap_mmc_s
*s
= (struct omap_mmc_s
*)
606 qemu_mallocz(sizeof(struct omap_mmc_s
));
616 iomemtype
= l4_register_io_memory(0, omap_mmc_readfn
,
617 omap_mmc_writefn
, s
);
618 omap_l4_attach(ta
, 0, iomemtype
);
620 /* Instantiate the storage */
621 s
->card
= sd_init(bd
, 0);
623 s
->cdet
= qemu_allocate_irqs(omap_mmc_cover_cb
, s
, 1)[0];
624 sd_set_cb(s
->card
, 0, s
->cdet
);
629 void omap_mmc_handlers(struct omap_mmc_s
*s
, qemu_irq ro
, qemu_irq cover
)
632 sd_set_cb(s
->card
, ro
, s
->cdet
);
633 s
->coverswitch
= cover
;
634 qemu_set_irq(cover
, s
->cdet_state
);
636 sd_set_cb(s
->card
, ro
, cover
);
639 void omap_mmc_enable(struct omap_mmc_s
*s
, int enable
)
641 sd_enable(s
->card
, enable
);