mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-07 17:08:49 +00:00
spi_flash: bringup for esp32c6
This commit is contained in:
@@ -45,6 +45,9 @@ extern "C" {
|
||||
/// Empty function to be compatible with new version chips.
|
||||
#define spi_flash_ll_set_dummy_out(dev, out_en, out_lev)
|
||||
|
||||
// On ESP32, we extent 4 bits to occupy `Continuous Read Mode` bits. (same to origin code.)
|
||||
#define SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS (4)
|
||||
|
||||
/// type to store pre-calculated register value in above layers
|
||||
typedef typeof(SPI1.clock.val) spi_flash_ll_clock_reg_t;
|
||||
|
||||
@@ -431,6 +434,17 @@ static inline uint32_t spi_flash_ll_calculate_clock_reg(uint8_t host_id, uint8_t
|
||||
return div_parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra address for bits M0-M7 in DIO/QIO mode.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param extra_addr extra address(M0-M7) to send.
|
||||
*/
|
||||
static inline void spi_flash_ll_set_extra_address(spi_dev_t *dev, uint32_t extra_addr)
|
||||
{
|
||||
// Not supported on ESP32.
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -353,20 +353,6 @@ static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n)
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set D/Q output level during dummy phase
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param out_en whether to enable IO output for dummy phase
|
||||
* @param out_level dummy output level
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_dummy_out(spi_dev_t *dev, uint32_t out_en, uint32_t out_lev)
|
||||
{
|
||||
dev->ctrl.dummy_out = out_en;
|
||||
dev->ctrl.q_pol = out_lev;
|
||||
dev->ctrl.d_pol = out_lev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra hold time of CS after the clocks.
|
||||
*
|
||||
|
||||
@@ -35,7 +35,8 @@ extern "C" {
|
||||
}\
|
||||
dev_id; \
|
||||
})
|
||||
|
||||
// Since ESP32-C6, WB_mode is available, we extend 8 bits to occupy `Continuous Read Mode` bits.
|
||||
#define SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS (8)
|
||||
|
||||
typedef union {
|
||||
gpspi_flash_ll_clock_reg_t gpspi;
|
||||
@@ -61,9 +62,9 @@ typedef union {
|
||||
#define spi_flash_ll_set_address(dev, addr) gpspi_flash_ll_set_address((spi_dev_t*)dev, addr)
|
||||
#define spi_flash_ll_set_usr_address(dev, addr, bitlen) gpspi_flash_ll_set_usr_address((spi_dev_t*)dev, addr, bitlen)
|
||||
#define spi_flash_ll_set_dummy(dev, dummy) gpspi_flash_ll_set_dummy((spi_dev_t*)dev, dummy)
|
||||
#define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev)
|
||||
#define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n)
|
||||
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time)
|
||||
#define spi_flash_ll_set_extra_address(dev, extra_addr) { /* Not supported on gpspi on ESP32-C6*/ }
|
||||
#else
|
||||
#define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev)
|
||||
@@ -88,9 +89,9 @@ typedef union {
|
||||
#define spi_flash_ll_set_address(dev, addr) spimem_flash_ll_set_address((spi_mem_dev_t*)dev, addr)
|
||||
#define spi_flash_ll_set_usr_address(dev, addr, bitlen) spimem_flash_ll_set_usr_address((spi_mem_dev_t*)dev, addr, bitlen)
|
||||
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
|
||||
#define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev)
|
||||
#define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n)
|
||||
#define spi_flash_ll_set_cs_setup(dev, cs_setup_time) spimem_flash_ll_set_cs_setup((spi_mem_dev_t*)dev, cs_setup_time)
|
||||
#define spi_flash_ll_set_extra_address(dev, extra_addr) spimem_flash_ll_set_extra_address((spi_mem_dev_t*)dev, extra_addr)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "hal/assert.h"
|
||||
#include "hal/spi_types.h"
|
||||
#include "hal/spi_flash_types.h"
|
||||
#include "soc/pcr_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -474,6 +475,18 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
dev->user.usr_addr = bitlen ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extra address for bits M0-M7 in DIO/QIO mode.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param extra_addr extra address(M0-M7) to send.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr)
|
||||
{
|
||||
dev->cache_fctrl.usr_addr_4byte = 0;
|
||||
dev->rd_status.wb_mode = extra_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
@@ -509,20 +522,6 @@ static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_
|
||||
dev->user1.usr_dummy_cyclelen = dummy_n - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set D/Q output level during dummy phase
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param out_en whether to enable IO output for dummy phase
|
||||
* @param out_level dummy output level
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_dummy_out(spi_mem_dev_t *dev, uint32_t out_en, uint32_t out_lev)
|
||||
{
|
||||
// dev->ctrl.fdummy_out = out_en; // TODO: IDF-5333 removed
|
||||
dev->ctrl.q_pol = out_lev;
|
||||
dev->ctrl.d_pol = out_lev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CS hold time.
|
||||
*
|
||||
@@ -551,25 +550,44 @@ static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_
|
||||
*/
|
||||
static inline uint8_t spimem_flash_ll_get_source_freq_mhz(void)
|
||||
{
|
||||
// TODO: IDF-5333
|
||||
// // TODO: Default is PLL480M, this is hard-coded.
|
||||
// // In the future, we can get the CPU clock source by calling interface.
|
||||
// uint8_t clock_val = 0;
|
||||
// switch (SPIMEM0.core_clk_sel.spi01_clk_sel) {
|
||||
// case 0:
|
||||
// clock_val = 80;
|
||||
// break;
|
||||
// case 1:
|
||||
// clock_val = 120;
|
||||
// break;
|
||||
// case 2:
|
||||
// clock_val = 160;
|
||||
// break;
|
||||
// default:
|
||||
// abort();
|
||||
// }
|
||||
// return clock_val;
|
||||
return 80;
|
||||
// TODO: Default is PLL480M, this is hard-coded.
|
||||
// In the future, we can get the CPU clock source by calling interface.
|
||||
uint8_t clock_val = 0;
|
||||
|
||||
if (PCR.sysclk_conf.soc_clk_sel == 1) {
|
||||
switch (PCR.mspi_clk_conf.mspi_fast_hs_div_num) {
|
||||
case 3:
|
||||
clock_val = 120;
|
||||
break;
|
||||
case 4:
|
||||
clock_val = 96;
|
||||
break;
|
||||
case 5:
|
||||
clock_val = 80;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
} else {
|
||||
// If the system clock source is XTAL/FOSC
|
||||
switch (PCR.mspi_clk_conf.mspi_fast_ls_div_num) {
|
||||
case 0:
|
||||
clock_val = 40;
|
||||
break;
|
||||
case 1:
|
||||
clock_val = 20;
|
||||
break;
|
||||
case 2:
|
||||
clock_val = 10;
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
// Hard-coded line, will be removed when pll is enabled.
|
||||
clock_val = 80;
|
||||
|
||||
return clock_val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@ static const char *TAG = "flash_hal";
|
||||
static uint32_t get_flash_clock_divider(const spi_flash_hal_config_t *cfg)
|
||||
{
|
||||
int clk_source = cfg->clock_src_freq;
|
||||
// On ESP32, ESP32-S2, ESP32-C3, we allow specific frequency 26.666MHz, // TODO: IDF-5333 (check this)
|
||||
// On ESP32, ESP32-S2, ESP32-C3, we allow specific frequency 26.666MHz
|
||||
// If user passes freq_mhz like 26 or 27, it's allowed to use integer divider 3.
|
||||
// However on other chips or on other frequency, we only allow user pass frequency which
|
||||
// can be integer divided. If no, the following strategy is round up the division and
|
||||
|
||||
@@ -105,12 +105,28 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
|
||||
// The CONTROL_DUMMY_OUTPUT feature is used to control M7-M0 bits.
|
||||
spi_flash_ll_set_dummy_out(dev, (conf_required? 1: 0), 1);
|
||||
#else
|
||||
// On ESP32, dummy output is not supported. These dummy bits will be moved into the address
|
||||
// phase (and appended as ones).
|
||||
/**
|
||||
* - On current chips, addr phase can support 32 bits at most.
|
||||
* - Flash chip requires continuous mode bits
|
||||
*
|
||||
* We send continuous mode bits via the dummy output feature, so as to support
|
||||
* 32-bit address.
|
||||
*
|
||||
* On chips without dummy output feature (ESP32, ESP32C6), we fallback to use
|
||||
* addr phase to send the continuous mode bits:
|
||||
* - On ESP32 (QIO), qio_dummy: 6 - 4 / 4 = 5, addr_bitlen: 24 + 4 = 28. (This
|
||||
* setting exists for long time, we keep this on ESP32)
|
||||
* - On ESP32C6 (QIO), qio_dummy: 6 - 8 / 4 = 4, addr_bitlen: 24 + 8 = 32
|
||||
* - On future chips without dummy output feature, we follow the ESP32C6 (QIO)
|
||||
* way.
|
||||
* - Above two ways, the timings are same.
|
||||
* - DIO is similar.
|
||||
*/
|
||||
if (conf_required) {
|
||||
int line_width = (io_mode == SPI_FLASH_DIO? 2: 4);
|
||||
dummy_cyclelen_base -= 4 / line_width;
|
||||
addr_bitlen += 4; //extra 4 bits indicate the conf bits is included
|
||||
dummy_cyclelen_base -= SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS / line_width;
|
||||
addr_bitlen += SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS;
|
||||
spi_flash_ll_set_extra_address(dev, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user