From 17f814acf3d8e47dfd88f81b54e04c0410f01b35 Mon Sep 17 00:00:00 2001 From: "C.S.M" Date: Tue, 30 Jul 2024 11:10:29 +0800 Subject: [PATCH] fix(spi_flash): Add external flash support on esp32c6,esp32h2,esp32p4,esp32c5 --- .../hal/esp32c5/include/hal/gpspi_flash_ll.h | 16 +++- .../hal/esp32c6/include/hal/gpspi_flash_ll.h | 16 +++- .../hal/esp32c61/include/hal/gpspi_flash_ll.h | 14 +++ .../hal/esp32h2/include/hal/gpspi_flash_ll.h | 62 ++++++------- .../hal/esp32p4/include/hal/gpspi_flash_ll.h | 92 +++++++++---------- components/hal/spi_flash_hal_common.inc | 4 + components/spi_flash/esp_flash_spi_init.c | 16 +++- .../esp_flash/main/test_esp_flash_def.h | 16 ++-- 8 files changed, 142 insertions(+), 94 deletions(-) diff --git a/components/hal/esp32c5/include/hal/gpspi_flash_ll.h b/components/hal/esp32c5/include/hal/gpspi_flash_ll.h index 4206665f6a..73d64db653 100644 --- a/components/hal/esp32c5/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c5/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -366,6 +366,20 @@ 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. * diff --git a/components/hal/esp32c6/include/hal/gpspi_flash_ll.h b/components/hal/esp32c6/include/hal/gpspi_flash_ll.h index 4206665f6a..73d64db653 100644 --- a/components/hal/esp32c6/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c6/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -366,6 +366,20 @@ 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. * diff --git a/components/hal/esp32c61/include/hal/gpspi_flash_ll.h b/components/hal/esp32c61/include/hal/gpspi_flash_ll.h index f0bfd56982..92620c7f75 100644 --- a/components/hal/esp32c61/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c61/include/hal/gpspi_flash_ll.h @@ -368,6 +368,20 @@ 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. * diff --git a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h index c086401f32..124863b7d6 100644 --- a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,9 +53,9 @@ static inline void gpspi_flash_ll_reset(spi_dev_t *dev) dev->clk_gate.mst_clk_sel = 1; dev->dma_conf.val = 0; - // dev->dma_conf.tx_seg_trans_clr_en = 1; - // dev->dma_conf.rx_seg_trans_clr_en = 1; - // dev->dma_conf.dma_seg_trans_en = 0; + dev->dma_conf.slv_tx_seg_trans_clr_en = 1; + dev->dma_conf.slv_rx_seg_trans_clr_en = 1; + dev->dma_conf.dma_slv_seg_trans_en = 0; } /** @@ -79,20 +79,20 @@ static inline bool gpspi_flash_ll_cmd_is_done(const spi_dev_t *dev) */ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, uint32_t read_len) { - // if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { - // // If everything is word-aligned, do a faster memcpy - // memcpy(buffer, (void *)dev->data_buf, read_len); - // } else { - // // Otherwise, slow(er) path copies word by word - // int copy_len = read_len; - // for (int i = 0; i < (read_len + 3) / 4; i++) { - // int word_len = MIN(sizeof(uint32_t), copy_len); - // uint32_t word = dev->data_buf[i]; - // memcpy(buffer, &word, word_len); - // buffer = (void *)((intptr_t)buffer + word_len); - // copy_len -= word_len; - // } - // } + if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { + // If everything is word-aligned, do a faster memcpy + memcpy(buffer, (void *)dev->data_buf, read_len); + } else { + // Otherwise, slow(er) path copies word by word + int copy_len = read_len; + for (int i = 0; i < (read_len + 3) / 4; i++) { + int word_len = MIN(sizeof(uint32_t), copy_len); + uint32_t word = dev->data_buf[i].buf0; + memcpy(buffer, &word, word_len); + buffer = (void *)((intptr_t)buffer + word_len); + copy_len -= word_len; + } + } } /** @@ -103,7 +103,7 @@ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, */ static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word) { - // dev->data_buf[0] = word; + dev->data_buf[0].buf0 = word; } /** @@ -116,15 +116,15 @@ static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word) static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *buffer, uint32_t length) { // Load data registers, word at a time - // int num_words = (length + 3) / 4; - // for (int i = 0; i < num_words; i++) { - // uint32_t word = 0; - // uint32_t word_len = MIN(length, sizeof(word)); - // memcpy(&word, buffer, word_len); - // dev->data_buf[i] = word; - // length -= word_len; - // buffer = (void *)((intptr_t)buffer + word_len); - // } + int num_words = (length + 3) / 4; + for (int i = 0; i < num_words; i++) { + uint32_t word = 0; + uint32_t word_len = MIN(length, sizeof(word)); + memcpy(&word, buffer, word_len); + dev->data_buf[i].buf0 = word; + length -= word_len; + buffer = (void *)((intptr_t)buffer + word_len); + } } /** @@ -339,8 +339,8 @@ static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitle static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, uint32_t bitlen) { // The blank region should be all ones - // uint32_t padding_ones = (bitlen == 32? 0 : UINT32_MAX >> bitlen); - // dev->addr = (addr << (32 - bitlen)) | padding_ones; + uint32_t padding_ones = (bitlen == 32? 0 : UINT32_MAX >> bitlen); + dev->addr.val = (addr << (32 - bitlen)) | padding_ones; } /** @@ -351,7 +351,7 @@ static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, */ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) { - // dev->addr = addr; + dev->addr.val = addr; } /** diff --git a/components/hal/esp32p4/include/hal/gpspi_flash_ll.h b/components/hal/esp32p4/include/hal/gpspi_flash_ll.h index 05c38d87f2..73d64db653 100644 --- a/components/hal/esp32p4/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32p4/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,7 +23,6 @@ #include #include #include "hal/misc.h" -//TODO: IDF-7499 #ifdef __cplusplus extern "C" { @@ -33,7 +32,7 @@ extern "C" { #define gpspi_flash_ll_get_hw(host_id) ( ((host_id)==SPI2_HOST) ? &GPSPI2 : ({abort();(spi_dev_t*)0;}) ) #define gpspi_flash_ll_hw_get_id(dev) ( ((dev) == (void*)&GPSPI2) ? SPI2_HOST : -1 ) -typedef typeof(GPSPI2.clock) gpspi_flash_ll_clock_reg_t; +typedef typeof(GPSPI2.clock.val) gpspi_flash_ll_clock_reg_t; #define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (80) /*------------------------------------------------------------------------------ @@ -46,18 +45,17 @@ typedef typeof(GPSPI2.clock) gpspi_flash_ll_clock_reg_t; */ static inline void gpspi_flash_ll_reset(spi_dev_t *dev) { - // dev->user.val = 0; - // dev->ctrl.val = 0; + dev->user.val = 0; + dev->ctrl.val = 0; - // dev->clk_gate.clk_en = 1; - // dev->clk_gate.mst_clk_active = 1; - // dev->clk_gate.mst_clk_sel = 1; + dev->clk_gate.clk_en = 1; + dev->clk_gate.mst_clk_active = 1; + dev->clk_gate.mst_clk_sel = 1; - // dev->dma_conf.val = 0; - // dev->dma_conf.tx_seg_trans_clr_en = 1; - // dev->dma_conf.rx_seg_trans_clr_en = 1; - // dev->dma_conf.dma_seg_trans_en = 0; - abort(); //TODO: IDF-7499 + dev->dma_conf.val = 0; + dev->dma_conf.slv_tx_seg_trans_clr_en = 1; + dev->dma_conf.slv_rx_seg_trans_clr_en = 1; + dev->dma_conf.dma_slv_seg_trans_en = 0; } /** @@ -81,21 +79,20 @@ static inline bool gpspi_flash_ll_cmd_is_done(const spi_dev_t *dev) */ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, uint32_t read_len) { - // if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { - // // If everything is word-aligned, do a faster memcpy - // memcpy(buffer, (void *)dev->data_buf, read_len); - // } else { - // // Otherwise, slow(er) path copies word by word - // int copy_len = read_len; - // for (int i = 0; i < (read_len + 3) / 4; i++) { - // int word_len = MIN(sizeof(uint32_t), copy_len); - // uint32_t word = dev->data_buf[i]; - // memcpy(buffer, &word, word_len); - // buffer = (void *)((intptr_t)buffer + word_len); - // copy_len -= word_len; - // } - // } - abort(); //TODO: IDF-7499 + if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { + // If everything is word-aligned, do a faster memcpy + memcpy(buffer, (void *)dev->data_buf, read_len); + } else { + // Otherwise, slow(er) path copies word by word + int copy_len = read_len; + for (int i = 0; i < (read_len + 3) / 4; i++) { + int word_len = MIN(sizeof(uint32_t), copy_len); + uint32_t word = dev->data_buf[i].buf; + memcpy(buffer, &word, word_len); + buffer = (void *)((intptr_t)buffer + word_len); + copy_len -= word_len; + } + } } /** @@ -106,8 +103,7 @@ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, */ static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word) { - // dev->data_buf[0] = word; - abort(); //TODO: IDF-7499 + dev->data_buf[0].buf = word; } /** @@ -119,17 +115,16 @@ static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word) */ static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *buffer, uint32_t length) { - // // Load data registers, word at a time - // int num_words = (length + 3) / 4; - // for (int i = 0; i < num_words; i++) { - // uint32_t word = 0; - // uint32_t word_len = MIN(length, sizeof(word)); - // memcpy(&word, buffer, word_len); - // dev->data_buf[i] = word; - // length -= word_len; - // buffer = (void *)((intptr_t)buffer + word_len); - // } - abort(); //TODO: IDF-7499 + // Load data registers, word at a time + int num_words = (length + 3) / 4; + for (int i = 0; i < num_words; i++) { + uint32_t word = 0; + uint32_t word_len = MIN(length, sizeof(word)); + memcpy(&word, buffer, word_len); + dev->data_buf[i].buf = word; + length -= word_len; + buffer = (void *)((intptr_t)buffer + word_len); + } } /** @@ -141,7 +136,6 @@ static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *bu */ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev, bool pe_ops) { - dev->ctrl.hold_pol = 1; dev->cmd.update = 1; while (dev->cmd.update); dev->cmd.usr = 1; @@ -264,7 +258,7 @@ static inline void gpspi_flash_ll_set_read_mode(spi_dev_t *dev, esp_flash_io_mod */ static inline void gpspi_flash_ll_set_clock(spi_dev_t *dev, gpspi_flash_ll_clock_reg_t *clock_val) { - dev->clock.val = (*clock_val).val; + dev->clock.val = *clock_val; } /** @@ -344,10 +338,9 @@ static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitle */ static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, uint32_t bitlen) { - // // The blank region should be all ones - // uint32_t padding_ones = (bitlen == 32? 0 : UINT32_MAX >> bitlen); - // dev->addr = (addr << (32 - bitlen)) | padding_ones; - abort(); //TODO: IDF-7499 + // The blank region should be all ones + uint32_t padding_ones = (bitlen == 32? 0 : UINT32_MAX >> bitlen); + dev->addr.val = (addr << (32 - bitlen)) | padding_ones; } /** @@ -358,8 +351,7 @@ static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, */ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) { - // dev->addr = addr; - abort(); //TODO: IDF-7499 + dev->addr.val = addr; } /** @@ -371,7 +363,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index e83fd0a290..4281105faa 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -103,6 +103,7 @@ esp_err_t spi_flash_hal_configure_host_io_mode( return ESP_ERR_NOT_SUPPORTED; } +#ifndef GPSPI_BUILD #if SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT // The CONTROL_DUMMY_OUTPUT feature is used to control M7-M0 bits. spi_flash_ll_set_dummy_out(dev, (conf_required? 1: 0), 1); @@ -131,6 +132,9 @@ esp_err_t spi_flash_hal_configure_host_io_mode( spi_flash_ll_set_extra_address(dev, 0); } #endif +#else + gpspi_flash_ll_set_dummy_out(dev, (conf_required? 1: 0), 1); +#endif #if CONFIG_IDF_TARGET_ESP32P4 // TODO: This is temporarily for ESP32P4-ECO0, please remove it when eco0 is not widly used. IDF-10019 diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 0ab6c98da1..7c7235eab6 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -123,7 +123,7 @@ esp_flash_t *esp_flash_default_chip = NULL; #endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND #endif // Other target -static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_flash_spi_device_config_t *config, bool use_iomux, int cs_id) +static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_flash_spi_device_config_t *config, bool cs_use_iomux, int cs_id) { //Not using spicommon_cs_initialize since we don't want to put the whole //spi_periph_signal into the DRAM. Copy these data from flash before the @@ -140,7 +140,7 @@ static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_f //initialization, disable the cache temporarily chip->os_func->start(chip->os_func_data); gpio_hal_input_enable(&gpio_hal, cs_io_num); - if (use_iomux) { + if (cs_use_iomux) { gpio_hal_func_sel(&gpio_hal, cs_io_num, spics_func); } else { gpio_hal_output_enable(&gpio_hal, cs_io_num); @@ -175,6 +175,16 @@ static bool bus_using_iomux(spi_host_device_t host) return true; } +static bool cs_using_iomux(const esp_flash_spi_device_config_t *config) +{ + bool use_iomux = true; + CHECK_IOMUX_PIN(config->host_id, spics); + if (config->cs_io_num != spi_periph_signal[config->host_id].spics_in) { + use_iomux = false; + } + return use_iomux; +} + static esp_err_t acquire_spi_device(const esp_flash_spi_device_config_t *config, int* out_dev_id, spi_bus_lock_dev_handle_t* out_dev_handle) { esp_err_t ret = ESP_OK; @@ -274,7 +284,7 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d } // The cs_id inside `config` is deprecated, use the `dev_id` provided by the bus lock instead. - cs_initialize(chip, config, use_iomux, dev_id); + cs_initialize(chip, config, cs_using_iomux(config), dev_id); *out_chip = chip; return ret; fail: diff --git a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h index d6a2da7c3e..ecbb64df50 100644 --- a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h +++ b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h @@ -68,7 +68,7 @@ #define HSPI_PIN_NUM_WP FSPI_PIN_NUM_WP #define HSPI_PIN_NUM_CS FSPI_PIN_NUM_CS -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C5 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 #define SPI1_CS_IO 26 //the pin which is usually used by the PSRAM cs #define SPI1_HD_IO 27 //the pin which is usually used by the PSRAM hd #define SPI1_WP_IO 28 //the pin which is usually used by the PSRAM wp @@ -88,14 +88,14 @@ #define HSPI_PIN_NUM_WP FSPI_PIN_NUM_WP #define HSPI_PIN_NUM_CS FSPI_PIN_NUM_CS -#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32H2 -#define FSPI_PIN_NUM_MOSI 7 -#define FSPI_PIN_NUM_MISO 2 -#define FSPI_PIN_NUM_CLK 6 -#define FSPI_PIN_NUM_HD 4 -#define FSPI_PIN_NUM_WP 5 -#define FSPI_PIN_NUM_CS 17 +#define FSPI_PIN_NUM_MOSI 5 +#define FSPI_PIN_NUM_MISO 0 +#define FSPI_PIN_NUM_CLK 4 +#define FSPI_PIN_NUM_HD 3 +#define FSPI_PIN_NUM_WP 2 +#define FSPI_PIN_NUM_CS 1 // Just use the same pins for HSPI #define HSPI_PIN_NUM_MOSI FSPI_PIN_NUM_MOSI