Skip to content

Commit 775616c

Browse files
author
pbrook
committed
Partial SD card SPI mode support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3731 c046a42c-6fe2-441c-8c8c-71466251a162
1 parent f3b9f95 commit 775616c

File tree

12 files changed

+370
-16
lines changed

12 files changed

+370
-16
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o
5757
OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o
5858
OBJS+=scsi-disk.o cdrom.o
5959
OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o
60+
OBJS+=sd.o ssi-sd.o
6061

6162
ifdef CONFIG_WIN32
6263
OBJS+=tap-win32.o

Makefile.target

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ endif
488488
ifeq ($(TARGET_BASE_ARCH), arm)
489489
VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
490490
VL_OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
491-
VL_OBJS+= versatile_pci.o sd.o ptimer.o
491+
VL_OBJS+= versatile_pci.o ptimer.o
492492
VL_OBJS+= realview_gic.o realview.o arm_sysctl.o mpcore.o
493493
VL_OBJS+= armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
494494
VL_OBJS+= pl061.o

hw/omap_mmc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ struct omap_mmc_s *omap_mmc_init(target_phys_addr_t base,
525525
cpu_register_physical_memory(s->base, 0x800, iomemtype);
526526

527527
/* Instantiate the storage */
528-
s->card = sd_init(bd);
528+
s->card = sd_init(bd, 0);
529529

530530
return s;
531531
}

