1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * linux/arch/arm/mm/proc-v7m.S |
4 | * |
5 | * Copyright (C) 2008 ARM Ltd. |
6 | * Copyright (C) 2001 Deep Blue Solutions Ltd. |
7 | * |
8 | * This is the "shell" of the ARMv7-M processor support. |
9 | */ |
10 | #include <linux/linkage.h> |
11 | #include <asm/assembler.h> |
12 | #include <asm/page.h> |
13 | #include <asm/v7m.h> |
14 | #include "proc-macros.S" |
15 | |
16 | ENTRY(cpu_v7m_proc_init) |
17 | ret lr |
18 | ENDPROC(cpu_v7m_proc_init) |
19 | |
20 | ENTRY(cpu_v7m_proc_fin) |
21 | ret lr |
22 | ENDPROC(cpu_v7m_proc_fin) |
23 | |
24 | /* |
25 | * cpu_v7m_reset(loc) |
26 | * |
27 | * Perform a soft reset of the system. Put the CPU into the |
28 | * same state as it would be if it had been reset, and branch |
29 | * to what would be the reset vector. |
30 | * |
31 | * - loc - location to jump to for soft reset |
32 | */ |
33 | .align 5 |
34 | ENTRY(cpu_v7m_reset) |
35 | ret r0 |
36 | ENDPROC(cpu_v7m_reset) |
37 | |
38 | /* |
39 | * cpu_v7m_do_idle() |
40 | * |
41 | * Idle the processor (eg, wait for interrupt). |
42 | * |
43 | * IRQs are already disabled. |
44 | */ |
45 | ENTRY(cpu_v7m_do_idle) |
46 | wfi |
47 | ret lr |
48 | ENDPROC(cpu_v7m_do_idle) |
49 | |
50 | ENTRY(cpu_v7m_dcache_clean_area) |
51 | ret lr |
52 | ENDPROC(cpu_v7m_dcache_clean_area) |
53 | |
54 | /* |
55 | * There is no MMU, so here is nothing to do. |
56 | */ |
57 | ENTRY(cpu_v7m_switch_mm) |
58 | ret lr |
59 | ENDPROC(cpu_v7m_switch_mm) |
60 | |
61 | .globl cpu_v7m_suspend_size |
62 | .equ cpu_v7m_suspend_size, 0 |
63 | |
64 | #ifdef CONFIG_ARM_CPU_SUSPEND |
65 | ENTRY(cpu_v7m_do_suspend) |
66 | ret lr |
67 | ENDPROC(cpu_v7m_do_suspend) |
68 | |
69 | ENTRY(cpu_v7m_do_resume) |
70 | ret lr |
71 | ENDPROC(cpu_v7m_do_resume) |
72 | #endif |
73 | |
74 | ENTRY(cpu_cm7_dcache_clean_area) |
75 | dcache_line_size r2, r3 |
76 | movw r3, #:lower16:BASEADDR_V7M_SCB + V7M_SCB_DCCMVAC |
77 | movt r3, #:upper16:BASEADDR_V7M_SCB + V7M_SCB_DCCMVAC |
78 | |
79 | 1: str r0, [r3] @ clean D entry |
80 | add r0, r0, r2 |
81 | subs r1, r1, r2 |
82 | bhi 1b |
83 | dsb |
84 | ret lr |
85 | ENDPROC(cpu_cm7_dcache_clean_area) |
86 | |
87 | ENTRY(cpu_cm7_proc_fin) |
88 | movw r2, #:lower16:(BASEADDR_V7M_SCB + V7M_SCB_CCR) |
89 | movt r2, #:upper16:(BASEADDR_V7M_SCB + V7M_SCB_CCR) |
90 | ldr r0, [r2] |
91 | bic r0, r0, #(V7M_SCB_CCR_DC | V7M_SCB_CCR_IC) |
92 | str r0, [r2] |
93 | ret lr |
94 | ENDPROC(cpu_cm7_proc_fin) |
95 | |
96 | .section ".init.text" , "ax" |
97 | |
98 | __v7m_cm7_setup: |
99 | mov r8, #(V7M_SCB_CCR_DC | V7M_SCB_CCR_IC| V7M_SCB_CCR_BP) |
100 | b __v7m_setup_cont |
101 | /* |
102 | * __v7m_setup |
103 | * |
104 | * This should be able to cover all ARMv7-M cores. |
105 | */ |
106 | __v7m_setup: |
107 | mov r8, 0 |
108 | |
109 | __v7m_setup_cont: |
110 | @ Configure the vector table base address |
111 | ldr r0, =BASEADDR_V7M_SCB |
112 | ldr r12, =vector_table |
113 | str r12, [r0, V7M_SCB_VTOR] |
114 | |
115 | @ enable UsageFault, BusFault and MemManage fault. |
116 | ldr r5, [r0, #V7M_SCB_SHCSR] |
117 | orr r5, #(V7M_SCB_SHCSR_USGFAULTENA | V7M_SCB_SHCSR_BUSFAULTENA | V7M_SCB_SHCSR_MEMFAULTENA) |
118 | str r5, [r0, #V7M_SCB_SHCSR] |
119 | |
120 | @ Lower the priority of the SVC and PendSV exceptions |
121 | mov r5, #0x80000000 |
122 | str r5, [r0, V7M_SCB_SHPR2] @ set SVC priority |
123 | mov r5, #0x00800000 |
124 | str r5, [r0, V7M_SCB_SHPR3] @ set PendSV priority |
125 | |
126 | @ SVC to switch to handler mode. Notice that this requires sp to |
127 | @ point to writeable memory because the processor saves |
128 | @ some registers to the stack. |
129 | badr r1, 1f |
130 | ldr r5, [r12, #11 * 4] @ read the SVC vector entry |
131 | str r1, [r12, #11 * 4] @ write the temporary SVC vector entry |
132 | dsb |
133 | mov r6, lr @ save LR |
134 | ldr sp, =init_thread_union + THREAD_START_SP |
135 | cpsie i |
136 | svc #0 |
137 | 1: cpsid i |
138 | /* Calculate exc_ret */ |
139 | orr r10, lr, #EXC_RET_THREADMODE_PROCESSSTACK |
140 | ldmia sp, {r0-r3, r12} |
141 | str r5, [r12, #11 * 4] @ restore the original SVC vector entry |
142 | mov lr, r6 @ restore LR |
143 | |
144 | @ Special-purpose control register |
145 | mov r1, #1 |
146 | msr control, r1 @ Thread mode has unpriviledged access |
147 | |
148 | @ Configure caches (if implemented) |
149 | teq r8, #0 |
150 | stmiane sp, {r0-r6, lr} @ v7m_invalidate_l1 touches r0-r6 |
151 | blne v7m_invalidate_l1 |
152 | teq r8, #0 @ re-evalutae condition |
153 | ldmiane sp, {r0-r6, lr} |
154 | |
155 | @ Configure the System Control Register to ensure 8-byte stack alignment |
156 | @ Note the STKALIGN bit is either RW or RAO. |
157 | ldr r0, [r0, V7M_SCB_CCR] @ system control register |
158 | orr r0, #V7M_SCB_CCR_STKALIGN |
159 | orr r0, r0, r8 |
160 | |
161 | ret lr |
162 | ENDPROC(__v7m_setup) |
163 | |
164 | /* |
165 | * Cortex-M7 processor functions |
166 | */ |
167 | globl_equ cpu_cm7_proc_init, cpu_v7m_proc_init |
168 | globl_equ cpu_cm7_reset, cpu_v7m_reset |
169 | globl_equ cpu_cm7_do_idle, cpu_v7m_do_idle |
170 | globl_equ cpu_cm7_switch_mm, cpu_v7m_switch_mm |
171 | |
172 | define_processor_functions v7m, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1 |
173 | define_processor_functions cm7, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1 |
174 | |
175 | .section ".rodata" |
176 | string cpu_arch_name, "armv7m" |
177 | string cpu_elf_name "v7m" |
178 | string cpu_v7m_name "ARMv7-M" |
179 | |
180 | .section ".proc.info.init" , "a" |
181 | |
182 | .macro __v7m_proc name, initfunc, cache_fns = nop_cache_fns, hwcaps = 0, proc_fns = v7m_processor_functions |
183 | .long 0 /* proc_info_list.__cpu_mm_mmu_flags */ |
184 | .long 0 /* proc_info_list.__cpu_io_mmu_flags */ |
185 | initfn \initfunc, \name |
186 | .long cpu_arch_name |
187 | .long cpu_elf_name |
188 | .long HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \hwcaps |
189 | .long cpu_v7m_name |
190 | .long \proc_fns |
191 | .long 0 /* proc_info_list.tlb */ |
192 | .long 0 /* proc_info_list.user */ |
193 | .long \cache_fns |
194 | .endm |
195 | |
196 | /* |
197 | * Match ARM Cortex-M55 processor. |
198 | */ |
199 | .type __v7m_cm55_proc_info, #object |
200 | __v7m_cm55_proc_info: |
201 | .long 0x410fd220 /* ARM Cortex-M55 0xD22 */ |
202 | .long 0xff0ffff0 /* Mask off revision, patch release */ |
203 | __v7m_proc __v7m_cm55_proc_info, __v7m_cm7_setup, hwcaps = HWCAP_EDSP, cache_fns = v7m_cache_fns, proc_fns = cm7_processor_functions |
204 | .size __v7m_cm55_proc_info, . - __v7m_cm55_proc_info |
205 | |
206 | /* |
207 | * Match ARM Cortex-M33 processor. |
208 | */ |
209 | .type __v7m_cm33_proc_info, #object |
210 | __v7m_cm33_proc_info: |
211 | .long 0x410fd210 /* ARM Cortex-M33 0xD21 */ |
212 | .long 0xff0ffff0 /* Mask off revision, patch release */ |
213 | __v7m_proc __v7m_cm33_proc_info, __v7m_setup, hwcaps = HWCAP_EDSP |
214 | .size __v7m_cm33_proc_info, . - __v7m_cm33_proc_info |
215 | |
216 | /* |
217 | * Match ARM Cortex-M7 processor. |
218 | */ |
219 | .type __v7m_cm7_proc_info, #object |
220 | __v7m_cm7_proc_info: |
221 | .long 0x410fc270 /* ARM Cortex-M7 0xC27 */ |
222 | .long 0xff0ffff0 /* Mask off revision, patch release */ |
223 | __v7m_proc __v7m_cm7_proc_info, __v7m_cm7_setup, hwcaps = HWCAP_EDSP, cache_fns = v7m_cache_fns, proc_fns = cm7_processor_functions |
224 | .size __v7m_cm7_proc_info, . - __v7m_cm7_proc_info |
225 | |
226 | /* |
227 | * Match ARM Cortex-M4 processor. |
228 | */ |
229 | .type __v7m_cm4_proc_info, #object |
230 | __v7m_cm4_proc_info: |
231 | .long 0x410fc240 /* ARM Cortex-M4 0xC24 */ |
232 | .long 0xff0ffff0 /* Mask off revision, patch release */ |
233 | __v7m_proc __v7m_cm4_proc_info, __v7m_setup, hwcaps = HWCAP_EDSP |
234 | .size __v7m_cm4_proc_info, . - __v7m_cm4_proc_info |
235 | |
236 | /* |
237 | * Match ARM Cortex-M3 processor. |
238 | */ |
239 | .type __v7m_cm3_proc_info, #object |
240 | __v7m_cm3_proc_info: |
241 | .long 0x410fc230 /* ARM Cortex-M3 0xC23 */ |
242 | .long 0xff0ffff0 /* Mask off revision, patch release */ |
243 | __v7m_proc __v7m_cm3_proc_info, __v7m_setup |
244 | .size __v7m_cm3_proc_info, . - __v7m_cm3_proc_info |
245 | |
246 | /* |
247 | * Match any ARMv7-M processor core. |
248 | */ |
249 | .type __v7m_proc_info, #object |
250 | __v7m_proc_info: |
251 | .long 0x000f0000 @ Required ID value |
252 | .long 0x000f0000 @ Mask for ID |
253 | __v7m_proc __v7m_proc_info, __v7m_setup |
254 | .size __v7m_proc_info, . - __v7m_proc_info |
255 | |
256 | |