1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "soc/dport_reg.h"
8 #include "esp_attr.h"
9 #include "esp_psram.h"
10 #include "esp_private/esp_psram_extram.h"
11 
12 #if CONFIG_FREERTOS_UNICORE
13 #define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
14 #else
15 #define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
16 #endif
17 
18 
19 /*
20  Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
21  otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
22  Note that this routine assumes some unique mapping for the first 2 banks of the PSRAM memory range, as well as the
23  2 banks after the 2 MiB mark.
24 */
esp_psram_extram_writeback_cache(void)25 void IRAM_ATTR esp_psram_extram_writeback_cache(void)
26 {
27     int x;
28     volatile int i=0;
29     volatile uint8_t *psram=(volatile uint8_t*)SOC_EXTRAM_DATA_LOW;
30     int cache_was_disabled=0;
31 
32     if (!esp_psram_is_initialized()) return;
33 
34     //We need cache enabled for this to work. Re-enable it if needed; make sure we
35     //disable it again on exit as well.
36     if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
37         cache_was_disabled|=(1<<0);
38         DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
39     }
40 #ifndef CONFIG_FREERTOS_UNICORE
41     if (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
42         cache_was_disabled|=(1<<1);
43         DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
44     }
45 #endif
46 
47 #if (PSRAM_MODE != PSRAM_VADDR_MODE_LOWHIGH)
48     /*
49     Single-core and even/odd mode only have 32K of cache evenly distributed over the address lines. We can clear
50     the cache by just reading 64K worth of cache lines.
51     */
52     for (x=0; x<1024*64; x+=32) {
53         i+=psram[x];
54     }
55 #else
56     /*
57     Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI flash and another 32K for the highest
58     2MiB. Clear this by reading from both regions.
59     Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If
60     we ever support external RAM chips of 2M or smaller, this may need adjusting.
61     */
62     for (x=0; x<1024*64; x+=32) {
63         i+=psram[x];
64         i+=psram[x+(1024*1024*2)];
65     }
66 #endif
67 
68     if (cache_was_disabled&(1<<0)) {
69         while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) ;
70         DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
71     }
72 #ifndef CONFIG_FREERTOS_UNICORE
73     if (cache_was_disabled&(1<<1)) {
74         while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1);
75         DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
76     }
77 #endif
78 }
79