hw/pl061.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ typedef struct {
4848
uint8_t slr;
4949
uint8_t den;
5050
uint8_t cr;
51+
uint8_t float_high;
5152
qemu_irq irq;
5253
qemu_irq out[8];
5354
} pl061_state;
@@ -56,18 +57,22 @@ static void pl061_update(pl061_state *s)
5657
{
5758
uint8_t changed;
5859
uint8_t mask;
60+
uint8_t out;
5961
int i;
6062

61-
changed = s->old_data ^ s->data;
63+
/* Outputs float high. */
64+
/* FIXME: This is board dependent. */
65+
out = (s->data & s->dir) | ~s->dir;
66+
changed = s->old_data ^ out;
6267
if (!changed)
6368
return;
6469

65-
s->old_data = s->data;
70+
s->old_data = out;
6671
for (i = 0; i < 8; i++) {
6772
mask = 1 << i;
68-
if ((changed & mask & s->dir) && s->out) {
69-
DPRINTF("Set output %d = %d\n", i, (s->data & mask) != 0);
70-
qemu_set_irq(s->out[i], (s->data & mask) != 0);
73+
if ((changed & mask) && s->out) {
74+
DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
75+
qemu_set_irq(s->out[i], (out & mask) != 0);
7176
}
7277
}
7378

hw/pl181.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ void pl181_init(uint32_t base, BlockDriverState *bd,
458458
pl181_writefn, s);
459459
cpu_register_physical_memory(base, 0x00001000, iomemtype);
460460
s->base = base;
461-
s->card = sd_init(bd);
461+
s->card = sd_init(bd, 0);
462462
s->irq[0] = irq0;
463463
s->irq[1] = irq1;
464464
qemu_register_reset(pl181_reset, s);

hw/primecell.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ void pl011_init(uint32_t base, qemu_irq irq, CharDriverState *chr,
2121
enum pl011_type type);
2222

2323
/* pl022.c */
24-
void pl022_init(uint32_t base, qemu_irq irq, int (*xfer_cb)(void *, int),
24+
typedef int (*ssi_xfer_cb)(void *, int);
25+
void pl022_init(uint32_t base, qemu_irq irq, ssi_xfer_cb xfer_cb,
2526
void *opaque);
2627

2728
/* pl050.c */
2829
void pl050_init(uint32_t base, qemu_irq irq, int is_mouse);
2930

3031
/* pl061.c */
32+
void pl061_float_high(void *opaque, uint8_t mask);
3133
qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out);
3234

3335
/* pl080.c */

hw/pxa2xx_mmci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base,
538538
cpu_register_physical_memory(base, 0x00100000, iomemtype);
539539

540540
/* Instantiate the actual storage */
541-
s->card = sd_init(bd);
541+
s->card = sd_init(bd, 1);
542542

543543
register_savevm("pxa2xx_mmci", 0, 0,
544544
pxa2xx_mmci_save, pxa2xx_mmci_load, s);

hw/sd.c

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct SDState {
8787
int pwd_len;
8888
int function_group[6];
8989

90+
int spi;
9091
int current_cmd;
9192
int blk_written;
9293
uint32_t data_start;
@@ -395,11 +396,16 @@ static void sd_cardchange(void *opaque)
395396
}
396397
}
397398

398-
SDState *sd_init(BlockDriverState *bs)
399+
/* We do not model the chip select pin, so allow the board to select
400+
whether card should be in SSI ot MMC/SD mode. It is also up to the
401+
board to ensure that ssi transfers only occur when the chip select
402+
is asserted. */
403+
SDState *sd_init(BlockDriverState *bs, int is_spi)
399404
{
400405
SDState *sd;
401406

402407
sd = (SDState *) qemu_mallocz(sizeof(SDState));
408+
sd->spi = is_spi;
403409
sd_reset(sd, bs);
404410
bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);
405411
return sd;
@@ -567,16 +573,25 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
567573
case 0: /* CMD0: GO_IDLE_STATE */
568574
switch (sd->state) {
569575
case sd_inactive_state:
570-
return sd_r0;
576+
return sd->spi ? sd_r1 : sd_r0;
571577

572578
default:
573579
sd->state = sd_idle_state;
574580
sd_reset(sd, sd->bdrv);
575-
return sd_r0;
581+
return sd->spi ? sd_r1 : sd_r0;
576582
}
577583
break;
578584

585+
case 1: /* CMD1: SEND_OP_CMD */
586+
if (!sd->spi)
587+
goto bad_cmd;
588+
589+
sd->state = sd_transfer_state;
590+
return sd_r1;
591+
579592
case 2: /* CMD2: ALL_SEND_CID */
593+
if (sd->spi)
594+
goto bad_cmd;
580595
switch (sd->state) {
581596
case sd_ready_state:
582597
sd->state = sd_identification_state;
@@ -588,6 +603,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
588603
break;
589604

590605
case 3: /* CMD3: SEND_RELATIVE_ADDR */
606+
if (sd->spi)
607+
goto bad_cmd;
591608
switch (sd->state) {
592609
case sd_identification_state:
593610
case sd_standby_state:
@@ -601,6 +618,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
601618
break;
602619

603620
case 4: /* CMD4: SEND_DSR */
621+
if (sd->spi)
622+
goto bad_cmd;
604623
switch (sd->state) {
605624
case sd_standby_state:
606625
break;
@@ -611,6 +630,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
611630
break;
612631

613632
case 6: /* CMD6: SWITCH_FUNCTION */
633+
if (sd->spi)
634+
goto bad_cmd;
614635
switch (sd->mode) {
615636
case sd_data_transfer_mode:
616637
sd_function_switch(sd, req.arg);
@@ -625,6 +646,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
625646
break;
626647

627648
case 7: /* CMD7: SELECT/DESELECT_CARD */
649+
if (sd->spi)
650+
goto bad_cmd;
628651
switch (sd->state) {
629652
case sd_standby_state:
630653
if (sd->rca != rca)
@@ -668,6 +691,15 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
668691

669692
return sd_r2_s;
670693

694+
case sd_transfer_state:
695+
if (!sd->spi)
696+
break;
697+
sd->state = sd_sendingdata_state;
698+
memcpy(sd->data, sd->csd, 16);
699+
sd->data_start = req.arg;
700+
sd->data_offset = 0;
701+
return sd_r1;
702+
671703
default:
672704
break;
673705
}
@@ -681,12 +713,23 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
681713

682714
return sd_r2_i;
683715

716+
case sd_transfer_state:
717+
if (!sd->spi)
718+
break;
719+
sd->state = sd_sendingdata_state;
720+
memcpy(sd->data, sd->cid, 16);
721+
sd->data_start = req.arg;
722+
sd->data_offset = 0;
723+
return sd_r1;
724+
684725
default:
685726
break;
686727
}
687728
break;
688729

689730
case 11: /* CMD11: READ_DAT_UNTIL_STOP */
731+
if (sd->spi)
732+
goto bad_cmd;
690733
switch (sd->state) {
691734
case sd_transfer_state:
692735
sd->state = sd_sendingdata_state;
@@ -733,6 +776,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
733776
break;
734777

735778
case 15: /* CMD15: GO_INACTIVE_STATE */
779+
if (sd->spi)
780+
goto bad_cmd;
736781
switch (sd->mode) {
737782
case sd_data_transfer_mode:
738783
if (sd->rca != rca)
@@ -796,8 +841,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
796841

797842
/* Block write commands (Class 4) */
798843
case 24: /* CMD24: WRITE_SINGLE_BLOCK */
844+
if (sd->spi)
845+
goto unimplemented_cmd;
799846
switch (sd->state) {
800847
case sd_transfer_state:
848+
/* Writing in SPI mode not implemented. */
849+
if (sd->spi)
850+
break;
801851
sd->state = sd_receivingdata_state;
802852
sd->data_start = req.arg;
803853
sd->data_offset = 0;
@@ -817,8 +867,13 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
817867
break;
818868

819869
case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */
870+
if (sd->spi)
871+
goto unimplemented_cmd;
820872
switch (sd->state) {
821873
case sd_transfer_state:
874+
/* Writing in SPI mode not implemented. */
875+
if (sd->spi)
876+
break;
822877
sd->state = sd_receivingdata_state;
823878
sd->data_start = req.arg;
824879
sd->data_offset = 0;
@@ -838,6 +893,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
838893
break;
839894

840895
case 26: /* CMD26: PROGRAM_CID */
896+
if (sd->spi)
897+
goto bad_cmd;
841898
switch (sd->state) {
842899
case sd_transfer_state:
843900
sd->state = sd_receivingdata_state;
@@ -851,6 +908,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
851908
break;
852909

853910
case 27: /* CMD27: PROGRAM_CSD */
911+
if (sd->spi)
912+
goto unimplemented_cmd;
854913
switch (sd->state) {
855914
case sd_transfer_state:
856915
sd->state = sd_receivingdata_state;
@@ -962,6 +1021,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
9621021

9631022
/* Lock card commands (Class 7) */
9641023
case 42: /* CMD42: LOCK_UNLOCK */
1024+
if (sd->spi)
1025+
goto unimplemented_cmd;
9651026
switch (sd->state) {
9661027
case sd_transfer_state:
9671028
sd->state = sd_receivingdata_state;
@@ -1000,10 +1061,17 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
10001061
break;
10011062

10021063
default:
1064+
bad_cmd:
10031065
sd->card_status |= ILLEGAL_COMMAND;
10041066

10051067
printf("SD: Unknown CMD%i\n", req.cmd);
10061068
return sd_r0;
1069+
1070+
unimplemented_cmd:
1071+
/* Commands that are recognised but not yet implemented in SPI mode. */
1072+
sd->card_status |= ILLEGAL_COMMAND;
1073+
printf ("SD: CMD%i not implemented in SPI mode\n", req.cmd);
1074+
return sd_r0;
10071075
}
10081076

10091077
sd->card_status |= ILLEGAL_COMMAND;
@@ -1069,6 +1137,11 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
10691137
break;
10701138

10711139
case 41: /* ACMD41: SD_APP_OP_COND */
1140+
if (sd->spi) {
1141+
/* SEND_OP_CMD */
1142+
sd->state = sd_transfer_state;
1143+
return sd_r1;
1144+
}
10721145
switch (sd->state) {
10731146
case sd_idle_state:
10741147
/* We accept any voltage. 10000 V is nothing. */
@@ -1414,6 +1487,14 @@ uint8_t sd_read_data(SDState *sd)
14141487
sd->state = sd_transfer_state;
14151488
break;
14161489

1490+
case 9: /* CMD9: SEND_CSD */
1491+
case 10: /* CMD10: SEND_CID */
1492+
ret = sd->data[sd->data_offset ++];
1493+
1494+
if (sd->data_offset >= 16)
1495+
sd->state = sd_transfer_state;
1496+
break;
1497+
14171498
case 11: /* CMD11: READ_DAT_UNTIL_STOP */
14181499
if (sd->data_offset == 0)
14191500
BLK_READ_BLOCK(sd->data_start, sd->blk_len);

hw/sd.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,16 @@ struct sd_request_s {
6767

6868
typedef struct SDState SDState;
6969

70-
SDState *sd_init(BlockDriverState *bs);
70+
SDState *sd_init(BlockDriverState *bs, int is_spi);
7171
int sd_do_command(SDState *sd, struct sd_request_s *req,
7272
uint8_t *response);
7373
void sd_write_data(SDState *sd, uint8_t value);
7474
uint8_t sd_read_data(SDState *sd);
7575
void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
7676
int sd_data_ready(SDState *sd);
7777

78+
/* ssi-sd.c */
79+
int ssi_sd_xfer(void *opaque, int val);
80+
void *ssi_sd_init(BlockDriverState *bs);
81+
7882
#endif /* __hw_sd_h */

hw/ssd0323.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ int ssd0323_xfer_ssi(void *opaque, int data)
157157
case 0xe3: /* NOP. */
158158
DATA(0);
159159
break;
160+
case 0xff: /* Nasty hack because we don't handle chip selects
161+
properly. */
162+
break;
160163
default:
161164
BADF("Unknown command: 0x%x\n", data);
162165
}

0 commit comments

Comments
 (0)