On Thu, Dec 31, 2020 at 3:41 AM Bin Meng <bmeng...@gmail.com> wrote: > > From: Bin Meng <bin.m...@windriver.com> > > In the case of a multiple block read operation every transfered > block has its suffix of CRC16. Update the state machine logic to > handle multiple block read. > > This also fixed the wrong command index for STOP_TRANSMISSION, > the required command to interupt the multiple block read command, > in the old codes. It should be CMD12 (0x4c), not CMD13 (0x4d). > > Signed-off-by: Bin Meng <bin.m...@windriver.com>
Acked-by: Alistair Francis <alistair.fran...@wdc.com> Alistair > --- > > hw/sd/ssi-sd.c | 15 ++++++++++++--- > 1 file changed, 12 insertions(+), 3 deletions(-) > > diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c > index 10b0ac2eaf..889260bd8f 100644 > --- a/hw/sd/ssi-sd.c > +++ b/hw/sd/ssi-sd.c > @@ -51,6 +51,7 @@ struct ssi_sd_state { > uint8_t cmdarg[4]; > uint8_t response[5]; > uint16_t crc16; > + int32_t read_bytes; > int32_t arglen; > int32_t response_pos; > int32_t stopping; > @@ -82,7 +83,7 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, > uint32_t val) > ssi_sd_state *s = SSI_SD(dev); > > /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data. */ > - if (s->mode == SSI_SD_DATA_READ && val == 0x4d) { > + if (s->mode == SSI_SD_DATA_READ && val == 0x4c) { > s->mode = SSI_SD_CMD; > /* There must be at least one byte delay before the card responds. > */ > s->stopping = 1; > @@ -200,8 +201,9 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, > uint32_t val) > return 0xfe; > case SSI_SD_DATA_READ: > val = sdbus_read_byte(&s->sdbus); > + s->read_bytes++; > s->crc16 = crc_ccitt_false(s->crc16, (uint8_t *)&val, 1); > - if (!sdbus_data_ready(&s->sdbus)) { > + if (!sdbus_data_ready(&s->sdbus) || s->read_bytes == 512) { > DPRINTF("Data read end\n"); > s->mode = SSI_SD_DATA_CRC16; > } > @@ -212,7 +214,12 @@ static uint32_t ssi_sd_transfer(SSIPeripheral *dev, > uint32_t val) > s->response_pos++; > if (s->response_pos == 2) { > DPRINTF("CRC16 read end\n"); > - s->mode = SSI_SD_CMD; > + if (s->read_bytes == 512 && s->cmd != 17) { > + s->mode = SSI_SD_DATA_START; > + } else { > + s->mode = SSI_SD_CMD; > + } > + s->read_bytes = 0; > s->response_pos = 0; > } > return val; > @@ -252,6 +259,7 @@ static const VMStateDescription vmstate_ssi_sd = { > VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4), > VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5), > VMSTATE_UINT16(crc16, ssi_sd_state), > + VMSTATE_INT32(read_bytes, ssi_sd_state), > VMSTATE_INT32(arglen, ssi_sd_state), > VMSTATE_INT32(response_pos, ssi_sd_state), > VMSTATE_INT32(stopping, ssi_sd_state), > @@ -304,6 +312,7 @@ static void ssi_sd_reset(DeviceState *dev) > memset(s->cmdarg, 0, sizeof(s->cmdarg)); > memset(s->response, 0, sizeof(s->response)); > s->crc16 = 0; > + s->read_bytes = 0; > s->arglen = 0; > s->response_pos = 0; > s->stopping = 0; > -- > 2.25.1 > >