xref: /optee_os/core/arch/arm/plat-stm/tz_a9init.S (revision f17691b3f6b27866f66636a53685bd3a6f7daa8a)
1/*
2 * Copyright (c) 2014, STMicroelectronics International N.V.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * Entry points for the A9 inits, A9 revision specific or not.
30 * It is assume no stack is available when these routines are called.
31 * It is assume each routine is called with return address in LR
32 * and with ARM registers R0, R1, R2, R3 being scratchable.
33 */
34#include <kernel/tz_ssvce_def.h>
35#include <arm32_macros.S>
36#include <asm.S>
37#include <kernel/unwind.h>
38
39#define CPUID_A9_R2P2_H 0x412f
40#define CPUID_A9_R2P2_L 0xc092
41
42#define CPUID_A9_R3P0_H 0x413f
43#define CPUID_A9_R3P0_L 0xc090
44
45.section .text
46.balign 4
47.code 32
48
49/*
50 * arm_secboot_identify_cpu - identify and save CPU version
51 *
52 * Use scratables registers R0-R3.
53 * No stack usage.
54 * LR store return address.
55 * Trap CPU in case of error.
56 */
57FUNC arm_secboot_identify_cpu , :
58UNWIND(	.fnstart)
59
60	mrc  p15, 0, r0, c0, c0, 0  /* read A9 ID */
61	movw r1, #CPUID_A9_R2P2_L
62	movt r1, #CPUID_A9_R2P2_H
63	cmp  r0, r1
64	beq  _ident_a9_r2p2
65	movw r1, #CPUID_A9_R3P0_L
66	movt r1, #CPUID_A9_R3P0_H
67	cmp  r0, r1
68	beq  _ident_a9_r3p0
69	b . /* TODO: unknown id: reset? log? */
70
71_ident_a9_r2p2:
72	/* unsupported version. TODO: needs to be supported */
73	b . /* TODO: unknown id: reset? log? */
74
75_ident_a9_r3p0:
76	mov pc, lr /* back to tzinit */
77UNWIND(	.fnend)
78END_FUNC arm_secboot_identify_cpu
79
80/*
81 * Memory Cache Level2 Configuration Function
82 *
83 * Use scratables registers R0-R3.
84 * No stack usage.
85 * LR store return address.
86 * Trap CPU in case of error.
87 */
88FUNC arm_cl2_config , :
89UNWIND(	.fnstart)
90
91	mrc  p15, 0, r0, c0, c0, 0  /* read A9 ID */
92	movw r1, #CPUID_A9_R3P0_L
93	movt r1, #CPUID_A9_R3P0_H
94	cmp  r0, r1
95	beq  _config_l2cc_r3p0
96	b . /* TODO: unknown id: reset? log? */
97
98_config_l2cc_r3p0:
99	/*
100	 * TAG RAM Control Register
101	 *
102	 * bit[10:8]:1 - 2 cycle of write accesses latency
103	 * bit[6:4]:1 - 2 cycle of read accesses latency
104	 * bit[2:0]:1 - 2 cycle of setup latency
105	 */
106	movw r0, #PL310_TAG_RAM_CTRL
107	movt r0, #PL310_BASE_H
108	ldr  r2, [r0]
109	movw r1, #0xf888
110	movt r1, #0xffff
111	and  r2,r2,r1
112	movw r1, #0xf999
113	movt r1, #0xffff
114	orr  r2,r2,r1
115	str  r2, [r0]
116
117	/*
118	 * DATA RAM Control Register
119	 *
120	 * bit[10:8]:2 - 3 cycle of write accesses latency
121	 * bit[6:4]:2 - 3 cycle of read accesses latency
122	 * bit[2:0]:2 - 3 cycle of setup latency
123	 */
124	movw r0, #PL310_DATA_RAM_CTRL
125	movt r0, #PL310_BASE_H
126	ldr  r2, [r0]
127	movw r1, #0xf888
128	movt r1, #0xffff
129	and  r2,r2,r1
130	movw r1, #0xfaaa
131	movt r1, #0xffff
132	orr  r2,r2,r1
133	str  r2, [r0]
134
135	/*
136	 * Auxiliary Control Register = 0x3C480800
137	 *
138	 * I/Dcache prefetch enabled (bit29:28=2b11)
139	 * NS can access interrupts (bit27=1)
140	 * NS can lockown cache lines (bit26=1)
141	 * Pseudo-random replacement policy (bit25=0)
142	 * Force write allocated (default)
143	 * Shared attribute internally ignored (bit22=1, bit13=0)
144	 * Parity disabled (bit21=0)
145	 * Event monitor disabled (bit20=0)
146	 * 128kB ways, 8-way associativity (bit19:17=3b100 bit16=0)
147	 * Store buffer device limitation enabled (bit11=1)
148	 * Cacheable accesses have high prio (bit10=0)
149	 * Full Line Zero (FLZ) disabled (bit0=0)
150	 */
151	movw r0, #PL310_AUX_CTRL
152	movt r0, #PL310_BASE_H
153	movw r1, #0x0800
154	movt r1, #0x3C48
155	str  r1, [r0]
156
157	/*
158	 * Prefetch Control Register = 0x31000007
159	 *
160	 * Double linefill disabled (bit30=0)
161	 * I/D prefetch enabled (bit29:28=2b11)
162	 * Prefetch drop enabled (bit24=1)
163	 * Incr double linefill disable (bit23=0)
164	 * Prefetch offset = 7 (bit4:0)
165	 */
166	movw r0, #PL310_PREFETCH_CTRL
167	movt r0, #PL310_BASE_H
168	movw r1, #0x0007
169	movt r1, #0x3100
170	str  r1, [r0]
171
172	/*
173	 * Power Register = 0x00000003
174	 *
175	 * Dynamic clock gating enabled
176	 * Standby mode enabled
177	 */
178	movw r0, #PL310_POWER_CTRL
179	movt r0, #PL310_BASE_H
180	movw r1, #0x0003
181	movt r1, #0x0000
182	str  r1, [r0]
183
184	/* invalidate all cache ways */
185	movw r0, #PL310_INV_BY_WAY
186	movt r0, #PL310_BASE_H
187	movw r1, #0x00FF
188	movt r1, #0x0000
189	str  r1, [r0]
190
191	mov pc, lr
192UNWIND(	.fnend)
193END_FUNC arm_cl2_config
194/* End of arm_cl2_config */
195
196
197/*
198 * Memory Cache Level2 Enable Function
199 *
200 * If PL310 supports FZLW, enable also FZL in A9 core
201 *
202 * Use scratables registers R0-R3.
203 * No stack usage.
204 * LR store return address.
205 * Trap CPU in case of error.
206 * TODO: to be moved to PL310 code (tz_svce_pl310.S ?)
207 */
208FUNC arm_cl2_enable , :
209UNWIND(	.fnstart)
210
211
212	/* Enable PL310 ctrl -> only set lsb bit */
213	movw r0, #PL310_CTRL
214	movt r0, #PL310_BASE_H
215	mov  r1, #0x1
216	str  r1, [r0]
217
218	/* if L2 FLZW enable, enable in L1 */
219	movw r0, #PL310_AUX_CTRL
220	movt r0, #PL310_BASE_H
221	ldr  r1, [r0]
222	tst  r1, #(1 << 0) /* test AUX_CTRL[FLZ] */
223	mrc  p15, 0, r0, c1, c0, 1
224	orrne r0, r0, #(1 << 3) /* enable ACTLR[FLZW] */
225	mcr  p15, 0, r0, c1, c0, 1
226
227	mov pc, lr
228UNWIND(	.fnend)
229END_FUNC arm_cl2_enable
230
231/*
232 * Cortex A9 configuration early configuration
233 *
234 * Use scratables registers R0-R3.
235 * No stack usage.
236 * LR store return address.
237 * Trap CPU in case of error.
238 */
239FUNC plat_cpu_reset_early , :
240UNWIND(	.fnstart)
241
242	/* only r3p0 is supported */
243	mrc  p15, 0, r0, c0, c0, 0  /* read A9 ID */
244	movw r1, #CPUID_A9_R3P0_L
245	movt r1, #CPUID_A9_R3P0_H
246	cmp  r0, r1
247	beq  _early_a9_r3p0
248	b . /* TODO: unknown id: reset? log? */
249
250_early_a9_r3p0:
251	/*
252	 * Mandated HW config loaded
253	 *
254	 * SCTLR = 0x00004000
255	 * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin)
256	 *
257	 * ACTRL = 0x00000041
258	 * - core always in full SMP (FW bit0=1, SMP bit6=1)
259	 * - L2 write full line of zero disabled (bit3=0)
260	 *   (keep WFLZ low. Will be set once outer L2 is ready)
261	 *
262	 * NSACR = 0x00020C00
263	 * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0)
264	 * - Nsec can lockdown TLB (TL bit17=1)
265	 * - NSec cannot access PLE (PLE bit16=0)
266	 * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11)
267	 *
268	 * PCR = 0x00000001
269	 * - no change latency, enable clk gating
270	 */
271	movw r0, #0x4000
272	movt r0, #0x0000
273	write_sctlr r0
274
275	movw r0, #0x0041
276	movt r0, #0x0000
277	write_actlr r0
278
279	movw r0, #0x0C00
280	movt r0, #0x0002
281	write_nsacr r0
282
283	movw r0, #0x0000
284	movt r0, #0x0001
285	write_pcr r0
286
287	/*
288	 * GIC configuration
289	 *
290	 * Register ICDISR0 = 0xFFFFFFFF
291	 * - All local interrupts are NonSecure.
292	 *
293	 * Register ICCPMR = 0xFFFFFFFF
294	 */
295
296	movw r0, #GIC_DIST_ISR0
297	movt r0, #GIC_DIST_BASE_H
298	mov  r1, #0xFFFFFFFF
299	str  r1, [r0]
300
301	movw r0, #CORE_ICC_ICCPMR
302	movt r0, #GIC_CPU_BASE_H
303	mov  r1, #0xFFFFFFFF
304	str  r1, [r0]
305
306	mov pc, lr /* back to tzinit */
307UNWIND(	.fnend)
308END_FUNC plat_cpu_reset_early
309
310/*
311 * arm_secboot_errata - arm errata, specific per core revision
312 *
313 * Use scratables registers R0-R3.
314 * No stack usage.
315 * LR store return address.
316 * Trap CPU in case of error.
317 */
318FUNC arm_secboot_errata , :
319UNWIND(	.fnstart)
320
321	mrc  p15, 0, r0, c0, c0, 0  /* read A9 ID */
322	movw r1, #CPUID_A9_R2P2_L
323	movt r1, #CPUID_A9_R2P2_H
324	cmp  r0, r1
325	beq  _errata_a9_r2p2
326	movw r1, #CPUID_A9_R3P0_L
327	movt r1, #CPUID_A9_R3P0_H
328	cmp  r0, r1
329	beq  _errata_a9_r3p0
330	b . /* TODO: unknown id: reset? log? */
331
332_errata_a9_r2p2:
333	/* unsupported version. TODO: needs to be supported */
334	b . /* TODO: unknown id: reset? log? */
335
336_errata_a9_r3p0:
337	mov pc, lr
338UNWIND(	.fnend)
339END_FUNC arm_secboot_errata
340
341/*
342 * A9 secured config, needed only from a single core
343 *
344 * Use scratables registers R0-R3.
345 * No stack usage.
346 * LR store return address.
347 * Trap CPU in case of error.
348 *
349 * TODO: size optim in code
350 */
351FUNC plat_cpu_reset_late , :
352UNWIND(	.fnstart)
353
354	mrc p15, 0, r0, c0, c0, 5
355	ands r0, #3
356	beq _boot_late_primary_cpu
357
358_boot_late_secondary_cpu:
359	mov pc, lr
360
361_boot_late_primary_cpu:
362	/*
363	 * Snoop Control Unit configuration
364	 *
365	 * SCU is enabled with filtering off.
366	 * Both Secure/Unsecure can access SCU and timers
367	 *
368	 * 0x00 SCUControl = 0x00000060 !!!  should be 0x5 !   A NETTOYER !!!!!!!!!!!!!!!!!!!!!!!!!
369	 * 0x04 SCUConfiguration =  ???                        A NETTOYER !!!!!!!!!!!!!!!!!!!!!!!!!
370	 * 0x0C SCUInvalidateAll (Secure cfg)
371	 * 0x40 FilteringStartAddress = 0x40000000
372	 * 0x44 FilteeringEndAddress - 0x80000000
373	 * 0x50 SCUAccessControl
374	 * 0x54 SCUSecureAccessControl
375	 */
376
377	/*
378	 * SCU Access Register : SAC = 0x00000003
379	 * - both secure CPU access SCU
380	 */
381	movw r0, #SCU_SAC /* LSB */
382	movt r0, #SCU_BASE_H /* MSB */
383	movw r1, #0x0003
384	movt r1, #0x0000
385	str  r1, [r0]
386
387	/*
388	 * SCU NonSecure Access Register : SNSAC : 0x00000333
389	 * - both nonsec cpu access SCU, private and global timer
390	 */
391	movw r0, #SCU_NSAC /* LSB */
392	movt r0, #SCU_BASE_H /* MSB */
393	movw r1, #0x0333
394	movt r1, #0x0000
395	str  r1, [r0]
396
397	/*
398	 * SCU Filtering End Address register: SFEA
399	 */
400	movw r0, #SCU_FILT_EA /* LSB */
401	movt r0, #SCU_BASE_H /* MSB */
402	movw r1, #(CPU_PORT_FILT_END & 0xFFFF)
403	movt r1, #(CPU_PORT_FILT_END >> 16)
404	str  r1, [r0]
405
406	/*
407	 * SCU Filtering Start Address register: SFSA
408	 */
409	movw r0, #SCU_FILT_SA /* LSB */
410	movt r0, #SCU_BASE_H /* MSB */
411	movw r1, #(CPU_PORT_FILT_START & 0xFFFF)
412	movt r1, #(CPU_PORT_FILT_START >> 16)
413	str  r1, [r0]
414
415	/*
416	 * SCU Control Register : CTRL = 0x00000065
417	 * - ic stanby enable=1
418	 * - scu standby enable=1
419	 * - scu enable=1
420	 */
421	movw r0, #SCU_CTRL /* LSB */
422	movt r0, #SCU_BASE_H /* MSB */
423	movw r1, #0x0065
424	movt r1, #0x0000
425	str	 r1, [r0]
426
427	/*- GIC secure configuration ---*/
428
429	/*
430	 * Register ICDISR[1-31] = 0xFFFFFFFF
431	 * - All external interrupts are NonSecure.
432	 */
433	movw r0, #GIC_DIST_ISR1
434	movt r0, #GIC_DIST_BASE_H
435	mov  r2, #0xFFFFFFFF
436	mov  r1, #31 /* Nb of loop rounds */
437loop_1:
438	str r2, [r0]
439	add r0, #4
440	sub r1, r1, #1
441	cmp r1, #0
442	bne loop_1
443
444
445	/*- PL310 Memory Controller (Note: should be done with NS=1) ---*/
446
447	/*
448	 * reg12_addr_filtering_end
449	 */
450	movw r0, #PL310_ADDR_FILT_END
451	movt r0, #PL310_BASE_H
452	movw r1, #(CPU_PORT_FILT_END & 0xFFFF)
453	movt r1, #(CPU_PORT_FILT_END >> 16)
454	str  r1, [r0]
455
456	/*
457	 * reg12_addr_filtering_start
458	 */
459	movw r0, #PL310_ADDR_FILT_START
460	movt r0, #PL310_BASE_H
461	movw r1, #((CPU_PORT_FILT_START & 0xFFFF) | 1)
462	movt r1, #(CPU_PORT_FILT_START >> 16)
463	str  r1, [r0]
464
465	/* Allow NSec to manage FIQ/Imprecise abort */
466	mrc p15, 0, r0, c1, c1, 0    /* read Secure Configuration Register */
467	orr r0, r0, #0x30            /* SCR[FW]=1, SCR[AW]=1 */
468	mcr p15, 0, r0, c1, c1, 0    /* write updated value in Secure Configuration Register */
469
470	mov pc, lr
471UNWIND(	.fnend)
472END_FUNC plat_cpu_reset_late
473