Merge branch 'fix/fix_gpspi_flash_frequency' into 'master'

refactor(spi_flash): Refactor gpspi flash for making it's clock accurate

Closes IDF-13566

See merge request espressif/esp-idf!40651
This commit is contained in:
C.S.M
2025-07-23 16:46:30 +08:00
25 changed files with 552 additions and 15 deletions

View File

@@ -15,6 +15,8 @@
#include <stdlib.h>
#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 <sys/param.h> // 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

View File

@@ -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)))