sd: Enables High Speed Timing for MMC protocol
- Enables HS Timing Mode for MMC protocol. - Reads data about HS modes from EXT_CSD for MMC. Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
This commit is contained in:
parent
c89b2b08ce
commit
496ded03f1
1 changed files with 57 additions and 32 deletions
|
@ -75,7 +75,7 @@ static inline int mmc_set_max_freq(struct sd_card *card, struct sd_csd *card_csd
|
||||||
static int mmc_set_bus_width(struct sd_card *card);
|
static int mmc_set_bus_width(struct sd_card *card);
|
||||||
|
|
||||||
/* Sets card to the fastest timing mode (using CMD6) and SDHC to max frequency */
|
/* Sets card to the fastest timing mode (using CMD6) and SDHC to max frequency */
|
||||||
static int mmc_set_timing(struct sd_card *card);
|
static int mmc_set_timing(struct sd_card *card, struct mmc_ext_csd *card_ext_csd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize MMC card for use with subsystem
|
* Initialize MMC card for use with subsystem
|
||||||
|
@ -170,7 +170,7 @@ int mmc_card_init(struct sd_card *card)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set timing to fastest supported */
|
/* Set timing to fastest supported */
|
||||||
ret = mmc_set_timing(card);
|
ret = mmc_set_timing(card, &card_ext_csd);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -351,35 +351,6 @@ static inline int mmc_set_max_freq(struct sd_card *card, struct sd_csd *card_csd
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmc_set_timing(struct sd_card *card)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct sdhc_command cmd = {0};
|
|
||||||
|
|
||||||
/* Change Card Timing Mode */
|
|
||||||
cmd.opcode = SD_SWITCH;
|
|
||||||
cmd.arg = MMC_SWITCH_HS_TIMING_ARG;
|
|
||||||
cmd.response_type = SD_RSP_TYPE_R1b;
|
|
||||||
cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT;
|
|
||||||
ret = sdhc_request(card->sdhc, &cmd, NULL);
|
|
||||||
if (ret) {
|
|
||||||
LOG_DBG("Error setting bus timing: %d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
sdmmc_wait_ready(card);
|
|
||||||
|
|
||||||
/* Max frequency in HS mode is 52 MHz */
|
|
||||||
card->bus_io.clock = 52000000;
|
|
||||||
card->bus_io.timing = SDHC_TIMING_HS;
|
|
||||||
/* Change SDHC bus timing */
|
|
||||||
ret = sdhc_set_io(card->sdhc, &card->bus_io);
|
|
||||||
if (ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mmc_set_bus_width(struct sd_card *card)
|
static int mmc_set_bus_width(struct sd_card *card)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -392,7 +363,7 @@ static int mmc_set_bus_width(struct sd_card *card)
|
||||||
cmd.arg = MMC_SWITCH_4_BIT_BUS_ARG;
|
cmd.arg = MMC_SWITCH_4_BIT_BUS_ARG;
|
||||||
card->bus_io.bus_width = SDHC_BUS_WIDTH4BIT;
|
card->bus_io.bus_width = SDHC_BUS_WIDTH4BIT;
|
||||||
} else {
|
} else {
|
||||||
/* If only 1 bit bus is supoprted, nothing to be done */
|
/* If only 1 bit bus is supported, nothing to be done */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,9 +385,54 @@ static int mmc_set_bus_width(struct sd_card *card)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmc_set_hs_timing(struct sd_card *card)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct sdhc_command cmd = {0};
|
||||||
|
|
||||||
|
/* Change Card Timing Mode */
|
||||||
|
cmd.opcode = SD_SWITCH;
|
||||||
|
cmd.arg = MMC_SWITCH_HS_TIMING_ARG;
|
||||||
|
cmd.response_type = SD_RSP_TYPE_R1b;
|
||||||
|
cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT;
|
||||||
|
ret = sdhc_request(card->sdhc, &cmd, NULL);
|
||||||
|
if (ret) {
|
||||||
|
LOG_DBG("Error setting bus timing: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
sdmmc_wait_ready(card);
|
||||||
|
|
||||||
|
/* Max frequency in HS mode is 52 MHz */
|
||||||
|
card->bus_io.clock = MMC_CLOCK_52MHZ;
|
||||||
|
card->bus_io.timing = SDHC_TIMING_HS;
|
||||||
|
/* Change SDHC bus timing */
|
||||||
|
ret = sdhc_set_io(card->sdhc, &card->bus_io);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mmc_set_timing(struct sd_card *card, struct mmc_ext_csd *ext)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (ext->device_type.MMC_HS_52_DV) {
|
||||||
|
return mmc_set_HS_timing(card);
|
||||||
|
} else if (ext->device_type.MMC_HS_26_DV) {
|
||||||
|
/* Nothing to do, card is already configured for this */
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int mmc_read_ext_csd(struct sd_card *card, struct mmc_ext_csd *card_ext_csd)
|
static int mmc_read_ext_csd(struct sd_card *card, struct mmc_ext_csd *card_ext_csd)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -454,6 +470,15 @@ static inline void mmc_decode_ext_csd(struct mmc_ext_csd *ext, uint8_t *raw)
|
||||||
(raw[215U] << 24U) + (raw[214U] << 16U) + (raw[213U] << 8U) + (raw[212U] << 0U);
|
(raw[215U] << 24U) + (raw[214U] << 16U) + (raw[213U] << 8U) + (raw[212U] << 0U);
|
||||||
ext->bus_width = raw[183U];
|
ext->bus_width = raw[183U];
|
||||||
ext->hs_timing = raw[185U];
|
ext->hs_timing = raw[185U];
|
||||||
|
ext->device_type.MMC_HS400_DDR_1200MV = ((1 << 7U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS400_DDR_1800MV = ((1 << 6U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS200_SDR_1200MV = ((1 << 5U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS200_SDR_1800MV = ((1 << 4U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS_DDR_1200MV = ((1 << 3U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS_DDR_1800MV = ((1 << 2U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS_52_DV = ((1 << 1U) & raw[196U]);
|
||||||
|
ext->device_type.MMC_HS_26_DV = ((1 << 0U) & raw[196U]);
|
||||||
ext->rev = raw[192U];
|
ext->rev = raw[192U];
|
||||||
ext->power_class = (raw[187] & 0x0F);
|
ext->power_class = (raw[187] & 0x0F);
|
||||||
|
ext->mmc_driver_strengths = raw[197U];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue