diff --git a/components/driver/spi/gpspi/spi_common.c b/components/driver/spi/gpspi/spi_common.c index 72a2ab3a77..55d195434a 100644 --- a/components/driver/spi/gpspi/spi_common.c +++ b/components/driver/spi/gpspi/spi_common.c @@ -29,7 +29,7 @@ #include "hal/cache_ll.h" #endif -#if SOC_PERIPH_CLK_CTRL_SHARED +#if !SOC_RCC_IS_INDEPENDENT #define SPI_COMMON_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() #else #define SPI_COMMON_RCC_CLOCK_ATOMIC() @@ -107,15 +107,10 @@ bool spicommon_periph_claim(spi_host_device_t host, const char* source) bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true); if (ret) { spi_claiming_func[host] = source; -#if CONFIG_IDF_TARGET_ESP32P4 //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159 SPI_COMMON_RCC_CLOCK_ATOMIC() { spi_ll_enable_bus_clock(host, true); spi_ll_reset_register(host); - spi_ll_enable_clock(host, true); } -#else - periph_module_enable(spi_periph_signal[host].module); -#endif } else { ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]); } @@ -133,13 +128,9 @@ bool spicommon_periph_free(spi_host_device_t host) bool true_var = true; bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false); if (ret) { -#if CONFIG_IDF_TARGET_ESP32P4 SPI_COMMON_RCC_CLOCK_ATOMIC() { spi_ll_enable_bus_clock(host, false); } -#else - periph_module_disable(spi_periph_signal[host].module); -#endif } return ret; } @@ -156,10 +147,11 @@ int spicommon_irqdma_source_for_host(spi_host_device_t host) //----------------------------------------------------------alloc dma periph-------------------------------------------------------// #if !SOC_GDMA_SUPPORTED + +#if SPI_LL_DMA_SHARED static inline periph_module_t get_dma_periph(int dma_chan) { assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM); -#if CONFIG_IDF_TARGET_ESP32S2 if (dma_chan == 1) { return PERIPH_SPI2_DMA_MODULE; } else if (dma_chan == 2) { @@ -167,10 +159,8 @@ static inline periph_module_t get_dma_periph(int dma_chan) } else { abort(); } -#elif CONFIG_IDF_TARGET_ESP32 - return PERIPH_SPI_DMA_MODULE; -#endif } +#endif static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan) { @@ -180,7 +170,21 @@ static bool claim_dma_chan(int dma_chan, uint32_t *out_actual_dma_chan) bool is_used = (BIT(dma_chan) & spi_dma_chan_enabled); if (!is_used) { spi_dma_chan_enabled |= BIT(dma_chan); - periph_module_enable(get_dma_periph(dma_chan)); +#if SPI_LL_DMA_SHARED + PERIPH_RCC_ACQUIRE_ATOMIC(get_dma_periph(dma_chan), ref_count) { + //esp32s2: dma_chan index is same as spi host_id, no matter dma_chan_auto or not + if (ref_count == 0) { + spi_dma_ll_enable_bus_clock(dma_chan, true); + spi_dma_ll_reset_register(dma_chan); + } + } +#else + SPI_COMMON_RCC_CLOCK_ATOMIC() { + //esp32: have only one spi_dma + spi_dma_ll_enable_bus_clock(dma_chan, true); + spi_dma_ll_reset_register(dma_chan); + } +#endif *out_actual_dma_chan = dma_chan; ret = true; } @@ -355,7 +359,17 @@ static esp_err_t dma_chan_free(spi_host_device_t host_id) portENTER_CRITICAL(&spi_dma_spinlock); spi_dma_chan_enabled &= ~BIT(dma_chan); - periph_module_disable(get_dma_periph(dma_chan)); +#if SPI_LL_DMA_SHARED + PERIPH_RCC_RELEASE_ATOMIC(get_dma_periph(dma_chan), ref_count) { + if (ref_count == 0) { + spi_dma_ll_enable_bus_clock(host_id, false); + } + } +#else + SPI_COMMON_RCC_CLOCK_ATOMIC() { + spi_dma_ll_enable_bus_clock(host_id, false); + } +#endif portEXIT_CRITICAL(&spi_dma_spinlock); #else //SOC_GDMA_SUPPORTED diff --git a/components/driver/spi/gpspi/spi_master.c b/components/driver/spi/gpspi/spi_master.c index 0a47c4bddc..dda0ed77c9 100644 --- a/components/driver/spi/gpspi/spi_master.c +++ b/components/driver/spi/gpspi/spi_master.c @@ -177,9 +177,9 @@ static const char *SPI_TAG = "spi_master"; #define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE_ISR(a, ret_val, SPI_TAG, str) #if SOC_PERIPH_CLK_CTRL_SHARED -#define SPI_MASTER_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() +#define SPI_MASTER_PERI_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() #else -#define SPI_MASTER_RCC_CLOCK_ATOMIC() +#define SPI_MASTER_PERI_CLOCK_ATOMIC() #endif static void spi_intr(void *arg); @@ -270,6 +270,9 @@ static esp_err_t spi_master_init_driver(spi_host_device_t host_id) .rx_dma_chan = bus_attr->rx_dma_chan, .dmadesc_n = bus_attr->dma_desc_num, }; + SPI_MASTER_PERI_CLOCK_ATOMIC() { + spi_ll_enable_clock(host_id, true); + } spi_hal_init(&host->hal, host_id, &hal_config); if (host_id != SPI1_HOST) { @@ -556,7 +559,7 @@ static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev) if (spi_bus_lock_touch(dev_lock)) { /* Configuration has not been applied yet. */ spi_hal_setup_device(hal, hal_dev); - SPI_MASTER_RCC_CLOCK_ATOMIC() { + SPI_MASTER_PERI_CLOCK_ATOMIC() { spi_ll_set_clk_source(hal->hw, hal_dev->timing_conf.clock_source); } } diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c index 2953b6de7c..b0f7f4eacb 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_intr_alloc.c @@ -177,21 +177,21 @@ void IRAM_ATTR int_handler2(void *arg) } } +#if !SOC_RCC_IS_INDEPENDENT +#define TEST_BUS_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define TEST_BUS_RCC_CLOCK_ATOMIC() +#endif TEST_CASE("allocate 2 handlers for a same source and remove the later one", "[intr_alloc]") { intr_alloc_test_ctx_t ctx = {false, false, false, false }; intr_handle_t handle1, handle2; // enable SPI2 -#if CONFIG_IDF_TARGET_ESP32P4 //deprecate clk_gate_ll start from p4, others in TODO: IDF-8159 - PERIPH_RCC_ATOMIC() { + TEST_BUS_RCC_CLOCK_ATOMIC() { spi_ll_enable_bus_clock(1, true); spi_ll_reset_register(1); - spi_ll_enable_clock(1, true); } -#else - periph_module_enable(spi_periph_signal[1].module); -#endif esp_err_t r; r = esp_intr_alloc(spi_periph_signal[1].irq, ESP_INTR_FLAG_SHARED, int_handler1, &ctx, &handle1); diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index 42a64fa0cc..c82725e481 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -20,6 +20,7 @@ #include "esp32/rom/lldesc.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/dport_reg.h" #include "hal/misc.h" #include "hal/spi_types.h" #include "hal/assert.h" @@ -56,6 +57,86 @@ typedef spi_dev_t spi_dma_dev_t; /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + if (enable) { + switch (host_id) + { + case SPI1_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); + break; + case SPI2_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN); + break; + case SPI3_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); + break; + default: HAL_ASSERT(false); + } + } else { + switch (host_id) + { + case SPI1_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); + break; + case SPI2_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN); + break; + case SPI3_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); + break; + default: HAL_ASSERT(false); + } + } +} + +/// 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 spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); + break; + case SPI2_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST); + break; + case SPI3_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST); + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__) + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + //empty, keep this for compatibility +} /** * Select SPI peripheral clock source (master). @@ -970,6 +1051,39 @@ static inline void spi_ll_enable_int(spi_dev_t *hw) * RX DMA (Peripherals->DMA->RAM) * TX DMA (RAM->DMA->Peripherals) *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_dma_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + (void)host_id; // has only one spi_dma + if (enable) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN); + } else { + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_DMA_CLK_EN); + } +} + +/// 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 spi_dma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_dma_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_dma_ll_reset_register(spi_host_device_t host_id) { + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_DMA_RST); +} + +/// 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 spi_dma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_dma_ll_reset_register(__VA_ARGS__) + /** * Reset RX DMA which stores the data received from a peripheral into RAM. * diff --git a/components/hal/esp32c2/include/hal/spi_ll.h b/components/hal/esp32c2/include/hal/spi_ll.h index 7bad336400..ef3c941a68 100644 --- a/components/hal/esp32c2/include/hal/spi_ll.h +++ b/components/hal/esp32c2/include/hal/spi_ll.h @@ -20,6 +20,7 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/system_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -36,7 +37,7 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words @@ -90,6 +91,65 @@ typedef enum { /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + switch (host_id) + { + case SPI1_HOST: + SYSTEM.perip_clk_en0.spi01_clk_en = enable; + break; + case SPI2_HOST: + SYSTEM.perip_clk_en0.spi2_clk_en = enable; + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + SYSTEM.perip_rst_en0.spi01_rst = 1; + SYSTEM.perip_rst_en0.spi01_rst = 0; + break; + case SPI2_HOST: + SYSTEM.perip_rst_en0.spi2_rst = 1; + SYSTEM.perip_rst_en0.spi2_rst = 0; + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__) + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + spi_dev_t *hw = SPI_LL_GET_HW(host_id); + HAL_ASSERT(hw != NULL); + hw->clk_gate.clk_en = enable; +} /** * Select SPI peripheral clock source (master). @@ -129,7 +189,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - hw->clk_gate.clk_en = 1; hw->clk_gate.mst_clk_active = 1; hw->clk_gate.mst_clk_sel = 1; diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index 7f202ddc52..41c36294d0 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -20,6 +20,7 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/system_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -36,7 +37,7 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words @@ -92,6 +93,65 @@ typedef enum { /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + switch (host_id) + { + case SPI1_HOST: + SYSTEM.perip_clk_en0.reg_spi01_clk_en = enable; + break; + case SPI2_HOST: + SYSTEM.perip_clk_en0.reg_spi2_clk_en = enable; + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + SYSTEM.perip_rst_en0.reg_spi01_rst = 1; + SYSTEM.perip_rst_en0.reg_spi01_rst = 0; + break; + case SPI2_HOST: + SYSTEM.perip_rst_en0.reg_spi2_rst = 1; + SYSTEM.perip_rst_en0.reg_spi2_rst = 0; + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__) + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + spi_dev_t *hw = SPI_LL_GET_HW(host_id); + HAL_ASSERT(hw != NULL); + hw->clk_gate.clk_en = enable; +} /** * Select SPI peripheral clock source (master). @@ -131,7 +191,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - hw->clk_gate.clk_en = 1; hw->clk_gate.mst_clk_active = 1; hw->clk_gate.mst_clk_sel = 1; diff --git a/components/hal/esp32c6/include/hal/spi_ll.h b/components/hal/esp32c6/include/hal/spi_ll.h index effcdd505e..b253d7e45d 100644 --- a/components/hal/esp32c6/include/hal/spi_ll.h +++ b/components/hal/esp32c6/include/hal/spi_ll.h @@ -37,7 +37,7 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words @@ -91,6 +91,56 @@ typedef enum { /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + switch (host_id) + { + case SPI1_HOST: + PCR.mspi_conf.mspi_clk_en = enable; + break; + case SPI2_HOST: + PCR.spi2_conf.spi2_clk_en = enable; + break; + default: HAL_ASSERT(false); + } +} + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + PCR.mspi_conf.mspi_rst_en = 1; + PCR.mspi_conf.mspi_rst_en = 0; + break; + case SPI2_HOST: + PCR.spi2_conf.spi2_rst_en = 1; + PCR.spi2_conf.spi2_rst_en = 0; + break; + default: HAL_ASSERT(false); + } +} + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + (void) host_id; + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} /** * Select SPI peripheral clock source (master). @@ -134,7 +184,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - PCR.spi2_clkm_conf.spi2_clkm_en = 1; PCR.spi2_clkm_conf.spi2_clkm_sel = 1; hw->dma_conf.val = 0; diff --git a/components/hal/esp32h2/include/hal/spi_ll.h b/components/hal/esp32h2/include/hal/spi_ll.h index d18bb36638..baffa95787 100644 --- a/components/hal/esp32h2/include/hal/spi_ll.h +++ b/components/hal/esp32h2/include/hal/spi_ll.h @@ -37,9 +37,7 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -/// This is the expected clock frequency -#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):&GPSPI2) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : NULL) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words @@ -92,7 +90,56 @@ typedef enum { /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + switch (host_id) + { + case SPI1_HOST: + PCR.mspi_conf.mspi_clk_en = enable; + break; + case SPI2_HOST: + PCR.spi2_conf.spi2_clk_en = enable; + break; + default: HAL_ASSERT(false); + } +} +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + PCR.mspi_conf.mspi_rst_en = 1; + PCR.mspi_conf.mspi_rst_en = 0; + break; + case SPI2_HOST: + PCR.spi2_conf.spi2_rst_en = 1; + PCR.spi2_conf.spi2_rst_en = 0; + break; + default: HAL_ASSERT(false); + } +} + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + (void) host_id; + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} /** * Select SPI peripheral clock source (master). @@ -136,7 +183,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - PCR.spi2_clkm_conf.spi2_clkm_en = 1; PCR.spi2_clkm_conf.spi2_clkm_sel = 0; hw->dma_conf.val = 0; diff --git a/components/hal/esp32p4/include/hal/spi_ll.h b/components/hal/esp32p4/include/hal/spi_ll.h index 923c4ec00b..9df298fd5f 100644 --- a/components/hal/esp32p4/include/hal/spi_ll.h +++ b/components/hal/esp32p4/include/hal/spi_ll.h @@ -36,7 +36,7 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL)) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 8c525a05d1..032a907e15 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -20,6 +20,7 @@ #include "esp_attr.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/dport_reg.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -39,11 +40,12 @@ extern "C" { #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL)) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 23) //reg len: 23 bits #define SPI_LL_CPU_MAX_BIT_LEN (18 * 32) //Fifo len: 18 words #define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized +#define SPI_LL_DMA_SHARED 1 //spi_dma shared with adc and dac on S2 /** * The data structure holding calculated clock configuration. Since the @@ -100,6 +102,86 @@ typedef enum { /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + if (enable) { + switch (host_id) + { + case SPI1_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); + break; + case SPI2_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN); + break; + case SPI3_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); + break; + default: HAL_ASSERT(false); + } + } else { + switch (host_id) + { + case SPI1_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI01_CLK_EN); + break; + case SPI2_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN); + break; + case SPI3_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); + break; + default: HAL_ASSERT(false); + } + } +} + +/// 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 spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI01_RST); + break; + case SPI2_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST); + break; + case SPI3_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST); + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__) + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + //empty, keep this for compatibility +} /** * Select SPI peripheral clock source (master). @@ -1114,6 +1196,69 @@ static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) * RX DMA (Peripherals->DMA->RAM) * TX DMA (RAM->DMA->Peripherals) *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_dma_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + if (enable) { + switch (host_id) + { + case SPI2_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_DMA_CLK_EN); + break; + case SPI3_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN); + break; + default: + HAL_ASSERT(false); + } + } else { + switch (host_id) + { + case SPI2_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_DMA_CLK_EN); + break; + case SPI3_HOST: + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_DMA_CLK_EN); + break; + default: + HAL_ASSERT(false); + } + } +} + +/// 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_RC_ATOMIC_ENV variable in advance +#define spi_dma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; spi_dma_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_dma_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI2_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_DMA_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_DMA_RST); + break; + case SPI3_HOST: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_DMA_RST); + break; + default: + HAL_ASSERT(false); + } +} + +/// 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_RC_ATOMIC_ENV variable in advance +#define spi_dma_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; spi_dma_ll_reset_register(__VA_ARGS__) + //---------------------------------------------------RX-------------------------------------------------// /** * Reset RX DMA which stores the data received from a peripheral into RAM. diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index 590198029c..2670ed0d68 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -20,6 +20,7 @@ #include "esp_types.h" #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/system_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" @@ -38,7 +39,7 @@ extern "C" { /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) -#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3)) +#define SPI_LL_GET_HW(ID) (((ID)==1) ? &GPSPI2 : (((ID)==2) ? &GPSPI3 : NULL)) #define SPI_LL_DMA_MAX_BIT_LEN (1 << 18) //reg len: 18 bits #define SPI_LL_CPU_MAX_BIT_LEN (16 * 32) //Fifo len: 16 words @@ -92,6 +93,72 @@ typedef enum { /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ +/** + * Enable peripheral register clock + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_bus_clock(spi_host_device_t host_id, bool enable) { + switch (host_id) + { + case SPI1_HOST: + SYSTEM.perip_clk_en0.spi01_clk_en = enable; + break; + case SPI2_HOST: + SYSTEM.perip_clk_en0.spi2_clk_en = enable; + break; + case SPI3_HOST: + SYSTEM.perip_clk_en0.spi3_clk_en = enable; + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_enable_bus_clock(__VA_ARGS__) + +/** + * Reset whole peripheral register to init value defined by HW design + * + * @param host_id Peripheral index number, see `spi_host_device_t` + */ +static inline void spi_ll_reset_register(spi_host_device_t host_id) { + switch (host_id) + { + case SPI1_HOST: + SYSTEM.perip_rst_en0.spi01_rst = 1; + SYSTEM.perip_rst_en0.spi01_rst = 0; + break; + case SPI2_HOST: + SYSTEM.perip_rst_en0.spi2_rst = 1; + SYSTEM.perip_rst_en0.spi2_rst = 0; + break; + case SPI3_HOST: + SYSTEM.perip_rst_en0.spi3_rst = 1; + SYSTEM.perip_rst_en0.spi3_rst = 0; + break; + default: HAL_ASSERT(false); + } +} + +/// 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 spi_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; spi_ll_reset_register(__VA_ARGS__) + +/** + * Enable functional output clock within peripheral + * + * @param host_id Peripheral index number, see `spi_host_device_t` + * @param enable Enable/Disable + */ +static inline void spi_ll_enable_clock(spi_host_device_t host_id, bool enable) +{ + spi_dev_t *hw = SPI_LL_GET_HW(host_id); + HAL_ASSERT(hw != NULL); + hw->clk_gate.clk_en = enable; +} /** * Select SPI peripheral clock source (master). @@ -131,7 +198,6 @@ static inline void spi_ll_master_init(spi_dev_t *hw) hw->slave.val = 0; hw->user.val = 0; - hw->clk_gate.clk_en = 1; hw->clk_gate.mst_clk_active = 1; hw->clk_gate.mst_clk_sel = 1;