2 <:copyright-BRCM:2019:DUAL/GPL:standard
4 Copyright (c) 2019 Broadcom
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").
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.
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.
25 #include <arch_helpers.h>
27 #include <bl_common.h>
35 #include <generic_delay_timer.h>
36 #include <delay_timer.h>
38 #define MAP_BL_SP_MIN_TOTAL MAP_REGION_FLAT( \
40 BL32_END - BL32_BASE, \
41 MT_MEMORY | MT_RW | MT_SECURE)
43 #define ARM_MAP_BL_RO MAP_REGION_FLAT( \
45 BL_CODE_END - BL_CODE_BASE, \
48 #define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
49 BL_COHERENT_RAM_BASE, \
51 - BL_COHERENT_RAM_BASE, \
52 MT_DEVICE | MT_RW | MT_SECURE)
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 */
60 struct atf_entry_point_info
{
61 struct param_header h
;
64 struct aapcs64_params args
;
67 typedef struct bl31_params
{
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
;
77 #define BL32_END (uintptr_t)(&__BL32_END__)
78 #define DEVICE_BASE 0x80000000
79 #define DEVICE_SIZE 0x00010000
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)
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
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))
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
122 #define SCU_NSAC 0x54
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);
133 * Placeholder variables for copying the arguments that have been passed to
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
;
140 #if defined (PLATFORM_FLAVOR_63138)
141 char mmu_table
[1024*16] __attribute__((aligned(4096*4)));
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
),
148 MAP_REGION_FLAT(UART0_BASE
, UART0_SIZE
, MT_DEVICE
| MT_RW
| MT_SECURE
),
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
),
155 #if defined(BOOTLUT_BASE)
156 MAP_REGION_FLAT(BOOTLUT_BASE
, BOOTLUT_SIZE
, MT_DEVICE
| MT_RW
| MT_SECURE
),
158 #if defined(PL310_BASE)
159 MAP_REGION_FLAT(PL310_BASE
, PL310_MAP_SIZE
, MT_DEVICE
| MT_RW
| MT_SECURE
),
161 #if defined(B15_CTRL_BASE)
162 MAP_REGION_FLAT(B15_CTRL_BASE
, B15_CTRL_SIZE
, MT_DEVICE
| MT_RW
| MT_SECURE
),
164 #if defined(TIMR_BASE)
165 MAP_REGION_FLAT(TIMR_BASE
, TIMR_SIZE
, MT_DEVICE
| MT_RW
| MT_SECURE
),
167 MAP_REGION_FLAT(PMC_BASE
, PMC_SIZE
, MT_DEVICE
| MT_RW
| MT_SECURE
),
172 #if defined(PL310_BASE)
173 void a9_cl2_config(void)
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
);
181 /* invalidate all cache ways */
182 arm_cl2_invbyway(pl310_base
);
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
)
195 entry_point_info_t
*next_image_info
;
197 assert(sec_state_is_valid(type
));
198 next_image_info
= (type
== NON_SECURE
)
199 ? &bl33_image_ep_info
: &bl32_image_ep_info
;
201 * None of the images on the ARM development platforms can have 0x0
204 if (next_image_info
->pc
)
205 return next_image_info
;
210 /*******************************************************************************
211 * Obtain ns entry point
212 ******************************************************************************/
213 uintptr_t plat_get_ns_image_entrypoint(void)
215 return ns_entry_point
;
218 /*******************************************************************************
220 ******************************************************************************/
221 void plat_set_ns_image_entrypoint(uintptr_t entry_point
)
223 ns_entry_point
= entry_point
;
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)
234 entry_point_info_t
*next_image_info
;
236 next_image_info
= &bl33_image_ep_info
;
239 * None of the images on the ARM development platforms can have 0x0
242 if (next_image_info
->pc
)
243 return next_image_info
;
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
)
252 bl31_params_t
*from_bl2
= (bl31_params_t
*)plat_params
;
254 if (plat_my_core_pos() != 0){
255 plat_panic_handler();
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
);
263 mmio_write_32(SCU_BASE
+ SCU_CTRL
, 0x1);
266 #if defined(PL310_BASE)
270 /* Populate entry point information for BL32 */
271 SET_PARAM_HEAD(&bl32_image_ep_info
,
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
;
282 /* Populate entry point information for BL33 */
283 SET_PARAM_HEAD(&bl33_image_ep_info
,
288 /* Configure ns entry point */
289 plat_set_ns_image_entrypoint(from_bl2
->bl33_ep_info
->pc
);
292 * Tell SP_MIN where the non-trusted software image
293 * is located and the entry state information
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
);
302 void sp_min_early_platform_setup(void *from_bl2
,
303 void *plat_params_from_bl2
)
305 arm_sp_min_early_platform_setup(from_bl2
, 0, 0, plat_params_from_bl2
);
309 void sp_min_early_platform_setup2(u_register_t arg0
, u_register_t arg1
,
310 u_register_t arg2
, u_register_t arg3
)
312 sp_min_early_platform_setup((void *)arg0
, (void *)arg1
);
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)
333 static const interrupt_prop_t irq_sec_array
[] = {
334 PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0
)
337 static unsigned int target_mask_array
[PLATFORM_CORE_COUNT
];
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
),
348 /*******************************************************************************
349 * Perform any BL32 platform setup common to ARM standard platforms
350 ******************************************************************************/
351 void arm_bl32_platform_setup(void)
353 #if defined (PLATFORM_FLAVOR_63138)
354 a9_gic_secure_init();
356 /* Initialize the gic cpu and distributor interfaces */
357 gicv2_driver_init(&plat_gicv2_driver_data
);
359 gicv2_pcpu_distif_init();
360 gicv2_cpuif_enable();
364 /*******************************************************************************
365 * Perform any BL32 platform runtime setup prior to ARM standard platforms
366 ******************************************************************************/
367 void arm_bl32_plat_runtime_setup(void)
369 /* Initialize the runtime functions */
372 void sp_min_platform_setup(void)
374 arm_bl32_platform_setup();
377 void sp_min_runtime_setup(void)
379 arm_bl32_plat_runtime_setup();
382 #if defined (PLATFORM_FLAVOR_63138)
383 void a9_mmu_setup_region(uint32_t mem_addr
, uint32_t mem_size
, uint32_t mem_attr
)
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
);
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
);
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}");
409 __asm__
volatile ("bl a9_mmu_set_scn" ::: "lr");
412 void a9_bl32_plat_map_mmu(void)
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
);
425 void a9_bl32_plat_enable_mmu(void)
427 a9_mmu_invalidate_tlb();
428 a9_mmu_set_ttbr (mmu_table
);
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);
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
443 ******************************************************************************/
444 void arm_bl32_plat_arch_setup(void)
446 #if defined (PLATFORM_FLAVOR_63138)
447 a9_bl32_plat_map_mmu();
448 a9_bl32_plat_enable_mmu();
450 const mmap_region_t bl_regions
[] = {
454 ARM_MAP_BL_COHERENT_RAM
,
459 generic_delay_timer_init();
461 setup_page_tables(bl_regions
, plat_arm_get_mmap());
463 enable_mmu_svc_mon(0);
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;
472 void sp_min_plat_arch_setup(void)
474 arm_bl32_plat_arch_setup();
477 unsigned int plat_get_syscnt_freq2(void)
479 return SYS_COUNTER_FREQ_IN_TICKS
;
482 int plat_bcm_calc_core_pos(int mpidr
)
484 return plat_arm_calc_core_pos(mpidr
);