From 646cb24b71e6187cd3136f22a99bf0d6fccec626 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 Oct 2024 18:44:20 +0200 Subject: [PATCH] change(sdmmc): make sdmmc_host_clock_update_command compatible with CMD11 --- components/esp_driver_sdmmc/src/sdmmc_host.c | 77 +++++++++---------- .../esp_driver_sdmmc/src/sdmmc_private.h | 2 + 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/components/esp_driver_sdmmc/src/sdmmc_host.c b/components/esp_driver_sdmmc/src/sdmmc_host.c index f322f8316f..540e1b964a 100644 --- a/components/esp_driver_sdmmc/src/sdmmc_host.c +++ b/components/esp_driver_sdmmc/src/sdmmc_host.c @@ -176,7 +176,7 @@ static void sdmmc_host_set_clk_div(int div) esp_rom_delay_us(10); } -static esp_err_t sdmmc_host_clock_update_command(int slot) +static esp_err_t sdmmc_host_clock_update_command(int slot, bool is_cmd11) { // Clock update command (not a real command; just updates CIU registers) sdmmc_hw_cmd_t cmd_val = { @@ -184,38 +184,10 @@ static esp_err_t sdmmc_host_clock_update_command(int slot) .update_clk_reg = 1, .wait_complete = 1 }; - bool repeat = true; - while (repeat) { - - ESP_RETURN_ON_ERROR(sdmmc_host_start_command(slot, cmd_val, 0), TAG, "sdmmc_host_start_command returned 0x%x", err_rc_); - - int64_t yield_delay_us = 100 * 1000; // initially 100ms - int64_t t0 = esp_timer_get_time(); - int64_t t1 = 0; - while (true) { - t1 = esp_timer_get_time(); - if (t1 - t0 > SDMMC_HOST_CLOCK_UPDATE_CMD_TIMEOUT_US) { - return ESP_ERR_TIMEOUT; - } - // Sending clock update command to the CIU can generate HLE error. - // According to the manual, this is okay and we must retry the command. - if (sdmmc_ll_get_interrupt_raw(s_host_ctx.hal.dev) & SDMMC_LL_EVENT_HLE) { - sdmmc_ll_clear_interrupt(s_host_ctx.hal.dev, SDMMC_LL_EVENT_HLE); - repeat = true; - break; - } - // When the command is accepted by CIU, start_command bit will be - // cleared in SDMMC.cmd register. - if (sdmmc_ll_is_command_taken(s_host_ctx.hal.dev)) { - repeat = false; - break; - } - if (t1 - t0 > yield_delay_us) { - yield_delay_us *= 2; - vTaskDelay(1); - } - } + if (is_cmd11) { + cmd_val.volt_switch = 1; } + ESP_RETURN_ON_ERROR(sdmmc_host_start_command(slot, cmd_val, 0), TAG, "sdmmc_host_start_command returned 0x%x", err_rc_); return ESP_OK; } @@ -282,7 +254,7 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz) // Disable clock first sdmmc_ll_enable_card_clock(s_host_ctx.hal.dev, slot, false); - esp_err_t err = sdmmc_host_clock_update_command(slot); + esp_err_t err = sdmmc_host_clock_update_command(slot, false); if (err != ESP_OK) { ESP_LOGE(TAG, "disabling clk failed"); ESP_LOGE(TAG, "%s: sdmmc_host_clock_update_command returned 0x%x", __func__, err); @@ -299,7 +271,7 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz) // Program card clock settings, send them to the CIU sdmmc_ll_set_card_clock_div(s_host_ctx.hal.dev, slot, card_div); sdmmc_host_set_clk_div(host_div); - err = sdmmc_host_clock_update_command(slot); + err = sdmmc_host_clock_update_command(slot, false); if (err != ESP_OK) { ESP_LOGE(TAG, "setting clk div failed"); ESP_LOGE(TAG, "%s: sdmmc_host_clock_update_command returned 0x%x", __func__, err); @@ -309,7 +281,7 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz) // Re-enable clocks sdmmc_ll_enable_card_clock(s_host_ctx.hal.dev, slot, true); sdmmc_ll_enable_card_clock_low_power(s_host_ctx.hal.dev, slot, true); - err = sdmmc_host_clock_update_command(slot); + err = sdmmc_host_clock_update_command(slot, false); if (err != ESP_OK) { ESP_LOGE(TAG, "re-enabling clk failed"); ESP_LOGE(TAG, "%s: sdmmc_host_clock_update_command returned 0x%x", __func__, err); @@ -425,7 +397,25 @@ esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) int64_t yield_delay_us = 100 * 1000; // initially 100ms int64_t t0 = esp_timer_get_time(); int64_t t1 = 0; - while (!sdmmc_ll_is_command_taken(s_host_ctx.hal.dev)) { + bool skip_wait = (cmd.volt_switch && cmd.update_clk_reg); + if (!skip_wait) { + while (!(sdmmc_ll_is_command_taken(s_host_ctx.hal.dev))) { + t1 = esp_timer_get_time(); + if (t1 - t0 > SDMMC_HOST_START_CMD_TIMEOUT_US) { + return ESP_ERR_TIMEOUT; + } + if (t1 - t0 > yield_delay_us) { + yield_delay_us *= 2; + vTaskDelay(1); + } + } + } + sdmmc_ll_set_command_arg(s_host_ctx.hal.dev, arg); + cmd.card_num = slot; + cmd.start_command = 1; + sdmmc_ll_set_command(s_host_ctx.hal.dev, cmd); + + while (!(sdmmc_ll_is_command_taken(s_host_ctx.hal.dev))) { t1 = esp_timer_get_time(); if (t1 - t0 > SDMMC_HOST_START_CMD_TIMEOUT_US) { return ESP_ERR_TIMEOUT; @@ -435,10 +425,6 @@ esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) vTaskDelay(1); } } - sdmmc_ll_set_command_arg(s_host_ctx.hal.dev, arg); - cmd.card_num = slot; - cmd.start_command = 1; - sdmmc_ll_set_command(s_host_ctx.hal.dev, cmd); return ESP_OK; } @@ -940,10 +926,19 @@ esp_err_t sdmmc_host_set_cclk_always_on(int slot, bool cclk_always_on) } else { sdmmc_ll_enable_card_clock_low_power(s_host_ctx.hal.dev, slot, true); } - sdmmc_host_clock_update_command(slot); + sdmmc_host_clock_update_command(slot, false); return ESP_OK; } +void sdmmc_host_enable_clk_cmd11(int slot, bool enable) +{ + sdmmc_ll_enable_card_clock(s_host_ctx.hal.dev, slot, enable); + sdmmc_host_clock_update_command(slot, true); + if (enable) { + sdmmc_ll_enable_18v_mode(s_host_ctx.hal.dev, slot, true); + } +} + void sdmmc_host_dma_stop(void) { sdmmc_ll_stop_dma(s_host_ctx.hal.dev); diff --git a/components/esp_driver_sdmmc/src/sdmmc_private.h b/components/esp_driver_sdmmc/src/sdmmc_private.h index 529fa6b823..a68a6bf3fb 100644 --- a/components/esp_driver_sdmmc/src/sdmmc_private.h +++ b/components/esp_driver_sdmmc/src/sdmmc_private.h @@ -36,6 +36,8 @@ void sdmmc_host_dma_resume(void); bool sdmmc_host_card_busy(void); +void sdmmc_host_enable_clk_cmd11(int slot, bool enable); + esp_err_t sdmmc_host_transaction_handler_init(void); void sdmmc_host_transaction_handler_deinit(void);