Skip to content

Commit 1585ab9

Browse files
committed
hw/sd/sdcard: Fill SPI response bits in card code
ssi-sd.c contains the SPI link layer adaptation, while sd.c contains all the SD card internal details. We already handle the response values in sd.c, but missed the SPI case. Complete them (fill R1, prepend R1 in R3/R7 and always return something in SPI mode). Remove all the duplication in ssi-sd.c. Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Acked-by: Richard Henderson <[email protected]> Message-Id: <[email protected]>
1 parent b82e7a2 commit 1585ab9

File tree

2 files changed

+35
-84
lines changed

2 files changed

+35
-84
lines changed

hw/sd/sd.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -734,22 +734,24 @@ static size_t sd_response_size(SDState *sd, sd_rsp_type_t rtype)
734734
switch (rtype) {
735735
case sd_r1:
736736
case sd_r1b:
737-
return 4;
737+
return sd_is_spi(sd) ? 1 : 4;
738738

739739
case sd_r2_i:
740740
case sd_r2_s:
741+
assert(!sd_is_spi(sd));
741742
return 16;
742743

743744
case sd_r3:
744745
case sd_r7:
745-
return 4;
746+
return sd_is_spi(sd) ? 5 : 4;
746747

747748
case sd_r6:
749+
assert(!sd_is_spi(sd));
748750
return 4;
749751

750752
case sd_r0:
751753
case sd_illegal:
752-
return 0;
754+
return sd_is_spi(sd) ? 1 : 0;
753755

754756
default:
755757
g_assert_not_reached();
@@ -758,14 +760,31 @@ static size_t sd_response_size(SDState *sd, sd_rsp_type_t rtype)
758760

759761
static void sd_response_r1_make(SDState *sd, uint8_t *response)
760762
{
761-
stl_be_p(response, sd->card_status);
763+
if (sd_is_spi(sd)) {
764+
response[0] = sd->state == sd_idle_state
765+
&& !FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP);
766+
response[0] |= FIELD_EX32(sd->card_status, CSR, ERASE_RESET) << 1;
767+
response[0] |= FIELD_EX32(sd->card_status, CSR, ILLEGAL_COMMAND) << 2;
768+
response[0] |= FIELD_EX32(sd->card_status, CSR, COM_CRC_ERROR) << 3;
769+
response[0] |= FIELD_EX32(sd->card_status, CSR, ERASE_SEQ_ERROR) << 4;
770+
response[0] |= FIELD_EX32(sd->card_status, CSR, ADDRESS_ERROR) << 5;
771+
response[0] |= FIELD_EX32(sd->card_status, CSR, BLOCK_LEN_ERROR) << 6;
772+
response[0] |= 0 << 7;
773+
} else {
774+
stl_be_p(response, sd->card_status);
775+
}
762776

763777
/* Clear the "clear on read" status bits */
764778
sd->card_status &= ~CARD_STATUS_C;
765779
}
766780

767781
static void sd_response_r3_make(SDState *sd, uint8_t *response)
768782
{
783+
if (sd_is_spi(sd)) {
784+
/* Prepend R1 */
785+
sd_response_r1_make(sd, response);
786+
response++;
787+
}
769788
stl_be_p(response, sd->ocr & ACMD41_R3_MASK);
770789
}
771790

@@ -783,6 +802,11 @@ static void sd_response_r6_make(SDState *sd, uint8_t *response)
783802

784803
static void sd_response_r7_make(SDState *sd, uint8_t *response)
785804
{
805+
if (sd_is_spi(sd)) {
806+
/* Prepend R1 */
807+
sd_response_r1_make(sd, response);
808+
response++;
809+
}
786810
stl_be_p(response, sd->vhs);
787811
}
788812

hw/sd/ssi-sd.c

Lines changed: 7 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,6 @@ struct ssi_sd_state {
7070
#define TYPE_SSI_SD "ssi-sd"
7171
OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD)
7272

