mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 08:31:44 +01:00 
			
		
		
		
	sdmmc: I/O phase adjustments
1. Fix incorrect meaning of SDMMC.clock bits, synchronize the names with the TRM. 2. Choose input and output phases to satisfy typical timing requirements. 3. Move use_hold_reg setting into the host driver, since it is related to timing. Closes https://github.com/espressif/esp-idf/issues/8521 Related to https://github.com/espressif/esp-idf/issues/8257
This commit is contained in:
		@@ -116,33 +116,29 @@ esp_err_t sdmmc_host_reset(void)
 | 
			
		||||
static void sdmmc_host_set_clk_div(int div)
 | 
			
		||||
{
 | 
			
		||||
    // Set frequency to 160MHz / div
 | 
			
		||||
    // div = p + 1
 | 
			
		||||
    // duty cycle = (h + 1)/(p + 1) (should be = 1/2)
 | 
			
		||||
    // div = l + 1
 | 
			
		||||
    // duty cycle = (h + 1)/(l + 1) (should be = 1/2)
 | 
			
		||||
    assert (div > 1 && div <= 16);
 | 
			
		||||
    int p = div - 1;
 | 
			
		||||
    int l = div - 1;
 | 
			
		||||
    int h = div / 2 - 1;
 | 
			
		||||
 | 
			
		||||
    SDMMC.clock.div_factor_p = p;
 | 
			
		||||
    SDMMC.clock.div_factor_h = h;
 | 
			
		||||
    SDMMC.clock.div_factor_m = p;
 | 
			
		||||
    SDMMC.clock.div_factor_l = l;
 | 
			
		||||
    SDMMC.clock.div_factor_n = l;
 | 
			
		||||
 | 
			
		||||
    // Make sure 160 MHz source clock is used
 | 
			
		||||
#if SOC_SDMMC_SUPPORT_XTAL_CLOCK
 | 
			
		||||
    SDMMC.clock.clk_sel = 1;
 | 
			
		||||
#endif
 | 
			
		||||
#if SOC_SDMMC_USE_GPIO_MATRIX
 | 
			
		||||
    // 90 degree phase on input and output clocks
 | 
			
		||||
    const int inout_clock_phase = 1;
 | 
			
		||||
#else
 | 
			
		||||
    // 180 degree phase on input and output clocks
 | 
			
		||||
    const int inout_clock_phase = 4;
 | 
			
		||||
#endif
 | 
			
		||||
    // Set phases for in/out clocks
 | 
			
		||||
    SDMMC.clock.phase_dout = inout_clock_phase;
 | 
			
		||||
    SDMMC.clock.phase_din = inout_clock_phase;
 | 
			
		||||
 | 
			
		||||
    SDMMC.clock.phase_core = 0;
 | 
			
		||||
    // Wait for the clock to propagate
 | 
			
		||||
    esp_rom_delay_us(10);
 | 
			
		||||
    /* 90 deg. delay for cclk_out to satisfy large hold time for SDR12 (up to 25MHz) and SDR25 (up to 50MHz) modes.
 | 
			
		||||
     * Whether this delayed clock will be used depends on use_hold_reg bit in CMD structure,
 | 
			
		||||
     * determined when sending out the command.
 | 
			
		||||
     */
 | 
			
		||||
    SDMMC.clock.phase_dout = 1;
 | 
			
		||||
    SDMMC.clock.phase_din = 0;
 | 
			
		||||
    esp_rom_delay_us(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sdmmc_host_input_clk_disable(void)
 | 
			
		||||
@@ -300,7 +296,7 @@ esp_err_t sdmmc_host_get_real_freq(int slot, int* real_freq_khz)
 | 
			
		||||
        return ESP_ERR_INVALID_ARG;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int host_div = SDMMC.clock.div_factor_p + 1;
 | 
			
		||||
    int host_div = SDMMC.clock.div_factor_l + 1;
 | 
			
		||||
    int card_div = slot == 0 ? SDMMC.clkdiv.div0 : SDMMC.clkdiv.div1;
 | 
			
		||||
    *real_freq_khz = sdmmc_host_calc_freq(host_div, card_div);
 | 
			
		||||
 | 
			
		||||
@@ -317,6 +313,9 @@ esp_err_t sdmmc_host_start_command(int slot, sdmmc_hw_cmd_t cmd, uint32_t arg) {
 | 
			
		||||
    if (cmd.data_expected && cmd.rw && (SDMMC.wrtprt.cards & BIT(slot)) != 0) {
 | 
			
		||||
        return ESP_ERR_INVALID_STATE;
 | 
			
		||||
    }
 | 
			
		||||
    /* Outputs should be synchronized to cclk_out */
 | 
			
		||||
    cmd.use_hold_reg = 1;
 | 
			
		||||
 | 
			
		||||
    int64_t t0 = esp_timer_get_time();
 | 
			
		||||
    while (SDMMC.cmd.start_command == 1) {
 | 
			
		||||
        if (esp_timer_get_time() - t0 > SDMMC_HOST_START_CMD_TIMEOUT_US) {
 | 
			
		||||
 
 | 
			
		||||
@@ -305,7 +305,6 @@ static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd)
 | 
			
		||||
    if (cmd->flags & SCF_RSP_CRC) {
 | 
			
		||||
        res.check_response_crc = 1;
 | 
			
		||||
    }
 | 
			
		||||
    res.use_hold_reg = 1;
 | 
			
		||||
    if (cmd->data) {
 | 
			
		||||
        res.data_expected = 1;
 | 
			
		||||
        if ((cmd->flags & SCF_CMD_READ) == 0) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user