diff --git a/components/esp_driver_sdio/src/sdio_slave.c b/components/esp_driver_sdio/src/sdio_slave.c index 1689f97f18..ccc56d9ae9 100644 --- a/components/esp_driver_sdio/src/sdio_slave.c +++ b/components/esp_driver_sdio/src/sdio_slave.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -83,6 +83,7 @@ The driver of FIFOs works as below: #include "freertos/FreeRTOS.h" #include "soc/soc_memory_layout.h" #include "soc/gpio_periph.h" +#include "soc/soc_caps.h" #include "esp_cpu.h" #include "freertos/semphr.h" #include "esp_private/periph_ctrl.h" @@ -100,6 +101,12 @@ static const char TAG[] = "sdio_slave"; #define SDIO_SLAVE_LOGE(s, ...) ESP_LOGE(TAG, "%s(%d): "s, __FUNCTION__,__LINE__,##__VA_ARGS__) #define SDIO_SLAVE_LOGW(s, ...) ESP_LOGW(TAG, "%s: "s, __FUNCTION__,##__VA_ARGS__) +#if !SOC_RCC_IS_INDEPENDENT +#define SDIO_SLAVE_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define SDIO_SLAVE_RCC_ATOMIC() +#endif + // sdio_slave_buf_handle_t is of type recv_desc_t*; typedef struct recv_desc_s { union { @@ -304,9 +311,11 @@ static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config) } configure_pin(slot->d3_gpio, slot->func, pullup); - //enable module and config - periph_module_reset(PERIPH_SDIO_SLAVE_MODULE); - periph_module_enable(PERIPH_SDIO_SLAVE_MODULE); + //enable register clock + SDIO_SLAVE_RCC_ATOMIC() { + sdio_slave_ll_enable_bus_clock(true); + sdio_slave_ll_reset_register(); + } sdio_slave_hal_hw_init(context.hal); return ESP_OK; @@ -333,6 +342,11 @@ static void sdio_slave_hw_deinit(void) recover_pin(slot->d1_gpio, slot->func); recover_pin(slot->d2_gpio, slot->func); recover_pin(slot->d3_gpio, slot->func); + + //disable register clock + SDIO_SLAVE_RCC_ATOMIC() { + sdio_slave_ll_enable_bus_clock(false); + } } esp_err_t sdio_slave_initialize(sdio_slave_config_t *config) diff --git a/components/hal/esp32/include/hal/sdio_slave_ll.h b/components/hal/esp32/include/hal/sdio_slave_ll.h index 695c647941..2c94f217e7 100644 --- a/components/hal/esp32/include/hal/sdio_slave_ll.h +++ b/components/hal/esp32/include/hal/sdio_slave_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ #include "soc/host_reg.h" #include "soc/hinf_struct.h" #include "soc/lldesc.h" +#include "soc/dport_reg.h" #ifdef __cplusplus extern "C" { @@ -35,7 +36,6 @@ extern "C" { /// Get address of the only HINF registers for ESP32 #define sdio_slave_ll_get_hinf(ID) (&HINF) - /* * SLC2 DMA Desc struct, aka sdio_slave_ll_desc_t * @@ -75,6 +75,36 @@ typedef enum { SDIO_SLAVE_LL_SLVINT_7 = BIT(7), } sdio_slave_ll_slvint_t; +/** + * @brief Enable the bus clock for the SDIO slave module + * + * @param enable true to enable, false to disable + */ +static inline void _sdio_slave_ll_enable_bus_clock(bool enable) +{ + uint32_t reg_val = DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG); + reg_val &= ~DPORT_WIFI_CLK_SDIOSLAVE_EN; + reg_val |= enable << 4; + DPORT_WRITE_PERI_REG(DPORT_WIFI_CLK_EN_REG, reg_val); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define sdio_slave_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _sdio_slave_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset the SDIO slave module + */ +static inline void _sdio_slave_ll_reset_register(void) +{ + DPORT_WRITE_PERI_REG(DPORT_CORE_RST_EN_REG, DPORT_SDIO_RST); + DPORT_WRITE_PERI_REG(DPORT_CORE_RST_EN_REG, 0); +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define sdio_slave_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _sdio_slave_ll_reset_register(__VA_ARGS__) + /** * Initialize the hardware. * @@ -104,31 +134,31 @@ static inline void sdio_slave_ll_init(slc_dev_t *slc) */ static inline void sdio_slave_ll_set_timing(host_dev_t *host, sdio_slave_timing_t timing) { - switch(timing) { - case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: - host->conf.frc_sdio20 = 0x1f; - host->conf.frc_sdio11 = 0; - host->conf.frc_pos_samp = 0x1f; - host->conf.frc_neg_samp = 0; - break; - case SDIO_SLAVE_TIMING_PSEND_NSAMPLE: - host->conf.frc_sdio20 = 0x1f; - host->conf.frc_sdio11 = 0; - host->conf.frc_pos_samp = 0; - host->conf.frc_neg_samp = 0x1f; - break; - case SDIO_SLAVE_TIMING_NSEND_PSAMPLE: - host->conf.frc_sdio20 = 0; - host->conf.frc_sdio11 = 0x1f; - host->conf.frc_pos_samp = 0x1f; - host->conf.frc_neg_samp = 0; - break; - case SDIO_SLAVE_TIMING_NSEND_NSAMPLE: - host->conf.frc_sdio20 = 0; - host->conf.frc_sdio11 = 0x1f; - host->conf.frc_pos_samp = 0; - host->conf.frc_neg_samp = 0x1f; - break; + switch (timing) { + case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: + host->conf.frc_sdio20 = 0x1f; + host->conf.frc_sdio11 = 0; + host->conf.frc_pos_samp = 0x1f; + host->conf.frc_neg_samp = 0; + break; + case SDIO_SLAVE_TIMING_PSEND_NSAMPLE: + host->conf.frc_sdio20 = 0x1f; + host->conf.frc_sdio11 = 0; + host->conf.frc_pos_samp = 0; + host->conf.frc_neg_samp = 0x1f; + break; + case SDIO_SLAVE_TIMING_NSEND_PSAMPLE: + host->conf.frc_sdio20 = 0; + host->conf.frc_sdio11 = 0x1f; + host->conf.frc_pos_samp = 0x1f; + host->conf.frc_neg_samp = 0; + break; + case SDIO_SLAVE_TIMING_NSEND_NSAMPLE: + host->conf.frc_sdio20 = 0; + host->conf.frc_sdio11 = 0x1f; + host->conf.frc_pos_samp = 0; + host->conf.frc_neg_samp = 0x1f; + break; } } @@ -267,7 +297,7 @@ static inline void sdio_slave_ll_send_stop(slc_dev_t *slc) */ static inline void sdio_slave_ll_send_intr_ena(slc_dev_t *slc, bool ena) { - slc->slc0_int_ena.rx_eof = (ena? 1: 0); + slc->slc0_int_ena.rx_eof = (ena ? 1 : 0); } /** @@ -411,9 +441,9 @@ static inline void sdio_slave_ll_recv_stop(slc_dev_t *slc) * @param pos Position of the register, 0-63 except 24-27. * @return address of the register. */ -static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t* host, int pos) +static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t *host, int pos) { - return (intptr_t )&(host->conf_w0) + pos + (pos>23?4:0) + (pos>31?12:0); + return (intptr_t) & (host->conf_w0) + pos + (pos > 23 ? 4 : 0) + (pos > 31 ? 12 : 0); } /** @@ -425,7 +455,7 @@ static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t* host, int pos) */ static inline uint8_t sdio_slave_ll_host_get_reg(host_dev_t *host, int pos) { - return *(uint8_t*)sdio_slave_ll_host_get_w_reg(host, pos); + return *(uint8_t *)sdio_slave_ll_host_get_w_reg(host, pos); } /** @@ -435,9 +465,9 @@ static inline uint8_t sdio_slave_ll_host_get_reg(host_dev_t *host, int pos) * @param pos Position of the register, 0-63, except 24-27. * @param reg Value to set. */ -static inline void sdio_slave_ll_host_set_reg(host_dev_t* host, int pos, uint8_t reg) +static inline void sdio_slave_ll_host_set_reg(host_dev_t *host, int pos, uint8_t reg) { - uint32_t* addr = (uint32_t*)(sdio_slave_ll_host_get_w_reg(host, pos) & (~3)); + uint32_t *addr = (uint32_t *)(sdio_slave_ll_host_get_w_reg(host, pos) & (~3)); uint32_t shift = (pos % 4) * 8; *addr &= ~(0xff << shift); *addr |= ((uint32_t)reg << shift); @@ -449,7 +479,7 @@ static inline void sdio_slave_ll_host_set_reg(host_dev_t* host, int pos, uint8_t * @param host Address of the host registers * @return Enabled interrupts */ -static inline sdio_slave_hostint_t sdio_slave_ll_host_get_intena(host_dev_t* host) +static inline sdio_slave_hostint_t sdio_slave_ll_host_get_intena(host_dev_t *host) { return (sdio_slave_hostint_t)host->slc0_func1_int_ena.val; } @@ -470,7 +500,7 @@ static inline void sdio_slave_ll_host_set_intena(host_dev_t *host, const sdio_sl * @param host Address of the host registers * @param mask Mask of interrupts to clear. */ -static inline void sdio_slave_ll_host_intr_clear(host_dev_t* host, const sdio_slave_hostint_t *mask) +static inline void sdio_slave_ll_host_intr_clear(host_dev_t *host, const sdio_slave_hostint_t *mask) { host->slc0_int_clr.val = (*mask); } @@ -488,7 +518,7 @@ static inline void sdio_slave_ll_host_send_int(slc_dev_t *slc, const sdio_slave_ } /** - * Enable some of the slave interrups (send from host) + * Enable some of the slave interrupts (send from host) * * @param slc Address of the SLC registers * @param mask Mask of interrupts to enable, all those set to 0 will be disabled. diff --git a/components/hal/esp32c6/include/hal/sdio_slave_ll.h b/components/hal/esp32c6/include/hal/sdio_slave_ll.h index 7319cbe20a..97c4b54410 100644 --- a/components/hal/esp32c6/include/hal/sdio_slave_ll.h +++ b/components/hal/esp32c6/include/hal/sdio_slave_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ #include "soc/host_reg.h" #include "soc/hinf_struct.h" #include "soc/lldesc.h" +#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -35,7 +36,6 @@ extern "C" { /// Get address of the only HINF registers #define sdio_slave_ll_get_hinf(ID) (&HINF) - /* * SLC2 DMA Desc struct, aka sdio_slave_ll_desc_t * @@ -75,6 +75,25 @@ typedef enum { SDIO_SLAVE_LL_SLVINT_7 = BIT(7), } sdio_slave_ll_slvint_t; +/** + * @brief Enable the bus clock for the SDIO slave module + * + * @param enable true to enable, false to disable + */ +static inline void sdio_slave_ll_enable_bus_clock(bool enable) +{ + PCR.sdio_slave_conf.sdio_slave_clk_en = enable; +} + +/** + * @brief Reset the SDIO slave module + */ +static inline void sdio_slave_ll_reset_register(void) +{ + PCR.sdio_slave_conf.sdio_slave_rst_en = 1; + PCR.sdio_slave_conf.sdio_slave_rst_en = 0; +} + /** * Initialize the hardware. * @@ -104,31 +123,31 @@ static inline void sdio_slave_ll_init(slc_dev_t *slc) */ static inline void sdio_slave_ll_set_timing(host_dev_t *host, sdio_slave_timing_t timing) { - switch(timing) { - case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: - host->conf.frc_sdio20 = 0x1f; - host->conf.frc_sdio11 = 0; - host->conf.frc_pos_samp = 0x1f; - host->conf.frc_neg_samp = 0; - break; - case SDIO_SLAVE_TIMING_PSEND_NSAMPLE: - host->conf.frc_sdio20 = 0x1f; - host->conf.frc_sdio11 = 0; - host->conf.frc_pos_samp = 0; - host->conf.frc_neg_samp = 0x1f; - break; - case SDIO_SLAVE_TIMING_NSEND_PSAMPLE: - host->conf.frc_sdio20 = 0; - host->conf.frc_sdio11 = 0x1f; - host->conf.frc_pos_samp = 0x1f; - host->conf.frc_neg_samp = 0; - break; - case SDIO_SLAVE_TIMING_NSEND_NSAMPLE: - host->conf.frc_sdio20 = 0; - host->conf.frc_sdio11 = 0x1f; - host->conf.frc_pos_samp = 0; - host->conf.frc_neg_samp = 0x1f; - break; + switch (timing) { + case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: + host->conf.frc_sdio20 = 0x1f; + host->conf.frc_sdio11 = 0; + host->conf.frc_pos_samp = 0x1f; + host->conf.frc_neg_samp = 0; + break; + case SDIO_SLAVE_TIMING_PSEND_NSAMPLE: + host->conf.frc_sdio20 = 0x1f; + host->conf.frc_sdio11 = 0; + host->conf.frc_pos_samp = 0; + host->conf.frc_neg_samp = 0x1f; + break; + case SDIO_SLAVE_TIMING_NSEND_PSAMPLE: + host->conf.frc_sdio20 = 0; + host->conf.frc_sdio11 = 0x1f; + host->conf.frc_pos_samp = 0x1f; + host->conf.frc_neg_samp = 0; + break; + case SDIO_SLAVE_TIMING_NSEND_NSAMPLE: + host->conf.frc_sdio20 = 0; + host->conf.frc_sdio11 = 0x1f; + host->conf.frc_pos_samp = 0; + host->conf.frc_neg_samp = 0x1f; + break; } } @@ -267,7 +286,7 @@ static inline void sdio_slave_ll_send_stop(slc_dev_t *slc) */ static inline void sdio_slave_ll_send_intr_ena(slc_dev_t *slc, bool ena) { - slc->slc0int_ena.slc0_rx_eof_int_ena = (ena? 1: 0); + slc->slc0int_ena.slc0_rx_eof_int_ena = (ena ? 1 : 0); } /** @@ -411,9 +430,9 @@ static inline void sdio_slave_ll_recv_stop(slc_dev_t *slc) * @param pos Position of the register, 0-63 except 24-27. * @return address of the register. */ -static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t* host, int pos) +static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t *host, int pos) { - return (intptr_t )&(host->conf_w0) + pos + (pos>23?4:0) + (pos>31?12:0); + return (intptr_t) & (host->conf_w0) + pos + (pos > 23 ? 4 : 0) + (pos > 31 ? 12 : 0); } /** @@ -425,7 +444,7 @@ static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t* host, int pos) */ static inline uint8_t sdio_slave_ll_host_get_reg(host_dev_t *host, int pos) { - return *(uint8_t*)sdio_slave_ll_host_get_w_reg(host, pos); + return *(uint8_t *)sdio_slave_ll_host_get_w_reg(host, pos); } /** @@ -435,9 +454,9 @@ static inline uint8_t sdio_slave_ll_host_get_reg(host_dev_t *host, int pos) * @param pos Position of the register, 0-63, except 24-27. * @param reg Value to set. */ -static inline void sdio_slave_ll_host_set_reg(host_dev_t* host, int pos, uint8_t reg) +static inline void sdio_slave_ll_host_set_reg(host_dev_t *host, int pos, uint8_t reg) { - uint32_t* addr = (uint32_t*)(sdio_slave_ll_host_get_w_reg(host, pos) & (~3)); + uint32_t *addr = (uint32_t *)(sdio_slave_ll_host_get_w_reg(host, pos) & (~3)); uint32_t shift = (pos % 4) * 8; *addr &= ~(0xff << shift); *addr |= ((uint32_t)reg << shift); @@ -449,7 +468,7 @@ static inline void sdio_slave_ll_host_set_reg(host_dev_t* host, int pos, uint8_t * @param host Address of the host registers * @return Enabled interrupts */ -static inline sdio_slave_hostint_t sdio_slave_ll_host_get_intena(host_dev_t* host) +static inline sdio_slave_hostint_t sdio_slave_ll_host_get_intena(host_dev_t *host) { return (sdio_slave_hostint_t)host->slc0host_func1_int_ena.val; } @@ -470,7 +489,7 @@ static inline void sdio_slave_ll_host_set_intena(host_dev_t *host, const sdio_sl * @param host Address of the host registers * @param mask Mask of interrupts to clear. */ -static inline void sdio_slave_ll_host_intr_clear(host_dev_t* host, const sdio_slave_hostint_t *mask) +static inline void sdio_slave_ll_host_intr_clear(host_dev_t *host, const sdio_slave_hostint_t *mask) { host->slc0host_int_clr.val = (*mask); } @@ -488,7 +507,7 @@ static inline void sdio_slave_ll_host_send_int(slc_dev_t *slc, const sdio_slave_ } /** - * Enable some of the slave interrups (send from host) + * Enable some of the slave interrupts (send from host) * * @param slc Address of the SLC registers * @param mask Mask of interrupts to enable, all those set to 0 will be disabled.