73-
/* State word bits. */
74-
#define SSI_SDR_LOCKED 0x0001
75-
#define SSI_SDR_WP_ERASE 0x0002
76-
#define SSI_SDR_ERROR 0x0004
77-
#define SSI_SDR_CC_ERROR 0x0008
78-
#define SSI_SDR_ECC_FAILED 0x0010
79-
#define SSI_SDR_WP_VIOLATION 0x0020
80-
#define SSI_SDR_ERASE_PARAM 0x0040
81-
#define SSI_SDR_OUT_OF_RANGE 0x0080
82-
#define SSI_SDR_IDLE 0x0100
83-
#define SSI_SDR_ERASE_RESET 0x0200
84-
#define SSI_SDR_ILLEGAL_COMMAND 0x0400
85-
#define SSI_SDR_COM_CRC_ERROR 0x0800
86-
#define SSI_SDR_ERASE_SEQ_ERROR 0x1000
87-
#define SSI_SDR_ADDRESS_ERROR 0x2000
88-
#define SSI_SDR_PARAMETER_ERROR 0x4000
89-
9073
/* multiple block write */
9174
#define SSI_TOKEN_MULTI_WRITE 0xfc
9275
/* terminate multiple block write */
@@ -104,7 +87,7 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
10487
{
10588
ssi_sd_state *s = SSI_SD(dev);
10689
SDRequest request;
107-
uint8_t longresp[16];
90+
uint8_t longresp[5];
10891

10992
/*
11093
* Special case: allow CMD12 (STOP TRANSMISSION) while reading data.
@@ -171,74 +154,18 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val)
171154
/* FIXME: Check CRC. */
172155
request.cmd = s->cmd;
173156
request.arg = ldl_be_p(s->cmdarg);
174-
DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
175157
s->arglen = sdbus_do_command(&s->sdbus, &request,
176158
longresp, sizeof(longresp));
177-
if (s->arglen == 0) {
178-
s->arglen = 1;
179-
s->response[0] = 4;
180-
DPRINTF("SD command failed\n");
181-
} else if (s->cmd == 8 || s->cmd == 58) {
182-
/* CMD8/CMD58 returns R3/R7 response */
183-
DPRINTF("Returned R3/R7\n");
184-
s->arglen = 5;
185-
s->response[0] = 1;
186-
memcpy(&s->response[1], longresp, 4);
187-
} else if (s->arglen != 4) {
188-
BADF("Unexpected response to cmd %d\n", s->cmd);
189-
/* Illegal command is about as near as we can get. */
190-
s->arglen = 1;
191-
s->response[0] = 4;
192-
} else {
193-
/* All other commands return status. */
194-
uint32_t cardstatus;
195-
uint16_t status;
159+
DPRINTF("CMD%d arg 0x%08x = %d\n", s->cmd, request.arg, s->arglen);
160+
assert(s->arglen > 0);
196161
/* CMD13 returns a 2-byte statuse work. Other commands
197162
only return the first byte. */
198163
s->arglen = (s->cmd == 13) ? 2 : 1;
164+
memcpy(s->response, longresp, s->arglen);
199165

200-
/* handle R1b */
201-
if (s->cmd == 28 || s->cmd == 29 || s->cmd == 38) {
202-
s->stopping = 1;
203-
}
204-
205-
cardstatus = ldl_be_p(longresp);
206-
status = 0;
207-
if (((cardstatus >> 9) & 0xf) < 4)
208-
status |= SSI_SDR_IDLE;
209-
if (cardstatus & ERASE_RESET)
210-
status |= SSI_SDR_ERASE_RESET;
211-
if (cardstatus & ILLEGAL_COMMAND)
212-
status |= SSI_SDR_ILLEGAL_COMMAND;
213-
if (cardstatus & COM_CRC_ERROR)
214-
status |= SSI_SDR_COM_CRC_ERROR;
215-
if (cardstatus & ERASE_SEQ_ERROR)
216-
status |= SSI_SDR_ERASE_SEQ_ERROR;
217-
if (cardstatus & ADDRESS_ERROR)
218-
status |= SSI_SDR_ADDRESS_ERROR;
219-
if (cardstatus & CARD_IS_LOCKED)
220-
status |= SSI_SDR_LOCKED;
221-
if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP))
222-
status |= SSI_SDR_WP_ERASE;
223-
if (cardstatus & SD_ERROR)
224-
status |= SSI_SDR_ERROR;
225-
if (cardstatus & CC_ERROR)
226-
status |= SSI_SDR_CC_ERROR;
227-
if (cardstatus & CARD_ECC_FAILED)
228-
status |= SSI_SDR_ECC_FAILED;
229-
if (cardstatus & WP_VIOLATION)
230-
status |= SSI_SDR_WP_VIOLATION;
231-
if (cardstatus & ERASE_PARAM)
232-
status |= SSI_SDR_ERASE_PARAM;
233-
if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE))
234-
status |= SSI_SDR_OUT_OF_RANGE;
235-
/* ??? Don't know what Parameter Error really means, so
236-
assume it's set if the second byte is nonzero. */
237-
if (status & 0xff)
238-
status |= SSI_SDR_PARAMETER_ERROR;
239-
s->response[0] = status >> 8;
240-
s->response[1] = status;
241-
DPRINTF("Card status 0x%02x\n", status);
166+
/* handle R1b (busy signal) */
167+
if (s->cmd == 28 || s->cmd == 29 || s->cmd == 38) {
168+
s->stopping = 1;
242169
}
243170
s->mode = SSI_SD_PREP_RESP;
244171
s->response_pos = 0;

0 commit comments

Comments
 (0)