forked from espressif/esp-idf
feat(sdmmc): add high speed mode switch validation check for SDIO
This commit is contained in:
@@ -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_ocr(sdmmc_card_t* card);
|
||||||
esp_err_t sdmmc_init_spi_crc(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_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_blocklen(sdmmc_card_t* card);
|
||||||
esp_err_t sdmmc_init_sd_scr(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);
|
esp_err_t sdmmc_init_sd_ssr(sdmmc_card_t* card);
|
||||||
|
@@ -32,6 +32,16 @@ static const char* TAG = "sdmmc_init";
|
|||||||
} \
|
} \
|
||||||
} while(0);
|
} 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)
|
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 */
|
/* MMC cards: read CXD */
|
||||||
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_read_ext_csd);
|
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.
|
/* Try to switch card to HS mode if the card supports it.
|
||||||
* Set card->max_freq_khz value accordingly.
|
* 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);
|
SDMMC_INIT_STEP(is_sdmem, sdmmc_check_scr);
|
||||||
/* Sanity check after eMMC switch to HS mode */
|
/* Sanity check after eMMC switch to HS mode */
|
||||||
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_check_ext_csd);
|
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;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@@ -120,6 +120,48 @@ esp_err_t sdmmc_init_io(sdmmc_card_t* card)
|
|||||||
return ESP_OK;
|
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 sdmmc_init_io_bus_width(sdmmc_card_t* card)
|
||||||
{
|
{
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
|
Reference in New Issue
Block a user