From 81a9eb190d912e96e264613919a747eae08c17d3 Mon Sep 17 00:00:00 2001 From: Abdelatif Guettouche Date: Thu, 10 Dec 2020 09:15:24 +0000 Subject: [PATCH] arch/xtensa/src/esp32/esp32_spiflash.c: Invalidate the cache and writeback PSRAM data if the flash address used has a cache mapping. Signed-off-by: Abdelatif Guettouche --- arch/xtensa/src/esp32/esp32_spiflash.c | 309 +++++++++++++++++---- arch/xtensa/src/esp32/hardware/esp32_soc.h | 3 + 2 files changed, 252 insertions(+), 60 deletions(-) diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c b/arch/xtensa/src/esp32/esp32_spiflash.c index 95611b569f..cde3e6a3c7 100644 --- a/arch/xtensa/src/esp32/esp32_spiflash.c +++ b/arch/xtensa/src/esp32/esp32_spiflash.c @@ -41,10 +41,17 @@ #include "xtensa.h" #include "xtensa_attr.h" +#include "rom/esp32_spiflash.h" + #include "hardware/esp32_soc.h" #include "hardware/esp32_spi.h" #include "hardware/esp32_dport.h" -#include "rom/esp32_spiflash.h" + +#ifdef CONFIG_ESP32_SPIRAM +#include "esp32_spiram.h" +#endif + +#include "esp32_spiflash.h" /**************************************************************************** * Pre-processor Definitions @@ -56,7 +63,7 @@ #define SPI_FLASH_WRITE_WORDS (SPI_FLASH_WRITE_BUF_SIZE / 4) #define SPI_FLASH_READ_WORDS (SPI_FLASH_READ_BUF_SIZE / 4) -#define SPI_FLASH_MAP_PAGE_SIZE (0x10000) +#define SPI_FLASH_MMU_PAGE_SIZE (0x10000) #define SPI_FLASH_ENCRYPT_UNIT_SIZE (32) #define SPI_FLASH_ENCRYPT_WORDS (32 / 4) @@ -71,10 +78,13 @@ #define MTD_BLK2SIZE(_priv, _b) (MTD_BLKSIZE(_priv) * (_b)) #define MTD_SIZE2BLK(_priv, _s) ((_s) / MTD_BLKSIZE(_priv)) -#define MMU_ADDR2PAGE(_addr) ((_addr) / SPI_FLASH_MAP_PAGE_SIZE) -#define MMU_ADDR2OFF(_addr) ((_addr) % SPI_FLASH_MAP_PAGE_SIZE) -#define MMU_BYTES2PAGES(_n) (((_n) + SPI_FLASH_MAP_PAGE_SIZE - 1) \ - / SPI_FLASH_MAP_PAGE_SIZE) +#define MMU_ADDR2PAGE(_addr) ((_addr) / SPI_FLASH_MMU_PAGE_SIZE) +#define MMU_ADDR2OFF(_addr) ((_addr) % SPI_FLASH_MMU_PAGE_SIZE) +#define MMU_BYTES2PAGES(_n) (((_n) + SPI_FLASH_MMU_PAGE_SIZE - 1) \ + / SPI_FLASH_MMU_PAGE_SIZE) +#define MMU_ALIGNUP_SIZE(_s) (((_s) + SPI_FLASH_MMU_PAGE_SIZE - 1) \ + & ~(SPI_FLASH_MMU_PAGE_SIZE - 1)) +#define MMU_ALIGNDOWN_SIZE(_s) ((_s) & ~(SPI_FLASH_MMU_PAGE_SIZE - 1)) #ifndef MIN # define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -91,6 +101,9 @@ #define APP_MMU_TABLE ((volatile uint32_t *)DPORT_APP_FLASH_MMU_TABLE_REG) +#define PRO_IRAM0_FIRST_PAGE ((SOC_IRAM_LOW - SOC_DRAM_HIGH) /\ + (SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START)) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -148,13 +161,18 @@ struct spiflash_map_req uint32_t page_cnt; }; +struct spiflash_cachestate_s +{ + int cpu; + irqstate_t flags; + uint32_t val[2]; +}; + /**************************************************************************** * ROM function prototypes ****************************************************************************/ void Cache_Flush(int cpu); -void Cache_Read_Enable(int cpu); -void Cache_Read_Disable(int cpu); /**************************************************************************** * Private Functions Prototypes @@ -173,10 +191,13 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv, /* Misc. helpers */ -static inline irqstate_t IRAM_ATTR esp32_spiflash_opstart( - FAR struct esp32_spiflash_s *priv, int *cpu); -static inline void IRAM_ATTR esp32_spiflash_opdone( - FAR struct esp32_spiflash_s *priv, irqstate_t flags, int cpu); +static inline void IRAM_ATTR + esp32_spiflash_opstart(FAR struct spiflash_cachestate_s *state); +static inline void IRAM_ATTR + esp32_spiflash_opdone(FAR const struct spiflash_cachestate_s *state); + +static bool IRAM_ATTR spiflash_pagecached(uint32_t phypage); +static void IRAM_ATTR spiflash_flushmapped(size_t start, size_t size); /* Flash helpers */ @@ -376,6 +397,85 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv, putreg32(tmp & (~bits), priv->config->reg_base + offset); } +/**************************************************************************** + * Name: spiflash_disable_cache + ****************************************************************************/ + +static void IRAM_ATTR spi_disable_cache(int cpu, uint32_t *state) +{ + const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */ + uint32_t regval; + uint32_t ret = 0; + + if (cpu == 0) + { + ret |= (getreg32(DPORT_PRO_CACHE_CTRL1_REG) & cache_mask); + while (((getreg32(DPORT_PRO_DCACHE_DBUG0_REG) >> + DPORT_PRO_CACHE_STATE_S) & DPORT_PRO_CACHE_STATE) != 1) + { + ; + } + + regval = getreg32(DPORT_PRO_CACHE_CTRL_REG); + regval &= ~DPORT_PRO_CACHE_ENABLE_M; + putreg32(regval, DPORT_PRO_CACHE_CTRL_REG); + } +#ifdef CONFIG_SMP + else + { + ret |= (getreg32(DPORT_APP_CACHE_CTRL1_REG) & cache_mask); + while (((getreg32(DPORT_APP_DCACHE_DBUG0_REG) >> + DPORT_APP_CACHE_STATE_S) & DPORT_APP_CACHE_STATE) != 1) + { + ; + } + + regval = getreg32(DPORT_APP_CACHE_CTRL_REG); + regval &= ~DPORT_APP_CACHE_ENABLE_M; + putreg32(regval, DPORT_APP_CACHE_CTRL_REG); + } + +#endif + *state = ret; +} + +/**************************************************************************** + * Name: spiflash_enable_cache + ****************************************************************************/ + +static void IRAM_ATTR spi_enable_cache(int cpu, uint32_t state) +{ + const uint32_t cache_mask = 0x3f; /* Caches' bits in CTRL1_REG */ + uint32_t regval; + uint32_t ctrlreg; + uint32_t ctrl1reg; + uint32_t ctrlmask; + + if (cpu == 0) + { + ctrlreg = DPORT_PRO_CACHE_CTRL_REG; + ctrl1reg = DPORT_PRO_CACHE_CTRL1_REG; + ctrlmask = DPORT_PRO_CACHE_ENABLE_M; + } +#ifdef CONFIG_SMP + else + { + ctrlreg = DPORT_APP_CACHE_CTRL_REG; + ctrl1reg = DPORT_APP_CACHE_CTRL1_REG; + ctrlmask = DPORT_APP_CACHE_ENABLE_M; + } +#endif + + regval = getreg32(ctrlreg); + regval |= ctrlmask; + putreg32(regval, ctrlreg); + + regval = getreg32(ctrl1reg); + regval &= ~cache_mask; + regval |= state; + putreg32(regval, ctrl1reg); +} + /**************************************************************************** * Name: esp32_spiflash_opstart * @@ -384,32 +484,29 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv, * ****************************************************************************/ -static inline irqstate_t IRAM_ATTR esp32_spiflash_opstart( - FAR struct esp32_spiflash_s *priv, int *cpu) +static inline void IRAM_ATTR + esp32_spiflash_opstart(FAR struct spiflash_cachestate_s *state) { - irqstate_t flags; #ifdef CONFIG_SMP int other; #endif - flags = enter_critical_section(); + state->flags = enter_critical_section(); - *cpu = up_cpu_index(); + state->cpu = up_cpu_index(); #ifdef CONFIG_SMP - other = *cpu ? 0 : 1; + other = state->cpu ? 0 : 1; #endif - DEBUGASSERT(*cpu == 0 || *cpu == 1); + DEBUGASSERT(state->cpu == 0 || state->cpu == 1); #ifdef CONFIG_SMP DEBUGASSERT(other == 0 || other == 1); #endif - Cache_Read_Disable(*cpu); + spi_disable_cache(state->cpu, &state->val[state->cpu]); #ifdef CONFIG_SMP - Cache_Read_Disable(other); + spi_disable_cache(state->cpu, &state->val[other]); #endif - - return flags; } /**************************************************************************** @@ -420,30 +517,108 @@ static inline irqstate_t IRAM_ATTR esp32_spiflash_opstart( * ****************************************************************************/ -static inline void IRAM_ATTR esp32_spiflash_opdone( - FAR struct esp32_spiflash_s *priv, irqstate_t flags, int cpu) +static inline void IRAM_ATTR + esp32_spiflash_opdone(FAR const struct spiflash_cachestate_s *state) { #ifdef CONFIG_SMP int other; #endif #ifdef CONFIG_SMP - other = cpu ? 0 : 1; + other = state->cpu ? 0 : 1; #endif - DEBUGASSERT(cpu == 0 || cpu == 1); + DEBUGASSERT(state->cpu == 0 || state->cpu == 1); #ifdef CONFIG_SMP DEBUGASSERT(other == 0 || other == 1); #endif - Cache_Flush(cpu); - Cache_Read_Enable(cpu); + spi_enable_cache(state->cpu, state->val[state->cpu]); #ifdef CONFIG_SMP - Cache_Flush(other); - Cache_Read_Enable(other); + spi_enable_cache(other, state->val[other]); #endif - leave_critical_section(flags); + leave_critical_section(state->flags); +} + +/**************************************************************************** + * Name: spiflash_pagecached + * + * Description: + * Check if the given page is cached. + * + ****************************************************************************/ + +static bool IRAM_ATTR spiflash_pagecached(uint32_t phypage) +{ + int start[2]; + int end[2]; + int i; + int j; + + /* Data ROM start and end pages */ + + start[0] = DROM0_PAGES_START; + end[0] = DROM0_PAGES_END; + + /* Instruction RAM start and end pages */ + + start[1] = PRO_IRAM0_FIRST_PAGE; + end[1] = IROM0_PAGES_END; + + for (i = 0; i < 2; i++) + { + for (j = start[i]; j < end[i]; j++) + { + if (PRO_MMU_TABLE[j] == phypage) + { + return true; + } + } + } + + return false; +} + +/**************************************************************************** + * Name: spiflash_flushmapped + * + * Description: + * Writeback PSRAM data and invalidate the cache if the address is mapped. + * + ****************************************************************************/ + +static void IRAM_ATTR spiflash_flushmapped(size_t start, size_t size) +{ + uint32_t page_start; + uint32_t addr; + uint32_t page; + + page_start = MMU_ALIGNDOWN_SIZE(size); + size += (start - page_start); + size = MMU_ALIGNUP_SIZE(size); + + for (addr = page_start; addr < page_start + size; + addr += SPI_FLASH_MMU_PAGE_SIZE) + { + page = addr / SPI_FLASH_MMU_PAGE_SIZE; + + if (page >= 256) + { + return; + } + + if (spiflash_pagecached(page)) + { +#ifdef CONFIG_ESP32_SPIRAM + esp_spiram_writeback_cache(); +#endif + Cache_Flush(0); +#ifndef CONFIG_SMP + Cache_Flush(1); + } +#endif + } } /**************************************************************************** @@ -819,8 +994,7 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv, uint32_t addr, uint32_t size) { uint32_t offset; - int me; - uint32_t flags; + struct spiflash_cachestate_s state; esp32_set_write_opt(priv); @@ -831,11 +1005,11 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv, for (offset = 0; offset < size; offset += MTD_ERASESIZE(priv)) { - flags = esp32_spiflash_opstart(priv, &me); + esp32_spiflash_opstart(&state); if (esp32_enable_write(priv) != OK) { - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); return -EIO; } @@ -848,13 +1022,17 @@ static int IRAM_ATTR esp32_erasesector(FAR struct esp32_spiflash_s *priv, if (esp32_wait_idle(priv) != OK) { - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); return -EIO; } - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); } + esp32_spiflash_opstart(&state); + spiflash_flushmapped(addr, size); + esp32_spiflash_opdone(&state); + return 0; } @@ -953,11 +1131,10 @@ static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv, uint32_t size) { int ret; - int me; - uint32_t flags; uint32_t off = 0; uint32_t bytes; uint32_t tmp_buf[SPI_FLASH_WRITE_WORDS]; + struct spiflash_cachestate_s state; esp32_set_write_opt(priv); @@ -976,9 +1153,9 @@ static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv, memcpy(tmp_buf, &buffer[off], bytes); - flags = esp32_spiflash_opstart(priv, &me); + esp32_spiflash_opstart(&state); ret = esp32_writeonce(priv, addr, tmp_buf, bytes); - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); if (ret) { @@ -990,6 +1167,10 @@ static int IRAM_ATTR esp32_writedata(FAR struct esp32_spiflash_s *priv, off += bytes; } + esp32_spiflash_opstart(&state); + spiflash_flushmapped(addr, size); + esp32_spiflash_opdone(&state); + return OK; } @@ -1020,9 +1201,8 @@ static int IRAM_ATTR esp32_writedata_encrypted( int i; int blocks; int ret = OK; - int me; - uint32_t flags; uint32_t tmp_buf[SPI_FLASH_ENCRYPT_WORDS]; + struct spiflash_cachestate_s state; if (addr % SPI_FLASH_ENCRYPT_UNIT_SIZE) { @@ -1044,7 +1224,7 @@ static int IRAM_ATTR esp32_writedata_encrypted( { memcpy(tmp_buf, buffer, SPI_FLASH_ENCRYPT_UNIT_SIZE); - flags = esp32_spiflash_opstart(priv, &me); + esp32_spiflash_opstart(&state); esp_rom_spiflash_write_encrypted_enable(); ret = esp_rom_spiflash_prepare_encrypted_data(addr, tmp_buf); @@ -1063,18 +1243,22 @@ static int IRAM_ATTR esp32_writedata_encrypted( } esp_rom_spiflash_write_encrypted_disable(); - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); addr += SPI_FLASH_ENCRYPT_UNIT_SIZE; buffer += SPI_FLASH_ENCRYPT_UNIT_SIZE; size -= SPI_FLASH_ENCRYPT_UNIT_SIZE; } + esp32_spiflash_opstart(&state); + spiflash_flushmapped(addr, size); + esp32_spiflash_opdone(&state); + return 0; exit: esp_rom_spiflash_write_encrypted_disable(); - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); return ret; } @@ -1166,19 +1350,18 @@ static int IRAM_ATTR esp32_readdata(FAR struct esp32_spiflash_s *priv, uint32_t size) { int ret; - int me; - uint32_t flags; uint32_t off = 0; uint32_t bytes; uint32_t tmp_buf[SPI_FLASH_READ_WORDS]; + struct spiflash_cachestate_s state; while (size > 0) { bytes = MIN(size, SPI_FLASH_READ_BUF_SIZE); - flags = esp32_spiflash_opstart(priv, &me); + esp32_spiflash_opstart(&state); ret = esp32_readonce(priv, addr, tmp_buf, bytes); - esp32_spiflash_opdone(priv, flags, me); + esp32_spiflash_opdone(&state); if (ret) { @@ -1219,13 +1402,12 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv, { int ret; int i; - int me; int start_page; int flash_page; int page_cnt; - uint32_t flags; + struct spiflash_cachestate_s state; - flags = esp32_spiflash_opstart(priv, &me); + esp32_spiflash_opstart(&state); for (start_page = DROM0_PAGES_START; start_page < DROM0_PAGES_END; @@ -1257,7 +1439,7 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv, req->start_page = start_page; req->page_cnt = page_cnt; req->ptr = (void *)(VADDR0_START_ADDR + - start_page * SPI_FLASH_MAP_PAGE_SIZE + + start_page * SPI_FLASH_MMU_PAGE_SIZE + MMU_ADDR2OFF(req->src_addr)); ret = 0; @@ -1267,7 +1449,11 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv, ret = -ENOBUFS; } - esp32_spiflash_opdone(priv, flags, me); + Cache_Flush(0); +#ifdef CONFIG_SMP + Cache_Flush(1); +#endif + esp32_spiflash_opdone(&state); return ret; } @@ -1290,11 +1476,10 @@ static int IRAM_ATTR esp32_mmap(FAR struct esp32_spiflash_s *priv, static void IRAM_ATTR esp32_ummap(FAR struct esp32_spiflash_s *priv, const struct spiflash_map_req *req) { - uint32_t flags; - int me; int i; + struct spiflash_cachestate_s state; - flags = esp32_spiflash_opstart(priv, &me); + esp32_spiflash_opstart(&state); for (i = req->start_page; i < req->start_page + req->page_cnt; ++i) { @@ -1304,7 +1489,11 @@ static void IRAM_ATTR esp32_ummap(FAR struct esp32_spiflash_s *priv, #endif } - esp32_spiflash_opdone(priv, flags, me); + Cache_Flush(0); +#ifdef CONFIG_SMP + Cache_Flush(1); +#endif + esp32_spiflash_opdone(&state); } /**************************************************************************** diff --git a/arch/xtensa/src/esp32/hardware/esp32_soc.h b/arch/xtensa/src/esp32/hardware/esp32_soc.h index f0bb7e6e5e..e361c723c6 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_soc.h +++ b/arch/xtensa/src/esp32/hardware/esp32_soc.h @@ -785,6 +785,9 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, #define DROM0_PAGES_START 0 #define DROM0_PAGES_END 64 +#define IROM0_PAGES_START 64 +#define IROM0_PAGES_END 256 + /* MMU invaild value */ #define INVALID_MMU_VAL 0x100