mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 11:17:20 +02:00
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:
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <stdlib.h>
|
||||
#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 <sys/param.h> // 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
|
||||
|
@ -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)))
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#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 <sys/param.h> // 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
|
||||
|
@ -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)))
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#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 <sys/param.h> // 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
|
||||
|
@ -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)))
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#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 <sys/param.h> // 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
|
||||
|
@ -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)))
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#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 <sys/param.h> // 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
|
||||
|
@ -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)))
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdlib.h>
|
||||
#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 <sys/param.h> // 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
|
||||
|
@ -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)))
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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) {
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "esp_err.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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.
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user