diff --git a/components/hal/esp32c2/include/hal/gpspi_flash_ll.h b/components/hal/esp32c2/include/hal/gpspi_flash_ll.h index 0053f81319..7b63e6fb92 100644 --- a/components/hal/esp32c2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c2/include/hal/gpspi_flash_ll.h @@ -425,6 +425,35 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_XTAL: + hw->clk_gate.mst_clk_sel = 0; + break; + default: + hw->clk_gate.mst_clk_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + hw->clk_gate.clk_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c2/include/hal/spi_flash_ll.h b/components/hal/esp32c2/include/hal/spi_flash_ll.h index f97423ab14..ff609abfec 100644 --- a/components/hal/esp32c2/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c2/include/hal/spi_flash_ll.h @@ -24,7 +24,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h index aa8f923d42..28285336fe 100644 --- a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h @@ -426,6 +426,35 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_XTAL: + hw->clk_gate.mst_clk_sel = 0; + break; + default: + hw->clk_gate.mst_clk_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + hw->clk_gate.clk_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/spi_flash_ll.h b/components/hal/esp32c3/include/hal/spi_flash_ll.h index 1610a2ef5f..31374d42dd 100644 --- a/components/hal/esp32c3/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c3/include/hal/spi_flash_ll.h @@ -24,7 +24,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32c5/include/hal/gpspi_flash_ll.h b/components/hal/esp32c5/include/hal/gpspi_flash_ll.h index c2d72ce158..67e588da2a 100644 --- a/components/hal/esp32c5/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c5/include/hal/gpspi_flash_ll.h @@ -15,6 +15,8 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/pcr_struct.h" +#include "hal/assert.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -31,6 +33,8 @@ extern "C" { typedef typeof(GPSPI2.clock.val) gpspi_flash_ll_clock_reg_t; #define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (80) +#define GPSPI_FLASH_LL_SUPPORT_CLK_SRC_PRE_DIV (1) +#define GPSPI_FLASH_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider /*------------------------------------------------------------------------------ * Control @@ -426,6 +430,56 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + uint32_t clk_id = 0; + switch (clk_source) { + case SOC_MOD_CLK_PLL_F160M: + clk_id = 1; + break; + case SOC_MOD_CLK_RC_FAST: + clk_id = 2; + break; + case SOC_MOD_CLK_XTAL: + clk_id = 0; + break; + default: + HAL_ASSERT(false); + } + + PCR.spi2_clkm_conf.spi2_clkm_sel = clk_id; +} + +/** + * Enable/disable SPI flash module clock + * + * @param host_id SPI host ID + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint8_t mst_div) +{ + // In IDF master driver 'mst_div' will be const 2 and 'hs_div' is actually pre_div temporally + (void) hs_div; + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi2_clkm_conf, spi2_clkm_div_num, mst_div - 1); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/spi_flash_ll.h b/components/hal/esp32c5/include/hal/spi_flash_ll.h index 6a3f3570f0..33565497e6 100644 --- a/components/hal/esp32c5/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c5/include/hal/spi_flash_ll.h @@ -26,7 +26,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32c6/include/hal/gpspi_flash_ll.h b/components/hal/esp32c6/include/hal/gpspi_flash_ll.h index c2d72ce158..db096c7f18 100644 --- a/components/hal/esp32c6/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c6/include/hal/gpspi_flash_ll.h @@ -15,6 +15,7 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/pcr_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -426,6 +427,39 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_RC_FAST: + PCR.spi2_clkm_conf.spi2_clkm_sel = 2; + break; + case SPI_CLK_SRC_XTAL: + PCR.spi2_clkm_conf.spi2_clkm_sel = 0; + break; + default: + PCR.spi2_clkm_conf.spi2_clkm_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + (void) hw; + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/spi_flash_ll.h b/components/hal/esp32c6/include/hal/spi_flash_ll.h index 2edd304491..8b5d17c470 100644 --- a/components/hal/esp32c6/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c6/include/hal/spi_flash_ll.h @@ -24,7 +24,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32c61/include/hal/gpspi_flash_ll.h b/components/hal/esp32c61/include/hal/gpspi_flash_ll.h index 40c4c247cc..6a3ce7894d 100644 --- a/components/hal/esp32c61/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c61/include/hal/gpspi_flash_ll.h @@ -15,6 +15,7 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/pcr_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -426,6 +427,39 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_RC_FAST: + PCR.spi2_clkm_conf.spi2_clkm_sel = 2; + break; + case SPI_CLK_SRC_XTAL: + PCR.spi2_clkm_conf.spi2_clkm_sel = 0; + break; + default: + PCR.spi2_clkm_conf.spi2_clkm_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + (void) hw; + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c61/include/hal/spi_flash_ll.h b/components/hal/esp32c61/include/hal/spi_flash_ll.h index 48ea93ca30..9c6a154a4f 100644 --- a/components/hal/esp32c61/include/hal/spi_flash_ll.h +++ b/components/hal/esp32c61/include/hal/spi_flash_ll.h @@ -26,7 +26,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h index c493614c01..8c101b3ee9 100644 --- a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h @@ -15,6 +15,7 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/pcr_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -426,6 +427,39 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_RC_FAST: + PCR.spi2_clkm_conf.spi2_clkm_sel = 2; + break; + case SPI_CLK_SRC_XTAL: + PCR.spi2_clkm_conf.spi2_clkm_sel = 0; + break; + default: + PCR.spi2_clkm_conf.spi2_clkm_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + (void) hw; + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/spi_flash_ll.h b/components/hal/esp32h2/include/hal/spi_flash_ll.h index ed227bc550..b847a477fd 100644 --- a/components/hal/esp32h2/include/hal/spi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spi_flash_ll.h @@ -24,7 +24,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32h21/include/hal/gpspi_flash_ll.h b/components/hal/esp32h21/include/hal/gpspi_flash_ll.h index 81b28fddfe..49424e110d 100644 --- a/components/hal/esp32h21/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h21/include/hal/gpspi_flash_ll.h @@ -15,6 +15,7 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/pcr_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -426,6 +427,38 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_RC_FAST: + PCR.spi2_clkm_conf.spi2_clkm_sel = 2; + break; + case SPI_CLK_SRC_XTAL: + PCR.spi2_clkm_conf.spi2_clkm_sel = 0; + break; + default: + PCR.spi2_clkm_conf.spi2_clkm_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h21/include/hal/spi_flash_ll.h b/components/hal/esp32h21/include/hal/spi_flash_ll.h index 24d7d469da..4b75b5c641 100644 --- a/components/hal/esp32h21/include/hal/spi_flash_ll.h +++ b/components/hal/esp32h21/include/hal/spi_flash_ll.h @@ -21,7 +21,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32h4/include/hal/gpspi_flash_ll.h b/components/hal/esp32h4/include/hal/gpspi_flash_ll.h index 728491716c..82f3597f48 100644 --- a/components/hal/esp32h4/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h4/include/hal/gpspi_flash_ll.h @@ -15,6 +15,7 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/pcr_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -425,6 +426,34 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) abort(); } +__attribute__((always_inline)) +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_RC_FAST: + PCR.spi2_clkm_conf.spi2_clkm_sel = 2; + break; + case SPI_CLK_SRC_XTAL: + PCR.spi2_clkm_conf.spi2_clkm_sel = 0; + break; + default: + PCR.spi2_clkm_conf.spi2_clkm_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + (void) hw; + PCR.spi2_clkm_conf.spi2_clkm_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h4/include/hal/spi_flash_ll.h b/components/hal/esp32h4/include/hal/spi_flash_ll.h index c2446e6548..68ce940eba 100644 --- a/components/hal/esp32h4/include/hal/spi_flash_ll.h +++ b/components/hal/esp32h4/include/hal/spi_flash_ll.h @@ -26,7 +26,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32p4/include/hal/gpspi_flash_ll.h b/components/hal/esp32p4/include/hal/gpspi_flash_ll.h index 13f9b37ea2..4ada4c24ed 100644 --- a/components/hal/esp32p4/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32p4/include/hal/gpspi_flash_ll.h @@ -15,6 +15,8 @@ #include #include "soc/spi_periph.h" #include "soc/spi_struct.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "hal/assert.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX @@ -37,6 +39,8 @@ extern "C" { typedef typeof(GPSPI2.clock.val) gpspi_flash_ll_clock_reg_t; #define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (80) +#define GPSPI_FLASH_LL_SUPPORT_CLK_SRC_PRE_DIV (1) +#define GPSPI_FLASH_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider /*------------------------------------------------------------------------------ * Control @@ -432,6 +436,84 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void _gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + uint32_t clk_id = 0; + switch (clk_source) { + case SPI_CLK_SRC_SPLL: + clk_id = 4; + break; + case SPI_CLK_SRC_RC_FAST: + clk_id = 1; + break; + case SPI_CLK_SRC_XTAL: + clk_id = 0; + break; + default: + HAL_ASSERT(false); + } + + if (hw == &GPSPI2) { + HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_clk_src_sel = clk_id; + } else if (hw == &GPSPI3) { + HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi3_clk_src_sel = clk_id; + } +} + +/// 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 gpspi_flash_ll_set_clk_source(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _gpspi_flash_ll_set_clk_source(__VA_ARGS__); \ + } while(0) + +/** + * Enable/disable SPI flash module clock + * + * @param host_id SPI host ID + * @param enable true to enable, false to disable + */ +static inline void _gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + if (hw == &GPSPI2) { + HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_hs_clk_en = enable; + HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi2_mst_clk_en = enable; + } else if (hw == &GPSPI3) { + HP_SYS_CLKRST.peri_clk_ctrl116.reg_gpspi3_hs_clk_en = enable; + HP_SYS_CLKRST.peri_clk_ctrl117.reg_gpspi3_mst_clk_en = enable; + } +} + +/// 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 gpspi_flash_ll_enable_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _gpspi_flash_ll_enable_clock(__VA_ARGS__); \ + } while(0) + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint8_t mst_div) +{ + if (hw == &GPSPI2) { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl116, reg_gpspi2_hs_clk_div_num, hs_div - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl116, reg_gpspi2_mst_clk_div_num, mst_div - 1); + } else if (hw == &GPSPI3) { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl117, reg_gpspi3_hs_clk_div_num, hs_div - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl117, reg_gpspi3_mst_clk_div_num, mst_div - 1); + } +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/spi_flash_ll.h b/components/hal/esp32p4/include/hal/spi_flash_ll.h index b76e1d91c4..d734a1febf 100644 --- a/components/hal/esp32p4/include/hal/spi_flash_ll.h +++ b/components/hal/esp32p4/include/hal/spi_flash_ll.h @@ -24,7 +24,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h index 4581e82175..b7ccf36148 100644 --- a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -421,6 +421,28 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + //empty, keep this for compatibility +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + //empty, keep this for compatibility +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/spi_flash_ll.h b/components/hal/esp32s2/include/hal/spi_flash_ll.h index 7b566cf547..8a51bff86a 100644 --- a/components/hal/esp32s2/include/hal/spi_flash_ll.h +++ b/components/hal/esp32s2/include/hal/spi_flash_ll.h @@ -25,7 +25,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h index 357a2d2e19..c5a44f124c 100644 --- a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -433,6 +433,35 @@ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) return div_parameter; } +/** + * Set the clock source + * + * @param hw Beginning address of the peripheral registers. + * @param clk_source Clock source to use + */ +static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) +{ + switch (clk_source) { + case SPI_CLK_SRC_XTAL: + hw->clk_gate.mst_clk_sel = 0; + break; + default: + hw->clk_gate.mst_clk_sel = 1; + break; + } +} + +/** + * Enable/disable SPI flash module clock + * + * @param hw Beginning address of the peripheral registers. + * @param enable true to enable, false to disable + */ +static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) +{ + hw->clk_gate.clk_en = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/spi_flash_ll.h b/components/hal/esp32s3/include/hal/spi_flash_ll.h index d9918f574a..b78f5c7778 100644 --- a/components/hal/esp32s3/include/hal/spi_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spi_flash_ll.h @@ -24,7 +24,7 @@ extern "C" { #define spi_flash_ll_calculate_clock_reg(host_id, clock_div) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_calculate_clock_reg(clock_div) \ : gpspi_flash_ll_calculate_clock_reg(clock_div)) -#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) +#define spi_flash_ll_get_source_clock_freq_mhz(host_id) (((host_id)<=SPI1_HOST) ? spimem_flash_ll_get_source_freq_mhz() : -1) #define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \ : gpspi_flash_ll_get_hw(host_id))) diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 8a63a3bbcd..93a55afdbd 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -26,6 +26,9 @@ #include "esp_rom_spiflash.h" #include "bootloader_flash.h" #include "esp_check.h" +#include "esp_private/esp_clk_tree_common.h" +#include "clk_ctrl_os.h" +#include "soc/soc_caps.h" __attribute__((unused)) static const char TAG[] = "spi_flash"; @@ -37,6 +40,12 @@ __attribute__((unused)) static const char TAG[] = "spi_flash"; #error "Flash chip size equal or over 32MB memory cannot use driver in ROM" #endif +#if SOC_PERIPH_CLK_CTRL_SHARED +#define GPSPI_FLASH_RCC_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define GPSPI_FLASH_RCC_CLOCK_ATOMIC() +#endif + /* This pointer is defined in ROM and extern-ed on targets where CONFIG_SPI_FLASH_ROM_IMPL = y*/ #if !CONFIG_SPI_FLASH_ROM_IMPL esp_flash_t *esp_flash_default_chip = NULL; @@ -230,6 +239,120 @@ static esp_err_t acquire_spi_device(const esp_flash_spi_device_config_t *config, return ret; } +#if GPSPI_FLASH_LL_SUPPORT_CLK_SRC_PRE_DIV +static uint32_t s_spi_find_clock_src_pre_div(uint32_t src_freq, uint32_t target_freq) +{ + // pre division must be even and at least 2 + uint32_t min_div = ((src_freq / GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ) + 1) & (~0x01UL); + min_div = min_div < 2 ? 2 : min_div; + + uint32_t total_div = src_freq / target_freq; + // Loop the `div` to find a divisible value of `total_div` + for (uint32_t pre_div = min_div; pre_div <= total_div; pre_div += 2) { + if ((total_div % pre_div) || (total_div / pre_div) > GPSPI_FLASH_LL_PERIPH_CLK_DIV_MAX) { + continue; + } + return pre_div; + } + return min_div; +} +#endif //GPSPI_FLASH_LL_SUPPORT_CLK_SRC_PRE_DIV + +/** + * Configure GPSPI clock source and frequency for flash device + * + * @param config Flash device configuration + * @return Clock source frequency in MHz + */ +static uint32_t init_gpspi_clock(esp_flash_t *chip, const esp_flash_spi_device_config_t *config) +{ +#if !CONFIG_IDF_TARGET_ESP32 + // Get clock source frequency + uint32_t clk_src_freq = 0; + spi_clock_source_t clk_src = config->clock_source ? config->clock_source : SPI_CLK_SRC_DEFAULT; + +#if SOC_SPI_SUPPORT_CLK_RC_FAST + if (config->clock_source == SPI_CLK_SRC_RC_FAST) { + periph_rtc_dig_clk8m_enable(); + } +#endif + + esp_clk_tree_enable_src(clk_src, true); + esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq); + + // Enable GPSPI clock + GPSPI_FLASH_RCC_CLOCK_ATOMIC() { + gpspi_flash_ll_enable_clock(spi_flash_ll_get_hw(config->host_id), true); + gpspi_flash_ll_set_clk_source(spi_flash_ll_get_hw(config->host_id), clk_src); + } + + // Store clock source in chip for later cleanup + chip->clock_source = clk_src; + + // Calculate final clock source frequency + uint32_t final_freq_mhz; +#if GPSPI_FLASH_LL_SUPPORT_CLK_SRC_PRE_DIV + uint32_t pre_div = s_spi_find_clock_src_pre_div(clk_src_freq, GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ * 1000 * 1000); + gpspi_flash_ll_clk_source_pre_div(spi_flash_ll_get_hw(config->host_id), pre_div / 2, 2); + final_freq_mhz = clk_src_freq / (1 * 1000 * 1000) / (pre_div); +#else + final_freq_mhz = clk_src_freq / (1 * 1000 * 1000); +#endif + + return final_freq_mhz; +#else + // Do nothing for ESP32 + return SPI_FLASH_LL_CLOCK_FREQUENCY_MHZ; +#endif // !CONFIG_IDF_TARGET_ESP32 +} + +#if !CONFIG_IDF_TARGET_ESP32 +/** + * Get host_id from esp_flash_t chip pointer + * + * @param chip Flash chip pointer + * @return host_id or -1 if invalid + */ +static int get_host_id_from_chip(esp_flash_t *chip) +{ + if (!chip || !chip->host) { + return -1; + } + + spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)chip->host; + return spi_flash_ll_hw_get_id(ctx->spi); +} +#endif // !CONFIG_IDF_TARGET_ESP32 + +static void deinit_gpspi_clock(esp_flash_t *chip) +{ +#if !CONFIG_IDF_TARGET_ESP32 + if (!chip) { + return; + } + + int host_id = get_host_id_from_chip(chip); + if (host_id < 0) { + return; + } + + // Disable GPSPI clock + GPSPI_FLASH_RCC_CLOCK_ATOMIC() { + gpspi_flash_ll_enable_clock(spi_flash_ll_get_hw(host_id), false); + } + + // Disable the clock source + esp_clk_tree_enable_src(chip->clock_source, false); + +#if SOC_SPI_SUPPORT_CLK_RC_FAST + // Disable RC_FAST clock if it was used + if (chip->clock_source == SPI_CLK_SRC_RC_FAST) { + periph_rtc_dig_clk8m_disable(); + } +#endif +#endif // !CONFIG_IDF_TARGET_ESP32 +} + esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_device_config_t *config) { if (out_chip == NULL) { @@ -286,7 +409,8 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d .freq_mhz = config->freq_mhz, }; - host_cfg.clock_src_freq = spi_flash_ll_get_source_clock_freq_mhz(host_cfg.host_id); + // Init the gpspi clock + host_cfg.clock_src_freq = init_gpspi_clock(chip, config); err = memspi_host_init_pointers(host, &host_cfg); if (err != ESP_OK) { @@ -310,6 +434,9 @@ esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip) return ESP_ERR_INVALID_ARG; } + // Disable GPSPI clocks before cleanup + deinit_gpspi_clock(chip); + spi_bus_lock_dev_handle_t dev_handle = NULL; esp_flash_deinit_os_functions(chip, &dev_handle); if (dev_handle) { diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index 062e1c598f..31c68611d4 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/components/spi_flash/include/esp_flash.h @@ -8,7 +8,6 @@ #include "esp_err.h" #include #include - #include "hal/spi_flash_types.h" #ifdef __cplusplus @@ -104,6 +103,7 @@ struct esp_flash_t { uint32_t busy :1; ///< This flag is used to verify chip's status. uint32_t hpm_dummy_ena :1; ///< This flag is used to verify whether flash works under HPM status. uint32_t reserved_flags :30; ///< reserved. + int clock_source; ///< Clock source for GPSPI. }; diff --git a/components/spi_flash/include/esp_flash_spi_init.h b/components/spi_flash/include/esp_flash_spi_init.h index 493bd937eb..0332d3c2cd 100644 --- a/components/spi_flash/include/esp_flash_spi_init.h +++ b/components/spi_flash/include/esp_flash_spi_init.h @@ -27,6 +27,7 @@ typedef struct { */ int cs_id; int freq_mhz; ///< The frequency of flash chip(MHZ) + spi_clock_source_t clock_source;///< Select SPI clock source, `SPI_CLK_SRC_DEFAULT` by default. } esp_flash_spi_device_config_t; /**