1 /*
2 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include "host_flash/cache_utils.h"
11 #include <zephyr/drivers/interrupt_controller/intc_esp32.h>
12
13 #define DPORT_CACHE_BIT(cpuid, regid) DPORT_ ## cpuid ## regid
14
15 #define DPORT_CACHE_MASK(cpuid) (DPORT_CACHE_BIT(cpuid, _CACHE_MASK_OPSDRAM) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DROM0) | \
16 DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DRAM1) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IROM0) | \
17 DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM1) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM0) )
18
19 #define DPORT_CACHE_VAL(cpuid) (~(DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DROM0) | \
20 DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DRAM1) | \
21 DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM0)))
22
23 #define DPORT_CACHE_GET_VAL(cpuid) (cpuid == 0) ? DPORT_CACHE_VAL(PRO) : DPORT_CACHE_VAL(APP)
24 #define DPORT_CACHE_GET_MASK(cpuid) (cpuid == 0) ? DPORT_CACHE_MASK(PRO) : DPORT_CACHE_MASK(APP)
25
26 static void spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state);
27 static void spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
28
29
30 static uint32_t s_cache_ops_saved_state[2];
31 static unsigned int s_intr_saved_state;
32
spi_flash_disable_cache(uint32_t cpuid,uint32_t * saved_state)33 static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state)
34 {
35 #if CONFIG_SOC_ESP32
36 uint32_t ret = 0;
37 const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
38 if (cpuid == 0) {
39 ret |= DPORT_GET_PERI_REG_BITS2(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, 0);
40 while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) {
41 ;
42 }
43 DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
44 }
45 #if CONFIG_SMP
46 else {
47 ret |= DPORT_GET_PERI_REG_BITS2(DPORT_APP_CACHE_CTRL1_REG, cache_mask, 0);
48 while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1) {
49 ;
50 }
51 DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
52 }
53 #endif
54 *saved_state = ret;
55 #elif CONFIG_SOC_ESP32S2
56 *saved_state = Cache_Suspend_ICache();
57 #elif CONFIG_SOC_ESP32S3
58 uint32_t icache_state, dcache_state;
59 icache_state = Cache_Suspend_ICache() << 16;
60 dcache_state = Cache_Suspend_DCache();
61 *saved_state = icache_state | dcache_state;
62 #elif CONFIG_SOC_ESP32C3
63 uint32_t icache_state;
64 icache_state = Cache_Suspend_ICache() << 16;
65 *saved_state = icache_state;
66 #endif
67 }
68
spi_flash_restore_cache(uint32_t cpuid,uint32_t saved_state)69 static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
70 {
71 #if CONFIG_SOC_ESP32
72 const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
73 if (cpuid == 0) {
74 DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
75 DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
76 }
77 #if CONFIG_SMP
78 else {
79 DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
80 DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
81 }
82 #endif
83 #elif CONFIG_SOC_ESP32S2
84 Cache_Resume_ICache(saved_state);
85 #elif CONFIG_SOC_ESP32S3
86 Cache_Resume_DCache(saved_state & 0xffff);
87 Cache_Resume_ICache(saved_state >> 16);
88 #elif CONFIG_SOC_ESP32C3
89 Cache_Resume_ICache(saved_state >> 16);
90 #endif
91 }
92
spi_flash_disable_interrupts_caches_and_other_cpu(void)93 void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
94 {
95 #ifdef CONFIG_MULTITHREADING
96 k_sched_lock();
97 #endif
98
99 s_intr_saved_state = irq_lock();
100
101 #if !defined(CONFIG_SOC_ESP32C3)
102 esp_intr_noniram_disable();
103 #endif
104
105 #if !defined(CONFIG_SOC_ESP32C3)
106 int cpu_id = arch_curr_cpu()->id;
107 #else
108 int cpu_id = PRO_CPU_NUM;
109 #endif
110 spi_flash_disable_cache(cpu_id, &s_cache_ops_saved_state[cpu_id]);
111
112 #ifdef CONFIG_SMP
113 int other_cpu = (cpu_id == PRO_CPU_NUM) ? APP_CPU_NUM : PRO_CPU_NUM;
114 spi_flash_disable_cache(other_cpu, &s_cache_ops_saved_state[other_cpu]);
115 #endif
116 }
117
spi_flash_enable_interrupts_caches_and_other_cpu(void)118 void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu(void)
119 {
120 #if !defined(CONFIG_SOC_ESP32C3)
121 int cpu_id = arch_curr_cpu()->id;
122 #else
123 int cpu_id = PRO_CPU_NUM;
124 #endif
125 spi_flash_restore_cache(cpu_id, s_cache_ops_saved_state[cpu_id]);
126
127 #ifdef CONFIG_SMP
128 int other_cpu = (cpu_id == PRO_CPU_NUM) ? APP_CPU_NUM : PRO_CPU_NUM;
129 spi_flash_restore_cache(other_cpu, s_cache_ops_saved_state[other_cpu]);
130 #endif
131
132 #if !defined(CONFIG_SOC_ESP32C3)
133 esp_intr_noniram_enable();
134 #endif
135
136 irq_unlock(s_intr_saved_state);
137
138 #ifdef CONFIG_MULTITHREADING
139 k_sched_unlock();
140 #endif
141 }
142