Message ID | 20230703132509.2474225-21-clg@kaod.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | hw/sd: eMMC support | expand |
On 3/7/23 15:24, Cédric Le Goater wrote: > From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com> > > MMC cards support different tuning sequence for entering HS200 mode. > > Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> > [ clg: - ported on QEMU 7.0 ] > Signed-off-by: Cédric Le Goater <clg@kaod.org> > --- > hw/sd/sd.c | 40 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 40 insertions(+) > > diff --git a/hw/sd/sd.c b/hw/sd/sd.c > index 4b4a4cda2e68..7332f7a18435 100644 > --- a/hw/sd/sd.c > +++ b/hw/sd/sd.c > @@ -2017,6 +2017,30 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { > 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, > }; > > +#define EXCSD_BUS_WIDTH_OFFSET 183 > +#define BUS_WIDTH_8_MASK 0x4 > +#define BUS_WIDTH_4_MASK 0x2 > +#define MMC_TUNING_BLOCK_SIZE 128 > + > +static const uint8_t mmc_tuning_block_pattern[128] = { > + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, > + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, > + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, > + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, > + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, > + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, > + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, > + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, > + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, > + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, > + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, > + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, > + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, > + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, > + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, > + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, > +}; > + > uint8_t sd_read_byte(SDState *sd) > { > /* TODO: Append CRCs */ > @@ -2103,6 +2127,22 @@ uint8_t sd_read_byte(SDState *sd) > ret = sd_tuning_block_pattern[sd->data_offset++]; > break; > > + case 21: /* CMD21: SEND_TUNING_BLOCK (MMC) */ This can be accessed in SPI/SD modes, should we check for eMMC then? Similarly, other cases previous eMMC introduction only expect SPI/SD but don't check for it. I need to think a bit more on how to handle that. > + if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { > + sd->state = sd_transfer_state; > + } > + if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { > + ret = mmc_tuning_block_pattern[sd->data_offset++]; > + } else { > + /* > + * Return LSB Nibbles of two byte from the 8bit tuning > + * block for 4bit mode > + */ > + ret = mmc_tuning_block_pattern[sd->data_offset++] & 0x0F; > + ret |= (mmc_tuning_block_pattern[sd->data_offset++] & 0x0F) << 4; > + } > + break; > + > case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ > ret = sd->data[sd->data_offset ++]; >
On 13/6/24 00:15, Philippe Mathieu-Daudé wrote: > On 3/7/23 15:24, Cédric Le Goater wrote: >> From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com> >> >> MMC cards support different tuning sequence for entering HS200 mode. >> >> Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com> >> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> >> [ clg: - ported on QEMU 7.0 ] >> Signed-off-by: Cédric Le Goater <clg@kaod.org> >> --- >> hw/sd/sd.c | 40 ++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 40 insertions(+) >> >> diff --git a/hw/sd/sd.c b/hw/sd/sd.c >> index 4b4a4cda2e68..7332f7a18435 100644 >> --- a/hw/sd/sd.c >> +++ b/hw/sd/sd.c >> @@ -2017,6 +2017,30 @@ static const uint8_t >> sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { >> 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, >> }; >> +#define EXCSD_BUS_WIDTH_OFFSET 183 >> +#define BUS_WIDTH_8_MASK 0x4 >> +#define BUS_WIDTH_4_MASK 0x2 >> +#define MMC_TUNING_BLOCK_SIZE 128 >> + >> +static const uint8_t mmc_tuning_block_pattern[128] = { >> + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, >> + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, >> + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, >> + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, >> + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, >> + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, >> + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, >> + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, >> + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, >> + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, >> + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, >> + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, >> + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, >> + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, >> + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, >> + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, >> +}; >> + >> uint8_t sd_read_byte(SDState *sd) >> { >> /* TODO: Append CRCs */ >> @@ -2103,6 +2127,22 @@ uint8_t sd_read_byte(SDState *sd) >> ret = sd_tuning_block_pattern[sd->data_offset++]; >> break; >> + case 21: /* CMD21: SEND_TUNING_BLOCK (MMC) */ > > This can be accessed in SPI/SD modes, should we check for eMMC then? This could do: -- >8 -- diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3c12ba2ad3..5bad19c766 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -160,12 +160,18 @@ static const struct SDProto *sd_proto(SDState *sd) } static const SDProto sd_proto_spi; +static const SDProto sd_proto_emmc; static bool sd_is_spi(SDState *sd) { return sd_proto(sd) == &sd_proto_spi; } +static bool sd_is_emmc(SDState *sd) +{ + return sd_proto(sd) == &sd_proto_emmc; +} + static const char *sd_version_str(enum SDPhySpecificationVersion version) { static const char *sdphy_version[] = { @@ -2389,7 +2395,9 @@ uint8_t sd_read_byte(SDState *sd) break; case 21: /* CMD21: SEND_TUNING_BLOCK (MMC) */ + if (!sd_is_emmc(sd)) { + return 0x00; + } if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { sd->state = sd_transfer_state; } --- > Similarly, other cases previous eMMC introduction only expect SPI/SD > but don't check for it. I need to think a bit more on how to handle > that. > >> + if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { >> + sd->state = sd_transfer_state; >> + } >> + if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { >> + ret = mmc_tuning_block_pattern[sd->data_offset++]; >> + } else { >> + /* >> + * Return LSB Nibbles of two byte from the 8bit tuning >> + * block for 4bit mode >> + */ >> + ret = mmc_tuning_block_pattern[sd->data_offset++] & 0x0F; >> + ret |= (mmc_tuning_block_pattern[sd->data_offset++] & >> 0x0F) << 4; >> + } >> + break; >> + >> case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ >> ret = sd->data[sd->data_offset ++]; >
diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 4b4a4cda2e68..7332f7a18435 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -2017,6 +2017,30 @@ static const uint8_t sd_tuning_block_pattern[SD_TUNING_BLOCK_SIZE] = { 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, }; +#define EXCSD_BUS_WIDTH_OFFSET 183 +#define BUS_WIDTH_8_MASK 0x4 +#define BUS_WIDTH_4_MASK 0x2 +#define MMC_TUNING_BLOCK_SIZE 128 + +static const uint8_t mmc_tuning_block_pattern[128] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, +}; + uint8_t sd_read_byte(SDState *sd) { /* TODO: Append CRCs */ @@ -2103,6 +2127,22 @@ uint8_t sd_read_byte(SDState *sd) ret = sd_tuning_block_pattern[sd->data_offset++]; break; + case 21: /* CMD21: SEND_TUNING_BLOCK (MMC) */ + if (sd->data_offset >= MMC_TUNING_BLOCK_SIZE - 1) { + sd->state = sd_transfer_state; + } + if (sd->ext_csd[EXCSD_BUS_WIDTH_OFFSET] & BUS_WIDTH_8_MASK) { + ret = mmc_tuning_block_pattern[sd->data_offset++]; + } else { + /* + * Return LSB Nibbles of two byte from the 8bit tuning + * block for 4bit mode + */ + ret = mmc_tuning_block_pattern[sd->data_offset++] & 0x0F; + ret |= (mmc_tuning_block_pattern[sd->data_offset++] & 0x0F) << 4; + } + break; + case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ ret = sd->data[sd->data_offset ++];