From aaf119e930f38aeaf757a58fd289b9a531cc9ee5 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Fri, 17 Jan 2020 15:14:13 +0800 Subject: [PATCH] flash(esp32s2): fix setting address field in spi user mode. --- .../esp_rom/include/esp32s2/rom/spi_flash.h | 10 +++--- .../soc/esp32/include/hal/spi_flash_ll.h | 25 +++++++++++++ .../soc/esp32s2/include/hal/gpspi_flash_ll.h | 36 +++++++++++++++++++ .../soc/esp32s2/include/hal/spi_flash_ll.h | 6 ++++ .../soc/esp32s2/include/hal/spimem_flash_ll.h | 25 +++++++++++++ .../soc/src/hal/spi_flash_hal_common.inc | 6 ++-- .../private_include/spi_flash_defs.h | 28 +++++++++++++++ components/spi_flash/spi_flash_chip_generic.c | 24 ++++++------- 8 files changed, 140 insertions(+), 20 deletions(-) diff --git a/components/esp_rom/include/esp32s2/rom/spi_flash.h b/components/esp_rom/include/esp32s2/rom/spi_flash.h index 1d9e8aa5e9..1eee20a5fa 100644 --- a/components/esp_rom/include/esp32s2/rom/spi_flash.h +++ b/components/esp_rom/include/esp32s2/rom/spi_flash.h @@ -129,11 +129,11 @@ typedef enum { ESP_ROM_SPIFLASH_DOUT_MODE, ESP_ROM_SPIFLASH_FASTRD_MODE, ESP_ROM_SPIFLASH_SLOWRD_MODE, - ESP_ROM_SPIFASH_OPI_STR_MODE, - ESP_ROM_SPIFASH_OPI_DTR_MODE, - ESP_ROM_SPIFASH_OOUT_MODE, - ESP_ROM_SPIFASH_OIO_STR_MODE, - ESP_ROM_SPIFASH_OIO_DTR_MODE, + ESP_ROM_SPIFLASH_OPI_STR_MODE, + ESP_ROM_SPIFLASH_OPI_DTR_MODE, + ESP_ROM_SPIFLASH_OOUT_MODE, + ESP_ROM_SPIFLASH_OIO_STR_MODE, + ESP_ROM_SPIFLASH_OIO_DTR_MODE, } esp_rom_spiflash_read_mode_t; typedef enum { diff --git a/components/soc/esp32/include/hal/spi_flash_ll.h b/components/soc/esp32/include/hal/spi_flash_ll.h index d818f011ca..36ccb71691 100644 --- a/components/soc/esp32/include/hal/spi_flash_ll.h +++ b/components/soc/esp32/include/hal/spi_flash_ll.h @@ -42,6 +42,9 @@ /// Get the start address of SPI peripheral registers by the host ID #define spi_flash_ll_get_hw(host_id) ((host_id)==SPI1_HOST? &SPI1:((host_id)==SPI2_HOST?&SPI2:((host_id)==SPI3_HOST?&SPI3:({abort();(spi_dev_t*)0;})))) +/// Empty function to be compatible with new version chips. +#define spi_flash_ll_set_dummy_out(dev, out_en, out_lev) + /// type to store pre-calculated register value in above layers typedef typeof(SPI1.clock) spi_flash_ll_clock_reg_t; @@ -316,6 +319,17 @@ static inline void spi_flash_ll_set_command8(spi_dev_t *dev, uint8_t command) dev->user2 = user2; } +/** + * Get the address length that is set in register, in bits. + * + * @param dev Beginning address of the peripheral registers. + * + */ +static inline int spi_flash_ll_get_addr_bitlen(spi_dev_t *dev) +{ + return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0; +} + /** * Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write... * @@ -328,6 +342,17 @@ static inline void spi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitlen) dev->user.usr_addr = bitlen ? 1 : 0; } +/** + * Set the address to send in user command mode. Should be called before commands that requires the address e.g. erase sector, read, write... + * + * @param dev Beginning address of the peripheral registers. + * @param addr Address to send + */ +static inline void spi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, int bit_len) +{ + dev->addr = (addr << (32 - bit_len)); +} + /** * Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write... * diff --git a/components/soc/esp32s2/include/hal/gpspi_flash_ll.h b/components/soc/esp32s2/include/hal/gpspi_flash_ll.h index 27ed122e5e..af23a0dbb0 100644 --- a/components/soc/esp32s2/include/hal/gpspi_flash_ll.h +++ b/components/soc/esp32s2/include/hal/gpspi_flash_ll.h @@ -281,6 +281,17 @@ static inline void gpspi_flash_ll_set_command8(spi_dev_t *dev, uint8_t command) dev->user2 = user2; } +/** + * Get the address length that is set in register, in bits. + * + * @param dev Beginning address of the peripheral registers. + * + */ +static inline int gpspi_flash_ll_get_addr_bitlen(spi_dev_t *dev) +{ + return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0; +} + /** * Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write... * @@ -293,6 +304,17 @@ static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitle dev->user.usr_addr = bitlen ? 1 : 0; } +/** + * Set the address to send in user mode. Should be called before commands that requires the address e.g. erase sector, read, write... + * + * @param dev Beginning address of the peripheral registers. + * @param addr Address to send + */ +static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, uint32_t bitlen) +{ + dev->addr = (addr << (32 - bitlen)); +} + /** * Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write... * @@ -316,3 +338,17 @@ static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) 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; +} + diff --git a/components/soc/esp32s2/include/hal/spi_flash_ll.h b/components/soc/esp32s2/include/hal/spi_flash_ll.h index 1c145dbd48..bc9e952005 100644 --- a/components/soc/esp32s2/include/hal/spi_flash_ll.h +++ b/components/soc/esp32s2/include/hal/spi_flash_ll.h @@ -58,8 +58,11 @@ typedef union { #define spi_flash_ll_set_mosi_bitlen(dev, bitlen) gpspi_flash_ll_set_mosi_bitlen((spi_dev_t*)dev, bitlen) #define spi_flash_ll_set_command8(dev, cmd) gpspi_flash_ll_set_command8((spi_dev_t*)dev, cmd) #define spi_flash_ll_set_addr_bitlen(dev, bitlen) gpspi_flash_ll_set_addr_bitlen((spi_dev_t*)dev, bitlen) +#define spi_flash_ll_get_addr_bitlen(dev) gpspi_flash_ll_get_addr_bitlen((spi_dev_t*)dev) #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) #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) @@ -80,6 +83,9 @@ typedef union { #define spi_flash_ll_set_mosi_bitlen(dev, bitlen) spimem_flash_ll_set_mosi_bitlen((spi_mem_dev_t*)dev, bitlen) #define spi_flash_ll_set_command8(dev, cmd) spimem_flash_ll_set_command8((spi_mem_dev_t*)dev, cmd) #define spi_flash_ll_set_addr_bitlen(dev, bitlen) spimem_flash_ll_set_addr_bitlen((spi_mem_dev_t*)dev, bitlen) +#define spi_flash_ll_get_addr_bitlen(dev) spimem_flash_ll_get_addr_bitlen(spi_mem_dev_t *dev) #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_address((spi_mem_dev_t*)dev, addr) #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) #endif diff --git a/components/soc/esp32s2/include/hal/spimem_flash_ll.h b/components/soc/esp32s2/include/hal/spimem_flash_ll.h index 100dd31c99..c243d2875a 100644 --- a/components/soc/esp32s2/include/hal/spimem_flash_ll.h +++ b/components/soc/esp32s2/include/hal/spimem_flash_ll.h @@ -318,6 +318,17 @@ static inline void spimem_flash_ll_set_command8(spi_mem_dev_t *dev, uint8_t comm dev->user2 = user2; } +/** + * Get the address length that is set in register, in bits. + * + * @param dev Beginning address of the peripheral registers. + * + */ +static inline int spimem_flash_ll_get_addr_bitlen(spi_mem_dev_t *dev) +{ + return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0; +} + /** * Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write... * @@ -352,3 +363,17 @@ static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_ dev->user.usr_dummy = dummy_n ? 1 : 0; 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; + dev->ctrl.q_pol = out_lev; + dev->ctrl.d_pol = out_lev; +} diff --git a/components/soc/src/hal/spi_flash_hal_common.inc b/components/soc/src/hal/spi_flash_hal_common.inc index fe888b3e23..e2b47e1850 100644 --- a/components/soc/src/hal/spi_flash_hal_common.inc +++ b/components/soc/src/hal/spi_flash_hal_common.inc @@ -60,6 +60,7 @@ esp_err_t spi_flash_hal_configure_host_io_mode( spi_flash_ll_set_addr_bitlen(dev, addr_bitlen); // Add dummy cycles to compensate for latency of GPIO matrix and external delay, if necessary... spi_flash_ll_set_dummy(dev, COMPUTE_DUMMY_CYCLELEN(host, dummy_cyclelen_base)); + spi_flash_ll_set_dummy_out(dev, 1, 1); //disable all data phases, enable them later if needed spi_flash_ll_set_miso_bitlen(dev, 0); spi_flash_ll_set_mosi_bitlen(dev, 0); @@ -78,8 +79,7 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *host, spi_flash_ spi_flash_ll_set_dummy(dev, 0); } - spi_flash_ll_set_address(dev, (trans->address & ADDRESS_MASK_24BIT) << 8); - + spi_flash_ll_set_usr_address(dev, (trans->address & ADDRESS_MASK_24BIT), spi_flash_ll_get_addr_bitlen(dev)); spi_flash_ll_set_mosi_bitlen(dev, trans->mosi_len * 8); spi_flash_ll_set_buffer_data(dev, trans->mosi_data, trans->mosi_len); @@ -93,7 +93,7 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *host, spi_flash_ esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *host, void *buffer, uint32_t address, uint32_t read_len) { spi_dev_t *dev = get_spi_dev(host); - spi_flash_ll_set_address(dev, address << 8); + spi_flash_ll_set_usr_address(dev, address, spi_flash_ll_get_addr_bitlen(dev)); spi_flash_ll_set_miso_bitlen(dev, read_len * 8); spi_flash_ll_user_start(dev); host->poll_cmd_done(host); diff --git a/components/spi_flash/private_include/spi_flash_defs.h b/components/spi_flash/private_include/spi_flash_defs.h index cd2e77fbb5..ea6df9a266 100644 --- a/components/spi_flash/private_include/spi_flash_defs.h +++ b/components/spi_flash/private_include/spi_flash_defs.h @@ -41,3 +41,31 @@ #define CMD_RST_EN 0x66 #define CMD_RST_DEV 0x99 + +#ifdef CONFIG_IDF_TARGET_ESP32S2 +#define SPI_FLASH_DIO_ADDR_BITLEN 24 +#define SPI_FLASH_DIO_DUMMY_BITLEN 4 +#define SPI_FLASH_QIO_ADDR_BITLEN 24 +#define SPI_FLASH_QIO_DUMMY_BITLEN 6 +#define SPI_FLASH_QOUT_ADDR_BITLEN 24 +#define SPI_FLASH_QOUT_DUMMY_BITLEN 8 +#define SPI_FLASH_DOUT_ADDR_BITLEN 24 +#define SPI_FLASH_DOUT_DUMMY_BITLEN 8 +#define SPI_FLASH_FASTRD_ADDR_BITLEN 24 +#define SPI_FLASH_FASTRD_DUMMY_BITLEN 8 +#define SPI_FLASH_SLOWRD_ADDR_BITLEN 24 +#define SPI_FLASH_SLOWRD_DUMMY_BITLEN 0 +#else +#define SPI_FLASH_DIO_ADDR_BITLEN 28 +#define SPI_FLASH_DIO_DUMMY_BITLEN 2 +#define SPI_FLASH_QIO_ADDR_BITLEN 32 +#define SPI_FLASH_QIO_DUMMY_BITLEN 4 +#define SPI_FLASH_QOUT_ADDR_BITLEN 24 +#define SPI_FLASH_QOUT_DUMMY_BITLEN 8 +#define SPI_FLASH_DOUT_ADDR_BITLEN 24 +#define SPI_FLASH_DOUT_DUMMY_BITLEN 8 +#define SPI_FLASH_FASTRD_ADDR_BITLEN 24 +#define SPI_FLASH_FASTRD_DUMMY_BITLEN 8 +#define SPI_FLASH_SLOWRD_ADDR_BITLEN 24 +#define SPI_FLASH_SLOWRD_DUMMY_BITLEN 0 +#endif \ No newline at end of file diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index 2def8b54b5..1b2995e29f 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -287,34 +287,34 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip) switch (chip->read_mode) { case SPI_FLASH_QIO: //for QIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that. - addr_bitlen = 32; - dummy_cyclelen_base = 4; + addr_bitlen = SPI_FLASH_QIO_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_QIO_DUMMY_BITLEN; read_command = CMD_FASTRD_QIO; break; case SPI_FLASH_QOUT: - addr_bitlen = 24; - dummy_cyclelen_base = 8; + addr_bitlen = SPI_FLASH_QOUT_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_QOUT_DUMMY_BITLEN; read_command = CMD_FASTRD_QUAD; break; case SPI_FLASH_DIO: //for DIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that. - addr_bitlen = 28; - dummy_cyclelen_base = 2; + addr_bitlen = SPI_FLASH_DIO_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_DIO_DUMMY_BITLEN; read_command = CMD_FASTRD_DIO; break; case SPI_FLASH_DOUT: - addr_bitlen = 24; - dummy_cyclelen_base = 8; + addr_bitlen = SPI_FLASH_DOUT_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_DOUT_DUMMY_BITLEN; read_command = CMD_FASTRD_DUAL; break; case SPI_FLASH_FASTRD: - addr_bitlen = 24; - dummy_cyclelen_base = 8; + addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_FASTRD_DUMMY_BITLEN; read_command = CMD_FASTRD; break; case SPI_FLASH_SLOWRD: - addr_bitlen = 24; - dummy_cyclelen_base = 0; + addr_bitlen = SPI_FLASH_SLOWRD_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_SLOWRD_DUMMY_BITLEN; read_command = CMD_READ; break; default: