Skip to content

Commit c2b8ea0

Browse files
committed
feat(sd): supported UHS-I SDR104 200MHz speed
1 parent 0944a2a commit c2b8ea0

File tree

10 files changed

+246
-64
lines changed

10 files changed

+246
-64
lines changed

components/esp_driver_sdspi/include/driver/sdspi_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef int sdspi_dev_handle_t;
6060
.get_real_freq = &sdspi_host_get_real_freq, \
6161
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
6262
.set_input_delay = NULL, \
63+
.set_input_delayline = NULL, \
6364
.dma_aligned_buffer = NULL, \
6465
.pwr_ctrl_handle = NULL, \
6566
.get_dma_info = NULL, \

components/hal/esp32p4/include/hal/sdmmc_ll.h

Lines changed: 103 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,46 @@ extern "C" {
8787
* SDMMC capabilities
8888
*/
8989
#define SDMMC_LL_SLOT_SUPPORT_GPIO_MATRIX(SLOT_ID) ((SLOT_ID == 0) ? 0 : 1)
90+
#define SDMMC_LL_IOMUX_FUNC 0
91+
#define SDMMC_LL_HOST_CTLR_NUMS 1U
92+
#define SDMMC_LL_DELAY_MAX_NUMS_LS 4
93+
#define SDMMC_LL_DELAY_PHASE_SUPPORTED 1
9094

91-
#define SDMMC_LL_IOMUX_FUNC 0
92-
95+
/**
96+
* SDMMC delay phase
97+
*/
9398
typedef enum {
9499
SDMMC_LL_DELAY_PHASE_0,
95100
SDMMC_LL_DELAY_PHASE_1,
96101
SDMMC_LL_DELAY_PHASE_2,
97102
SDMMC_LL_DELAY_PHASE_3,
103+
SDMMC_LL_DELAY_PHASE_4,
104+
SDMMC_LL_DELAY_PHASE_5,
105+
SDMMC_LL_DELAY_PHASE_6,
106+
SDMMC_LL_DELAY_PHASE_7,
98107
} sdmmc_ll_delay_phase_t;
99108

109+
/**
110+
* SDMMC delayline
111+
*/
112+
typedef enum {
113+
SDMMC_LL_DELAY_LINE_0,
114+
SDMMC_LL_DELAY_LINE_1,
115+
SDMMC_LL_DELAY_LINE_2,
116+
SDMMC_LL_DELAY_LINE_3,
117+
SDMMC_LL_DELAY_LINE_4,
118+
SDMMC_LL_DELAY_LINE_5,
119+
SDMMC_LL_DELAY_LINE_6,
120+
SDMMC_LL_DELAY_LINE_7,
121+
} sdmmc_ll_delay_line_t;
122+
123+
/**
124+
* SDMMC speed mode
125+
*/
126+
typedef enum {
127+
SDMMC_LL_SPEED_MODE_LS,
128+
SDMMC_LL_SPEED_MODE_HS,
129+
} sdmmc_ll_speed_mode_t;
100130

101131
/*---------------------------------------------------------------
102132
Clock & Reset
@@ -274,32 +304,85 @@ static inline void sdmmc_ll_init_phase_delay(sdmmc_dev_t *hw)
274304
#define sdmmc_ll_init_phase_delay(...) (void)__DECLARE_RCC_ATOMIC_ENV; sdmmc_ll_init_phase_delay(__VA_ARGS__)
275305

276306
/**
277-
* @brief Set SDMMC din delay
307+
* @brief Set SDMMC din delay phase
278308
*
279309
* @param hw hardware instance address
280310
* @param phase delay phase
281-
*/
282-
static inline void sdmmc_ll_set_din_delay(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_t phase)
283-
{
284-
switch (phase) {
285-
case SDMMC_LL_DELAY_PHASE_1:
286-
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x1;
287-
break;
288-
case SDMMC_LL_DELAY_PHASE_2:
289-
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x2;
290-
break;
291-
case SDMMC_LL_DELAY_PHASE_3:
292-
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x3;
293-
break;
294-
default:
295-
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x0;
296-
break;
311+
* @param mode speed mode
312+
*/
313+
static inline void sdmmc_ll_set_din_delay_phase(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_t phase, sdmmc_ll_speed_mode_t mode)
314+
{
315+
if (mode == SDMMC_LL_SPEED_MODE_LS) {
316+
switch (phase) {
317+
case SDMMC_LL_DELAY_PHASE_1:
318+
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x1;
319+
break;
320+
case SDMMC_LL_DELAY_PHASE_2:
321+
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x2;
322+
break;
323+
case SDMMC_LL_DELAY_PHASE_3:
324+
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x3;
325+
break;
326+
default:
327+
HP_SYS_CLKRST.peri_clk_ctrl02.reg_sdio_ls_sam_clk_edge_sel = 0x0;
328+
break;
329+
}
330+
} else {
331+
SDMMC.dll_clk_conf.dll_cclk_in_sam_phase = (phase << 3);
297332
}
298333
}
299334

300335
/// use a macro to wrap the function, force the caller to use it in a critical section
301336
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
302-
#define sdmmc_ll_set_din_delay(...) (void)__DECLARE_RCC_ATOMIC_ENV; sdmmc_ll_set_din_delay(__VA_ARGS__)
337+
#define sdmmc_ll_set_din_delay_phase(...) (void)__DECLARE_RCC_ATOMIC_ENV; sdmmc_ll_set_din_delay_phase(__VA_ARGS__)
338+
339+
/**
340+
* @brief Set SDMMC dout delay phase
341+
*
342+
* @param hw hardware instance address
343+
* @param phase delay phase
344+
* @param mode speed mode
345+
*/
346+
static inline void sdmmc_ll_set_dout_delay_phase(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_t phase, sdmmc_ll_speed_mode_t mode)
347+
{
348+
if (mode == SDMMC_LL_SPEED_MODE_HS) {
349+
SDMMC.dll_clk_conf.dll_cclk_in_drv_phase = (phase << 3);
350+
}
351+
}
352+
353+
/**
354+
* @brief Set SDMMC din delay line
355+
*
356+
* @param hw hardware instance address
357+
* @param phase delay line
358+
* @param mode speed mode
359+
*/
360+
static inline void sdmmc_ll_set_din_delay_line(sdmmc_dev_t *hw, sdmmc_ll_delay_line_t phase, sdmmc_ll_speed_mode_t mode)
361+
{
362+
SDMMC.dll_clk_conf.dll_cclk_in_sam_phase &= ~0x7;
363+
if (mode == SDMMC_LL_SPEED_MODE_HS) {
364+
SDMMC.dll_clk_conf.dll_cclk_in_sam_phase |= phase;
365+
} else {
366+
HAL_ASSERT(false);
367+
}
368+
}
369+
370+
/**
371+
* @brief Set SDMMC dout delay line
372+
*
373+
* @param hw hardware instance address
374+
* @param phase delay line
375+
* @param mode speed mode
376+
*/
377+
static inline void sdmmc_ll_set_dout_delay_line(sdmmc_dev_t *hw, sdmmc_ll_delay_line_t phase, sdmmc_ll_speed_mode_t mode)
378+
{
379+
SDMMC.dll_clk_conf.dll_cclk_in_drv_phase &= ~0x7;
380+
if (mode == SDMMC_LL_SPEED_MODE_HS) {
381+
SDMMC.dll_clk_conf.dll_cclk_in_drv_phase |= phase;
382+
} else {
383+
HAL_ASSERT(false);
384+
}
385+
}
303386

304387
/**
305388
* @brief Enable card clock

components/hal/esp32s3/include/hal/sdmmc_ll.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,28 @@ extern "C" {
8484
* SDMMC capabilities
8585
*/
8686
#define SDMMC_LL_SLOT_SUPPORT_GPIO_MATRIX(SLOT_ID) 1
87+
#define SDMMC_LL_IOMUX_FUNC -1
88+
#define SDMMC_LL_HOST_CTLR_NUMS 1U
89+
#define SDMMC_LL_DELAY_MAX_NUMS_LS 4
90+
#define SDMMC_LL_DELAY_PHASE_SUPPORTED 1
8791

88-
#define SDMMC_LL_IOMUX_FUNC -1
89-
92+
/**
93+
* SDMMC delay phase
94+
*/
9095
typedef enum {
9196
SDMMC_LL_DELAY_PHASE_0,
9297
SDMMC_LL_DELAY_PHASE_1,
9398
SDMMC_LL_DELAY_PHASE_2,
9499
SDMMC_LL_DELAY_PHASE_3,
95100
} sdmmc_ll_delay_phase_t;
96101

102+
/**
103+
* SDMMC speed mode
104+
*/
105+
typedef enum {
106+
SDMMC_LL_SPEED_MODE_LS,
107+
SDMMC_LL_SPEED_MODE_HS,
108+
} sdmmc_ll_speed_mode_t;
97109

98110
/*---------------------------------------------------------------
99111
Clock & Reset
@@ -220,13 +232,15 @@ static inline void sdmmc_ll_init_phase_delay(sdmmc_dev_t *hw)
220232
}
221233

222234
/**
223-
* @brief Set SDMMC din delay
235+
* @brief Set SDMMC din delay phase
224236
*
225237
* @param hw hardware instance address
226238
* @param phase delay phase
239+
* @param mode speed mode
227240
*/
228-
static inline void sdmmc_ll_set_din_delay(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_t phase)
241+
static inline void sdmmc_ll_set_din_delay_phase(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_t phase, sdmmc_ll_speed_mode_t mode)
229242
{
243+
(void)mode;
230244
switch (phase) {
231245
case SDMMC_LL_DELAY_PHASE_1:
232246
hw->clock.phase_din = 0x1;
@@ -243,6 +257,18 @@ static inline void sdmmc_ll_set_din_delay(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_
243257
}
244258
}
245259

260+
/**
261+
* @brief Set SDMMC dout delay phase
262+
*
263+
* @param hw hardware instance address
264+
* @param phase delay phase
265+
* @param mode speed mode
266+
*/
267+
static inline void sdmmc_ll_set_dout_delay_phase(sdmmc_dev_t *hw, sdmmc_ll_delay_phase_t phase, sdmmc_ll_speed_mode_t mode)
268+
{
269+
//for compatibility
270+
}
271+
246272
/**
247273
* @brief Enable card clock
248274
*

components/hal/include/hal/sd_types.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,45 @@ typedef enum {
3636
SD_SAMPLING_MODE_SDR, ///< Single data rate mode
3737
SD_SAMPLING_MODE_DDR, ///< Double data rate mode
3838
} sd_sampling_mode_t;
39+
40+
/**
41+
* @brief SD/MMC Host clock timing delay phases
42+
*
43+
* This will only take effect when the host works in
44+
* - SDMMC_FREQ_HIGHSPEED
45+
* - SDMMC_FREQ_52M
46+
* - SDR50
47+
* - DDR50
48+
* - SDR104
49+
* Driver will print out how long the delay is, in picosecond (ps).
50+
*/
51+
typedef enum {
52+
SDMMC_DELAY_PHASE_0, /*!< Delay phase 0 */
53+
SDMMC_DELAY_PHASE_1, /*!< Delay phase 1 */
54+
SDMMC_DELAY_PHASE_2, /*!< Delay phase 2 */
55+
SDMMC_DELAY_PHASE_3, /*!< Delay phase 3 */
56+
SDMMC_DELAY_PHASE_4, /*!< Delay phase 4 */
57+
SDMMC_DELAY_PHASE_5, /*!< Delay phase 5 */
58+
SDMMC_DELAY_PHASE_6, /*!< Delay phase 6 */
59+
SDMMC_DELAY_PHASE_7, /*!< Delay phase 7 */
60+
SDMMC_DELAY_PHASE_AUTO, /*!< Auto detect phase, only valid for UHS-I modes */
61+
} sdmmc_delay_phase_t;
62+
63+
/**
64+
* @brief SD/MMC Host clock timing delay lines
65+
*/
66+
typedef enum {
67+
SDMMC_DELAY_LINE_0, /*!< Delay line 0 */
68+
SDMMC_DELAY_LINE_1, /*!< Delay line 1 */
69+
SDMMC_DELAY_LINE_2, /*!< Delay line 2 */
70+
SDMMC_DELAY_LINE_3, /*!< Delay line 3 */
71+
SDMMC_DELAY_LINE_4, /*!< Delay line 4 */
72+
SDMMC_DELAY_LINE_5, /*!< Delay line 5 */
73+
SDMMC_DELAY_LINE_6, /*!< Delay line 6 */
74+
SDMMC_DELAY_LINE_7, /*!< Delay line 7 */
75+
SDMMC_DELAY_LINE_AUTO, /*!< Auto detect line */
76+
} sdmmc_delay_line_t;
77+
3978
#if SOC_SDMMC_DATA_WIDTH_MAX
4079
#define SDMMC_DATA_SIG_NUM SOC_SDMMC_DATA_WIDTH_MAX ///< Number of data signals
4180
#else

components/sdmmc/include/esp_private/sdmmc_common.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ extern "C" {
6262
#define SDMMC_MMC_TRIM_ARG 1
6363
#define SDMMC_MMC_DISCARD_ARG 3
6464

65-
#define SDMMC_FREQ_SDR104 208000 /*!< MMC 208MHz speed */
65+
/**
66+
* Delay mode
67+
*/
68+
typedef enum {
69+
SDMMC_DELAY_MODE_PHASE,
70+
SDMMC_DELAY_MODE_LINE,
71+
} sdmmc_delay_mode_t;
6672

6773
/* Functions to send individual commands */
6874
esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
@@ -97,7 +103,7 @@ esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
97103
uint32_t sdmmc_get_erase_timeout_ms(const sdmmc_card_t* card, int arg, size_t erase_size_kb);
98104
esp_err_t sdmmc_select_driver_strength(sdmmc_card_t *card, sdmmc_driver_strength_t driver_strength);
99105
esp_err_t sdmmc_select_current_limit(sdmmc_card_t *card, sdmmc_current_limit_t current_limit);
100-
esp_err_t sdmmc_do_timing_tuning(sdmmc_card_t *card);
106+
esp_err_t sdmmc_do_timing_tuning(sdmmc_card_t *card, sdmmc_delay_mode_t delay_mode);
101107

102108
/* SD specific */
103109
esp_err_t sdmmc_check_scr(sdmmc_card_t* card);

components/sdmmc/include/sd_protocol_types.h

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* SPDX-License-Identifier: ISC
55
*
6-
* SPDX-FileContributor: 2016-2024 Espressif Systems (Shanghai) CO LTD
6+
* SPDX-FileContributor: 2016-2025 Espressif Systems (Shanghai) CO LTD
77
*/
88
/*
99
* Copyright (c) 2006 Uwe Stuehler <[email protected]>
@@ -154,24 +154,6 @@ typedef struct {
154154
void* volt_switch_cb_arg; /*!< argument to be passed to the CMD11 callback */
155155
} sdmmc_command_t;
156156

157-
/**
158-
* SD/MMC Host clock timing delay phases
159-
*
160-
* This will only take effect when the host works in
161-
* - SDMMC_FREQ_HIGHSPEED
162-
* - SDMMC_FREQ_52M
163-
* - SDR50
164-
* - DDR50
165-
* Driver will print out how long the delay is, in picosecond (ps).
166-
*/
167-
typedef enum {
168-
SDMMC_DELAY_PHASE_0, /*!< Delay phase 0 */
169-
SDMMC_DELAY_PHASE_1, /*!< Delay phase 1 */
170-
SDMMC_DELAY_PHASE_2, /*!< Delay phase 2 */
171-
SDMMC_DELAY_PHASE_3, /*!< Delay phase 3 */
172-
SDMMC_DELAY_PHASE_AUTO, /*!< Auto detect phase, only valid for UHS-I mode */
173-
} sdmmc_delay_phase_t;
174-
175157
/**
176158
* @brief SD/MMC Driver Strength
177159
*/
@@ -220,6 +202,7 @@ typedef struct {
220202
#define SDMMC_FREQ_26M 26000 /*!< MMC 26MHz speed */
221203
#define SDMMC_FREQ_DDR50 50000 /*!< MMC 50MHz speed */
222204
#define SDMMC_FREQ_SDR50 100000 /*!< MMC 100MHz speed */
205+
#define SDMMC_FREQ_SDR104 200000 /*!< MMC 200MHz speed */
223206
float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */
224207
sdmmc_driver_strength_t driver_strength; /*!< Driver Strength */
225208
sdmmc_current_limit_t current_limit; /*!< Current Limit */
@@ -240,6 +223,7 @@ typedef struct {
240223
esp_err_t (*get_real_freq)(int slot, int* real_freq); /*!< Host function to provide real working freq, based on SDMMC controller setup */
241224
sdmmc_delay_phase_t input_delay_phase; /*!< input delay phase, this will only take into effect when the host works in SDMMC_FREQ_HIGHSPEED or SDMMC_FREQ_52M. Driver will print out how long the delay is*/
242225
esp_err_t (*set_input_delay)(int slot, sdmmc_delay_phase_t delay_phase); /*!< set input delay phase */
226+
esp_err_t (*set_input_delayline)(int slot, sdmmc_delay_line_t delay_line); /*!< set input delay line */
243227
void* dma_aligned_buffer; /*!< Leave it NULL. Reserved for cache aligned buffers for SDIO mode */
244228
sd_pwr_ctrl_handle_t pwr_ctrl_handle; /*!< Power control handle */
245229
esp_err_t (*get_dma_info)(int slot, esp_dma_mem_info_t *dma_mem_info); /*!< host function to dma memory information*/

components/sdmmc/sdmmc_common.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,12 @@ esp_err_t sdmmc_init_sd_current_limit(sdmmc_card_t *card)
206206

207207
esp_err_t sdmmc_init_sd_timing_tuning(sdmmc_card_t *card)
208208
{
209-
return sdmmc_do_timing_tuning(card);
209+
ESP_RETURN_ON_ERROR(sdmmc_do_timing_tuning(card, SDMMC_DELAY_MODE_PHASE), TAG, "failed to do phase timing tuning");
210+
if (card->host.max_freq_khz == SDMMC_FREQ_SDR104) {
211+
ESP_RETURN_ON_ERROR(sdmmc_do_timing_tuning(card, SDMMC_DELAY_MODE_LINE), TAG, "failed to do delayline timing tuning");
212+
}
213+
214+
return ESP_OK;
210215
}
211216

212217
esp_err_t sdmmc_init_host_bus_width(sdmmc_card_t* card)

0 commit comments

Comments
 (0)