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