feat(sdmmc): add high speed mode switch validation check for SDIO

This commit is contained in:
sonika.rathi 2024-05-09 10:25:47 +02:00
parent 9ac85e1d7b
commit 1af74c8a4a
3 changed files with 60 additions and 1 deletions

View File

@ -124,6 +124,8 @@ esp_err_t sdmmc_init_mmc_decode_cid(sdmmc_card_t* card);
esp_err_t sdmmc_init_ocr(sdmmc_card_t* card);
esp_err_t sdmmc_init_spi_crc(sdmmc_card_t* card);
esp_err_t sdmmc_init_io(sdmmc_card_t* card);
esp_err_t sdmmc_io_init_read_card_cap(sdmmc_card_t* card, uint8_t* card_cap);
esp_err_t sdmmc_io_init_check_card_cap(sdmmc_card_t* card, uint8_t* card_cap);
esp_err_t sdmmc_init_sd_blocklen(sdmmc_card_t* card);
esp_err_t sdmmc_init_sd_scr(sdmmc_card_t* card);
esp_err_t sdmmc_init_sd_ssr(sdmmc_card_t* card);

View File

@ -32,6 +32,16 @@ static const char* TAG = "sdmmc_init";
} \
} while(0);
#define SDMMC_INIT_STEP_PARAM(condition, function, param) \
do { \
if ((condition)) { \
esp_err_t err = (function)(card, param); \
if (err != ESP_OK) { \
ESP_LOGD(TAG, "%s: %s returned 0x%x", __func__, #function, err); \
return err; \
} \
} \
} while(0);
esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
{
@ -115,6 +125,10 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
/* MMC cards: read CXD */
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_read_ext_csd);
/* SDIO cards: read CCCR card capabilities */
uint8_t card_cap = 0;
SDMMC_INIT_STEP_PARAM(is_sdio, sdmmc_io_init_read_card_cap, &card_cap);
/* Try to switch card to HS mode if the card supports it.
* Set card->max_freq_khz value accordingly.
*/
@ -138,7 +152,8 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
SDMMC_INIT_STEP(is_sdmem, sdmmc_check_scr);
/* Sanity check after eMMC switch to HS mode */
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_check_ext_csd);
/* TODO: add similar checks for SDIO */
/* Sanity check for SDIO after switching the frequency */
SDMMC_INIT_STEP_PARAM(is_sdio, sdmmc_io_init_check_card_cap, &card_cap);
return ESP_OK;
}

View File

@ -120,6 +120,48 @@ esp_err_t sdmmc_init_io(sdmmc_card_t* card)
return ESP_OK;
}
esp_err_t sdmmc_io_init_read_card_cap(sdmmc_card_t* card, uint8_t *card_cap)
{
esp_err_t err = ESP_OK;
err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_CARD_CAP,
SD_ARG_CMD52_READ, card_cap);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_rw_direct (read SD_IO_CCCR_CARD_CAP) returned 0x%0x", __func__, err);
return err;
}
return ESP_OK;
}
esp_err_t sdmmc_io_init_check_card_cap(sdmmc_card_t* card, uint8_t *card_cap)
{
esp_err_t err = ESP_OK;
/*
* Integrity check required if card is switched to HS mode
* For frequency less than SDMMC_FREQ_HIGHSPEED, see sdmmc_io_enable_hs_mode()
*/
if (card->max_freq_khz < SDMMC_FREQ_HIGHSPEED) {
return ESP_OK;
}
/* If frequency switch has been performed, read card capabilities from CCCR to confirm
* that data can be read correctly at the new frequency.
*/
uint8_t temp_card_cap = 0;
err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_CARD_CAP,
SD_ARG_CMD52_READ, &temp_card_cap);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_rw_direct (read SD_IO_CCCR_CARD_CAP) returned 0x%0x", __func__, err);
return err;
}
if (*card_cap != temp_card_cap) {
ESP_LOGE(TAG, "%s: got corrupted data after increasing clock frequency", __func__);
return ESP_ERR_INVALID_RESPONSE;
}
return ESP_OK;
}
esp_err_t sdmmc_init_io_bus_width(sdmmc_card_t* card)
{
esp_err_t err;