Add Broadcom's code for bcm63xx support
[project/bcm63xx/atf.git] / plat / bcm / brcm_bl32_setup.c
1 /*
2 <:copyright-BRCM:2019:DUAL/GPL:standard
3
4 Copyright (c) 2019 Broadcom
5 All Rights Reserved
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License, version 2, as published by
9 the Free Software Foundation (the "GPL").
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16
17 A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php, or by
18 writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20
21 :>
22 */
23
24 #include <arch.h>
25 #include <arch_helpers.h>
26 #include <assert.h>
27 #include <bl_common.h>
28 #include <console.h>
29 #include <debug.h>
30 #include <mmio.h>
31 #include <plat_arm.h>
32 #include <platform.h>
33 #include <gicv2.h>
34 #include <string.h>
35 #include <generic_delay_timer.h>
36 #include <delay_timer.h>
37
38 #define MAP_BL_SP_MIN_TOTAL MAP_REGION_FLAT( \
39 BL32_BASE, \
40 BL32_END - BL32_BASE, \
41 MT_MEMORY | MT_RW | MT_SECURE)
42
43 #define ARM_MAP_BL_RO MAP_REGION_FLAT( \
44 BL_CODE_BASE, \
45 BL_CODE_END - BL_CODE_BASE, \
46 MT_CODE | MT_SECURE)
47
48 #define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
49 BL_COHERENT_RAM_BASE, \
50 BL_COHERENT_RAM_END \
51 - BL_COHERENT_RAM_BASE, \
52 MT_DEVICE | MT_RW | MT_SECURE)
53
54 struct atf_image_info {
55 struct param_header h;
56 uintptr_t image_base; /* physical address of base of image */
57 uint32_t image_size; /* bytes read from image file */
58 };
59
60 struct atf_entry_point_info {
61 struct param_header h;
62 uintptr_t pc;
63 uint32_t spsr;
64 struct aapcs64_params args;
65 };
66
67 typedef struct bl31_params {
68 param_header_t h;
69 struct atf_image_info *bl31_image_info;
70 struct atf_entry_point_info *bl32_ep_info;
71 struct atf_image_info *bl32_image_info;
72 struct atf_entry_point_info *bl33_ep_info;
73 struct atf_image_info *bl33_image_info;
74 } bl31_params_t;
75
76
77 #define BL32_END (uintptr_t)(&__BL32_END__)
78 #define DEVICE_BASE 0x80000000
79 #define DEVICE_SIZE 0x00010000
80
81
82 #define DESC_DOMAIN(x) ((x << 5) & 0x000001E0)
83 // section descriptor definitions
84 #define SECTION_AP 0xc00
85 #define SECTION_XN 0x10
86 #define SECTION_PXN 0x1
87 /* A9 does not support PXN */
88 #define SECTION_XN_ALL (SECTION_XN)
89 #define SECTION_SHAREABLE (1 << 16)
90 #define SECTION_SUPER_DESC (1 << 18)
91 #define SECTION_DESC_NS (1 << 19)
92 // TEX[2] = 1
93 #define SECTION_OUTER_NC_INNER_WBWA 0x00004006
94 #define SECTION_OUTER_WBNWA_INNER_WBWA 0x00007006
95 #define SECTION_OUTER_WTNWA_INNER_WBWA 0x00006006
96 #define SECTION_OUTER_WBWA_INNER_NC 0x00005002
97 // TEX[2] = 0, OUTER & INNER are same all the time
98 #define SECTION_OUTER_WBWA_INNER_WBWA 0x0000100E
99 #define SECTION_OUTER_NSD_INNER_NSD 0x00002002
100 #define SECTION_OUTER_NC_INNER_NC 0x00001002
101 #define SECTION_OUTER_WTNWA_INNER_WTNWA 0x0000000A
102 #define SECTION_OUTER_WBNWA_INNER_WBNWA 0x0000000E
103 #define SECTION_OUTER_SO_INNER_SO 0x00000002
104 #define SECTION_OUTER_SD_INNER_SD 0x00000006
105
106 // definition for common section attribute
107 #define SECTION_ATTR_INVALID 0x0
108 #define SECTION_ATTR_CACHED_MEM \
109 (SECTION_OUTER_WBWA_INNER_WBWA|SECTION_AP|DESC_DOMAIN(0)|SECTION_SHAREABLE)
110 #define SECTION_ATTR_NONCACHED_MEM \
111 (SECTION_OUTER_NC_INNER_NC|SECTION_AP|DESC_DOMAIN(0))
112 #define SECTION_ATTR_DEVICE \
113 (SECTION_OUTER_NSD_INNER_NSD|SECTION_AP|SECTION_XN_ALL|DESC_DOMAIN(0))
114 #define SECTION_ATTR_DEVICE_EXEC \
115 (SECTION_OUTER_NSD_INNER_NSD|SECTION_AP|DESC_DOMAIN(0))
116
117 #define SCU_INV_CTRL_INIT 0xFFFF
118 #define SCU_SAC_CTRL_INIT 0xF
119 #define SCU_NSAC_CTRL_INIT 0xFFF
120 #define SCU_INV_SEC 0x0C
121 #define SCU_SAC 0x50
122 #define SCU_NSAC 0x54
123 #define SCU_CTRL 0x0
124
125 extern void a9_mmu_invalidate_tlb(void);
126 extern void a9_mmu_enable(void);
127 extern void a9_l1cache_enable_i(void);
128 extern void a9_l1cache_enable_d(void);
129 extern void a9_mmu_set_ttbr(char* table_base);
130 extern void a9_gic_secure_init(void);
131 extern void arm_cl2_invbyway(uint32_t);
132 /*
133 * Placeholder variables for copying the arguments that have been passed to
134 * BL31 from BL2.
135 */
136 static entry_point_info_t bl32_image_ep_info;
137 static entry_point_info_t bl33_image_ep_info;
138 static uintptr_t ns_entry_point;
139
140 #if defined (PLATFORM_FLAVOR_63138)
141 char mmu_table[1024*16] __attribute__((aligned(4096*4)));
142 #endif
143
144 const mmap_region_t plat_arm_mmap[] = {
145 MAP_REGION_FLAT(DEVICE_BASE, DEVICE_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
146 MAP_REGION_FLAT(GICD_BASE, DEVICE_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
147 #if UART0_BASE
148 MAP_REGION_FLAT(UART0_BASE, UART0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
149 #endif
150 #if defined(BIUCFG_BASE)
151 MAP_REGION_FLAT(BIUCFG_BASE, BIUCFG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
152 #elif defined(BIUCTRL_BASE)
153 MAP_REGION_FLAT(BIUCTRL_BASE, BIUCTRL_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
154 #endif
155 #if defined(BOOTLUT_BASE)
156 MAP_REGION_FLAT(BOOTLUT_BASE, BOOTLUT_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
157 #endif
158 #if defined(PL310_BASE)
159 MAP_REGION_FLAT(PL310_BASE, PL310_MAP_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
160 #endif
161 #if defined(B15_CTRL_BASE)
162 MAP_REGION_FLAT(B15_CTRL_BASE, B15_CTRL_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
163 #endif
164 #if defined(TIMR_BASE)
165 MAP_REGION_FLAT(TIMR_BASE, TIMR_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
166 #endif
167 MAP_REGION_FLAT(PMC_BASE, PMC_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
168 {0}
169 };
170
171
172 #if defined(PL310_BASE)
173 void a9_cl2_config(void)
174 {
175 /* Disable PL310 */
176 uint32_t pl310_base = PL310_BASE;
177 mmio_write_32(pl310_base + PL310_CTRL, 0);
178 mmio_write_32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT);
179 mmio_write_32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT);
180
181 /* invalidate all cache ways */
182 arm_cl2_invbyway(pl310_base);
183 }
184 #endif
185
186
187 /*******************************************************************************
188 * Return a pointer to the 'entry_point_info' structure of the next image for the
189 * security state specified. BL33 corresponds to the non-secure image type
190 * while BL32 corresponds to the secure image type. A NULL pointer is returned
191 * if the image does not exist.
192 ******************************************************************************/
193 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
194 {
195 entry_point_info_t *next_image_info;
196
197 assert(sec_state_is_valid(type));
198 next_image_info = (type == NON_SECURE)
199 ? &bl33_image_ep_info : &bl32_image_ep_info;
200 /*
201 * None of the images on the ARM development platforms can have 0x0
202 * as the entrypoint
203 */
204 if (next_image_info->pc)
205 return next_image_info;
206 else
207 return NULL;
208 }
209
210 /*******************************************************************************
211 * Obtain ns entry point
212 ******************************************************************************/
213 uintptr_t plat_get_ns_image_entrypoint(void)
214 {
215 return ns_entry_point;
216 }
217
218 /*******************************************************************************
219 * Set ns-entry point
220 ******************************************************************************/
221 void plat_set_ns_image_entrypoint(uintptr_t entry_point)
222 {
223 ns_entry_point = entry_point;
224 }
225
226 /*******************************************************************************
227 * Return a pointer to the 'entry_point_info' structure of the next image for the
228 * security state specified. BL33 corresponds to the non-secure image type
229 * while BL32 corresponds to the secure image type. A NULL pointer is returned
230 * if the image does not exist.
231 ******************************************************************************/
232 entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
233 {
234 entry_point_info_t *next_image_info;
235
236 next_image_info = &bl33_image_ep_info;
237
238 /*
239 * None of the images on the ARM development platforms can have 0x0
240 * as the entrypoint
241 */
242 if (next_image_info->pc)
243 return next_image_info;
244 else
245 return NULL;
246 }
247
248
249 void arm_sp_min_early_platform_setup ( void *plat_params, uintptr_t tos_fw_config,
250 uintptr_t hw_config, void *plat_params_from_bl2 )
251 {
252 bl31_params_t *from_bl2 = (bl31_params_t*)plat_params;
253
254 if (plat_my_core_pos() != 0){
255 plat_panic_handler();
256 }
257
258 #if defined(SCU_BASE)
259 mmio_write_32(SCU_BASE + SCU_INV_SEC, SCU_INV_CTRL_INIT);
260 mmio_write_32(SCU_BASE + SCU_SAC, SCU_SAC_CTRL_INIT);
261 mmio_write_32(SCU_BASE + SCU_NSAC, SCU_NSAC_CTRL_INIT);
262 /* SCU enable */
263 mmio_write_32(SCU_BASE + SCU_CTRL, 0x1);
264 #endif
265
266 #if defined(PL310_BASE)
267 a9_cl2_config();
268 #endif
269
270 /* Populate entry point information for BL32 */
271 SET_PARAM_HEAD(&bl32_image_ep_info,
272 PARAM_EP,
273 VERSION_1,
274 0);
275 SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
276 bl32_image_ep_info.pc = BL322_BASE;
277 bl32_image_ep_info.spsr = MODE32_svc << MODE32_SHIFT;
278 /* Provide boot parameters to OPTEE */
279 memset(&bl32_image_ep_info.args, 0, sizeof(aapcs32_params_t));
280 bl32_image_ep_info.args.arg0 = (u_register_t)plat_params_from_bl2;
281
282 /* Populate entry point information for BL33 */
283 SET_PARAM_HEAD(&bl33_image_ep_info,
284 PARAM_EP,
285 VERSION_1,
286 0);
287
288 /* Configure ns entry point */
289 plat_set_ns_image_entrypoint(from_bl2->bl33_ep_info->pc);
290
291 /*
292 * Tell SP_MIN where the non-trusted software image
293 * is located and the entry state information
294 */
295 bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
296 bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry() & ~(MODE32_MASK << MODE32_SHIFT);
297 /* Always enter in non-secure SVC mode */
298 bl33_image_ep_info.spsr |= MODE32_svc << MODE32_SHIFT;
299 SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
300 }
301
302 void sp_min_early_platform_setup(void *from_bl2,
303 void *plat_params_from_bl2)
304 {
305 arm_sp_min_early_platform_setup(from_bl2, 0, 0, plat_params_from_bl2);
306 }
307
308
309 void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
310 u_register_t arg2, u_register_t arg3)
311 {
312 sp_min_early_platform_setup((void *)arg0, (void *)arg1);
313 }
314
315 #define PLATFORM_G1S_PROPS(grp) \
316 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \
317 grp, GIC_INTR_CFG_LEVEL), \
318 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \
319 grp, GIC_INTR_CFG_LEVEL), \
320 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \
321 grp, GIC_INTR_CFG_LEVEL), \
322 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \
323 grp, GIC_INTR_CFG_LEVEL), \
324 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \
325 grp, GIC_INTR_CFG_LEVEL), \
326 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \
327 grp, GIC_INTR_CFG_LEVEL), \
328 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
329 grp, GIC_INTR_CFG_LEVEL), \
330 INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \
331 grp, GIC_INTR_CFG_LEVEL)
332
333 static const interrupt_prop_t irq_sec_array[] = {
334 PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0)
335 };
336
337 static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
338
339 const struct gicv2_driver_data plat_gicv2_driver_data = {
340 .gicd_base = GICD_BASE,
341 .gicc_base = GICC_BASE,
342 .interrupt_props = irq_sec_array,
343 .interrupt_props_num = ARRAY_SIZE(irq_sec_array),
344 .target_masks = target_mask_array,
345 .target_masks_num = ARRAY_SIZE(target_mask_array),
346 };
347
348 /*******************************************************************************
349 * Perform any BL32 platform setup common to ARM standard platforms
350 ******************************************************************************/
351 void arm_bl32_platform_setup(void)
352 {
353 #if defined (PLATFORM_FLAVOR_63138)
354 a9_gic_secure_init();
355 #else
356 /* Initialize the gic cpu and distributor interfaces */
357 gicv2_driver_init(&plat_gicv2_driver_data);
358 gicv2_distif_init();
359 gicv2_pcpu_distif_init();
360 gicv2_cpuif_enable();
361 #endif
362 }
363
364 /*******************************************************************************
365 * Perform any BL32 platform runtime setup prior to ARM standard platforms
366 ******************************************************************************/
367 void arm_bl32_plat_runtime_setup(void)
368 {
369 /* Initialize the runtime functions */
370 }
371
372 void sp_min_platform_setup(void)
373 {
374 arm_bl32_platform_setup();
375 }
376
377 void sp_min_runtime_setup(void)
378 {
379 arm_bl32_plat_runtime_setup();
380 }
381
382 #if defined (PLATFORM_FLAVOR_63138)
383 void a9_mmu_setup_region(uint32_t mem_addr, uint32_t mem_size, uint32_t mem_attr)
384 {
385 #define size_mb(s) ((s + 0xFFFFF) / 0x100000)
386 register uint32_t table_base = (uint32_t)mmu_table;
387 register uint32_t table_size = sizeof(mmu_table);
388
389 /* Align the address to MB and then adjust the size */
390 mem_size += mem_addr & 0xFFFFF;
391 mem_addr &= ~0xFFFFF;
392 /* Convert the mem size in MB */
393 mem_size = size_mb(mem_size);
394
395 __asm__ volatile ("mov r0, %0" : : "r" (table_size) : "r0");
396 __asm__ volatile ("push {r0}");
397 __asm__ volatile ("mov r0, %0" : : "r" (mem_addr) : "r0");
398 __asm__ volatile ("push {r0}");
399 __asm__ volatile ("mov r0, %0" : : "r" (mem_attr) : "r0");
400 __asm__ volatile ("push {r0}");
401 __asm__ volatile ("mov r0, %0" : : "r" (mem_size) : "r0");
402 __asm__ volatile ("push {r0}");
403 __asm__ volatile ("mov r0, %0" : : "r" (mem_addr) : "r0");
404 __asm__ volatile ("push {r0}");
405 __asm__ volatile ("mov r0, %0" : : "r" (table_base) : "r0");
406 __asm__ volatile ("push {r0}");
407 __asm__ volatile ("pop {r0-r4,r6}");
408
409 __asm__ volatile ("bl a9_mmu_set_scn" ::: "lr");
410 }
411
412 void a9_bl32_plat_map_mmu(void)
413 {
414 int i = 0;
415 int region_cnt = sizeof(plat_arm_mmap) / sizeof(mmap_region_t);
416 /* Initialize the mmu table */
417 memset(mmu_table, 0, sizeof(mmu_table));
418 /* Map the code/data section of ATF */
419 a9_mmu_setup_region(BL32_BASE, BL32_END - BL32_BASE, SECTION_ATTR_CACHED_MEM);
420 for (i = 0; i < region_cnt - 1; i++ ){
421 a9_mmu_setup_region((uint32_t)plat_arm_mmap[i].base_pa, plat_arm_mmap[i].size, SECTION_ATTR_DEVICE);
422 }
423 }
424
425 void a9_bl32_plat_enable_mmu(void)
426 {
427 a9_mmu_invalidate_tlb();
428 a9_mmu_set_ttbr (mmu_table);
429 a9_mmu_enable();
430 a9_l1cache_enable_i();
431 a9_l1cache_enable_d();
432 if (plat_my_core_pos() != 0){
433 mmio_write_32(PL310_BASE + PL310_CTRL, 1);
434 }
435 }
436 #endif
437
438 /*******************************************************************************
439 * Perform the very early platform specific architectural setup shared between
440 * ARM standard platforms. This only does basic initialization. Later
441 * architectural setup (bl31_arch_setup()) does not do anything platform
442 * specific.
443 ******************************************************************************/
444 void arm_bl32_plat_arch_setup(void)
445 {
446 #if defined (PLATFORM_FLAVOR_63138)
447 a9_bl32_plat_map_mmu();
448 a9_bl32_plat_enable_mmu();
449 #else
450 const mmap_region_t bl_regions[] = {
451 MAP_BL_SP_MIN_TOTAL,
452 ARM_MAP_BL_RO,
453 #if USE_COHERENT_MEM
454 ARM_MAP_BL_COHERENT_RAM,
455 #endif
456 {0}
457 };
458
459 generic_delay_timer_init();
460
461 setup_page_tables(bl_regions, plat_arm_get_mmap());
462
463 enable_mmu_svc_mon(0);
464 #endif
465
466 #if defined(BIUCFG_BASE) && !(defined (PLATFORM_FLAVOR_63138) || defined (PLATFORM_FLAVOR_63148))
467 /* Enable BUS access control for non-secure Linux */
468 *(unsigned int*)(BIUCFG_BASE + 0x300) = 0xFF;
469 #endif
470 }
471
472 void sp_min_plat_arch_setup(void)
473 {
474 arm_bl32_plat_arch_setup();
475 }
476
477 unsigned int plat_get_syscnt_freq2(void)
478 {
479 return SYS_COUNTER_FREQ_IN_TICKS;
480 }
481
482 int plat_bcm_calc_core_pos(int mpidr)
483 {
484 return plat_arm_calc_core_pos(mpidr);
485 }