You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/12/18 19:44:04 UTC
[incubator-nuttx] branch master updated:
arch/xtensa/src/esp32/esp32_spiflash.c: Invalidate the cache and writeback
PSRAM data if the flash address used has a cache mapping.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 81a9eb1 arch/xtensa/src/esp32/esp32_spiflash.c: Invalidate the cache and writeback PSRAM data if the flash address used has a cache mapping.
81a9eb1 is described below
commit 81a9eb190d912e96e264613919a747eae08c17d3
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Thu Dec 10 09:15:24 2020 +0000
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 <ab...@espressif.com>
---
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 95611b5..cde3e6a 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 */
@@ -377,6 +398,85 @@ static inline void spi_reset_regbits(struct esp32_spiflash_s *priv,
}
/****************************************************************************
+ * 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
*
* Description:
@@ -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 f0bb7e6..e361c72 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