17931d332SJit Loon Lim /* 2998da640SHarrison Mutai * Copyright (c) 2019-2024, ARM Limited and Contributors. All rights reserved. 37931d332SJit Loon Lim * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 429d1e29dSJit Loon Lim * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. 57931d332SJit Loon Lim * 67931d332SJit Loon Lim * SPDX-License-Identifier: BSD-3-Clause 77931d332SJit Loon Lim */ 87931d332SJit Loon Lim 97931d332SJit Loon Lim #include <assert.h> 107931d332SJit Loon Lim #include <arch.h> 117931d332SJit Loon Lim #include <arch_helpers.h> 127931d332SJit Loon Lim #include <common/bl_common.h> 137931d332SJit Loon Lim #include <drivers/arm/gic_common.h> 147931d332SJit Loon Lim #include <drivers/arm/gicv3.h> 157931d332SJit Loon Lim #include <drivers/ti/uart/uart_16550.h> 167931d332SJit Loon Lim #include <lib/mmio.h> 177931d332SJit Loon Lim #include <lib/xlat_tables/xlat_mmu_helpers.h> 187931d332SJit Loon Lim #include <lib/xlat_tables/xlat_tables_v2.h> 197931d332SJit Loon Lim #include <plat/common/platform.h> 207931d332SJit Loon Lim 213c640c12STanmay Kathpalia #include "agilex5_cache.h" 227931d332SJit Loon Lim #include "agilex5_power_manager.h" 237931d332SJit Loon Lim #include "ccu/ncore_ccu.h" 2429d1e29dSJit Loon Lim #include "socfpga_dt.h" 257931d332SJit Loon Lim #include "socfpga_mailbox.h" 267931d332SJit Loon Lim #include "socfpga_private.h" 277931d332SJit Loon Lim #include "socfpga_reset_manager.h" 287931d332SJit Loon Lim 297931d332SJit Loon Lim /* Get non-secure SPSR for BL33. Zephyr and Linux */ 307931d332SJit Loon Lim uint32_t arm_get_spsr_for_bl33_entry(void); 317931d332SJit Loon Lim 327931d332SJit Loon Lim static entry_point_info_t bl32_image_ep_info; 337931d332SJit Loon Lim static entry_point_info_t bl33_image_ep_info; 347931d332SJit Loon Lim 357931d332SJit Loon Lim /* The GICv3 driver only needs to be initialized in EL3 */ 367931d332SJit Loon Lim static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 377931d332SJit Loon Lim 387931d332SJit Loon Lim #define SMMU_SDMMC 397931d332SJit Loon Lim 407931d332SJit Loon Lim entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) 417931d332SJit Loon Lim { 427931d332SJit Loon Lim entry_point_info_t *next_image_info; 437931d332SJit Loon Lim 447931d332SJit Loon Lim next_image_info = (type == NON_SECURE) ? 457931d332SJit Loon Lim &bl33_image_ep_info : &bl32_image_ep_info; 467931d332SJit Loon Lim 477931d332SJit Loon Lim /* None of the images on this platform can have 0x0 as the entrypoint */ 487931d332SJit Loon Lim if (next_image_info->pc) 497931d332SJit Loon Lim return next_image_info; 507931d332SJit Loon Lim else 517931d332SJit Loon Lim return NULL; 527931d332SJit Loon Lim } 537931d332SJit Loon Lim 547931d332SJit Loon Lim void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, 557931d332SJit Loon Lim u_register_t arg2, u_register_t arg3) 567931d332SJit Loon Lim { 577931d332SJit Loon Lim static console_t console; 587931d332SJit Loon Lim 597931d332SJit Loon Lim mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY); 607931d332SJit Loon Lim 617931d332SJit Loon Lim console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK, 627931d332SJit Loon Lim PLAT_BAUDRATE, &console); 637931d332SJit Loon Lim 647931d332SJit Loon Lim setup_smmu_stream_id(); 657931d332SJit Loon Lim 667931d332SJit Loon Lim /* 677931d332SJit Loon Lim * Check params passed from BL31 should not be NULL, 687931d332SJit Loon Lim */ 697931d332SJit Loon Lim void *from_bl2 = (void *) arg0; 707931d332SJit Loon Lim 717931d332SJit Loon Lim #if RESET_TO_BL31 727931d332SJit Loon Lim /* There are no parameters from BL2 if BL31 is a reset vector */ 737931d332SJit Loon Lim assert(from_bl2 == NULL); 747931d332SJit Loon Lim void *plat_params_from_bl2 = (void *) arg3; 757931d332SJit Loon Lim 767931d332SJit Loon Lim assert(plat_params_from_bl2 == NULL); 777931d332SJit Loon Lim 787931d332SJit Loon Lim /* Populate entry point information for BL33 */ 797931d332SJit Loon Lim SET_PARAM_HEAD(&bl33_image_ep_info, 807931d332SJit Loon Lim PARAM_EP, 817931d332SJit Loon Lim VERSION_1, 827931d332SJit Loon Lim 0); 837931d332SJit Loon Lim 847931d332SJit Loon Lim # if ARM_LINUX_KERNEL_AS_BL33 857931d332SJit Loon Lim /* 867931d332SJit Loon Lim * According to the file ``Documentation/arm64/booting.txt`` of the 877931d332SJit Loon Lim * Linux kernel tree, Linux expects the physical address of the device 887931d332SJit Loon Lim * tree blob (DTB) in x0, while x1-x3 are reserved for future use and 897931d332SJit Loon Lim * must be 0. 907931d332SJit Loon Lim */ 917931d332SJit Loon Lim bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; 927931d332SJit Loon Lim bl33_image_ep_info.args.arg1 = 0U; 937931d332SJit Loon Lim bl33_image_ep_info.args.arg2 = 0U; 947931d332SJit Loon Lim bl33_image_ep_info.args.arg3 = 0U; 957931d332SJit Loon Lim # endif 967931d332SJit Loon Lim 977931d332SJit Loon Lim #else /* RESET_TO_BL31 */ 987931d332SJit Loon Lim bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; 997931d332SJit Loon Lim 1007931d332SJit Loon Lim assert(params_from_bl2 != NULL); 1017931d332SJit Loon Lim 1027931d332SJit Loon Lim /* 1037931d332SJit Loon Lim * Copy BL32 (if populated by BL31) and BL33 entry point information. 1047931d332SJit Loon Lim * They are stored in Secure RAM, in BL31's address space. 1057931d332SJit Loon Lim */ 1067931d332SJit Loon Lim 1077931d332SJit Loon Lim if (params_from_bl2->h.type == PARAM_BL_PARAMS && 1087931d332SJit Loon Lim params_from_bl2->h.version >= VERSION_2) { 1097931d332SJit Loon Lim 1107931d332SJit Loon Lim bl_params_node_t *bl_params = params_from_bl2->head; 1117931d332SJit Loon Lim 1127931d332SJit Loon Lim while (bl_params) { 1137931d332SJit Loon Lim if (bl_params->image_id == BL33_IMAGE_ID) { 1147931d332SJit Loon Lim bl33_image_ep_info = *bl_params->ep_info; 1157931d332SJit Loon Lim } 1167931d332SJit Loon Lim bl_params = bl_params->next_params_info; 1177931d332SJit Loon Lim } 1187931d332SJit Loon Lim } else { 1197931d332SJit Loon Lim struct socfpga_bl31_params *arg_from_bl2 = 1207931d332SJit Loon Lim (struct socfpga_bl31_params *) from_bl2; 1217931d332SJit Loon Lim 1227931d332SJit Loon Lim assert(arg_from_bl2->h.type == PARAM_BL31); 1237931d332SJit Loon Lim assert(arg_from_bl2->h.version >= VERSION_1); 1247931d332SJit Loon Lim 1257931d332SJit Loon Lim bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; 1267931d332SJit Loon Lim bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; 1277931d332SJit Loon Lim } 1287931d332SJit Loon Lim 1297931d332SJit Loon Lim bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; 1307931d332SJit Loon Lim bl33_image_ep_info.args.arg1 = 0U; 1317931d332SJit Loon Lim bl33_image_ep_info.args.arg2 = 0U; 1327931d332SJit Loon Lim bl33_image_ep_info.args.arg3 = 0U; 1337931d332SJit Loon Lim #endif 1347931d332SJit Loon Lim 1357931d332SJit Loon Lim /* 1367931d332SJit Loon Lim * Tell BL31 where the non-trusted software image 1377931d332SJit Loon Lim * is located and the entry state information 1387931d332SJit Loon Lim */ 1397931d332SJit Loon Lim bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); 1407931d332SJit Loon Lim bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); 1417931d332SJit Loon Lim 1427931d332SJit Loon Lim SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); 1437931d332SJit Loon Lim } 1447931d332SJit Loon Lim 1457931d332SJit Loon Lim static const interrupt_prop_t agx5_interrupt_props[] = { 1467931d332SJit Loon Lim PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(INTR_GROUP1S), 1477931d332SJit Loon Lim PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(INTR_GROUP0) 1487931d332SJit Loon Lim }; 1497931d332SJit Loon Lim 15029d1e29dSJit Loon Lim gicv3_driver_data_t plat_gicv3_gic_data = { 1517931d332SJit Loon Lim .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, 1527931d332SJit Loon Lim .gicr_base = PLAT_INTEL_SOCFPGA_GICR_BASE, 1537931d332SJit Loon Lim .interrupt_props = agx5_interrupt_props, 1547931d332SJit Loon Lim .interrupt_props_num = ARRAY_SIZE(agx5_interrupt_props), 1557931d332SJit Loon Lim .rdistif_num = PLATFORM_CORE_COUNT, 1567931d332SJit Loon Lim .rdistif_base_addrs = rdistif_base_addrs, 1577931d332SJit Loon Lim }; 1587931d332SJit Loon Lim 1597931d332SJit Loon Lim /******************************************************************************* 1607931d332SJit Loon Lim * Perform any BL3-1 platform setup code 1617931d332SJit Loon Lim ******************************************************************************/ 1627931d332SJit Loon Lim void bl31_platform_setup(void) 1637931d332SJit Loon Lim { 1647931d332SJit Loon Lim socfpga_delay_timer_init(); 1657931d332SJit Loon Lim 16629d1e29dSJit Loon Lim /* TODO: DTB not available */ 16729d1e29dSJit Loon Lim // socfpga_dt_populate_gicv3_config(SOCFPGA_DTB_BASE, &plat_gicv3_gic_data); 16829d1e29dSJit Loon Lim // NOTICE("SOCFPGA: GIC GICD base address 0x%lx\n", plat_gicv3_gic_data.gicd_base); 16929d1e29dSJit Loon Lim // NOTICE("SOCFPGA: GIC GICR base address 0x%lx\n", plat_gicv3_gic_data.gicr_base); 17029d1e29dSJit Loon Lim 1717931d332SJit Loon Lim /* Initialize the gic cpu and distributor interfaces */ 1727931d332SJit Loon Lim gicv3_driver_init(&plat_gicv3_gic_data); 1737931d332SJit Loon Lim gicv3_distif_init(); 1747931d332SJit Loon Lim gicv3_rdistif_init(plat_my_core_pos()); 1757931d332SJit Loon Lim gicv3_cpuif_enable(plat_my_core_pos()); 176*204d5e67SSieu Mun Tang 177*204d5e67SSieu Mun Tang #if SIP_SVC_V3 178*204d5e67SSieu Mun Tang /* 179*204d5e67SSieu Mun Tang * Re-initialize the mailbox to include V3 specific routines. 180*204d5e67SSieu Mun Tang * In V3, this re-initialize is required because prior to BL31, U-Boot 181*204d5e67SSieu Mun Tang * SPL has its own mailbox settings and this initialization will 182*204d5e67SSieu Mun Tang * override to those settings as required by the V3 framework. 183*204d5e67SSieu Mun Tang */ 184*204d5e67SSieu Mun Tang mailbox_init(); 185*204d5e67SSieu Mun Tang #endif 186*204d5e67SSieu Mun Tang 1877931d332SJit Loon Lim mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); 1887931d332SJit Loon Lim } 1897931d332SJit Loon Lim 1907931d332SJit Loon Lim const mmap_region_t plat_agilex_mmap[] = { 1917931d332SJit Loon Lim MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), 1927931d332SJit Loon Lim MAP_REGION_FLAT(PSS_BASE, PSS_SIZE, MT_DEVICE | MT_RW | MT_NS), 1937931d332SJit Loon Lim MAP_REGION_FLAT(MPFE_BASE, MPFE_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1947931d332SJit Loon Lim MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, MT_NON_CACHEABLE | MT_RW | MT_SECURE), 1957931d332SJit Loon Lim MAP_REGION_FLAT(CCU_BASE, CCU_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1967931d332SJit Loon Lim MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS), 1977931d332SJit Loon Lim MAP_REGION_FLAT(GIC_BASE, GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1987931d332SJit Loon Lim {0} 1997931d332SJit Loon Lim }; 2007931d332SJit Loon Lim 2017931d332SJit Loon Lim /******************************************************************************* 2027931d332SJit Loon Lim * Perform the very early platform specific architectural setup here. At the 203998da640SHarrison Mutai * moment this is only initializes the mmu in a quick and dirty way. 2047931d332SJit Loon Lim ******************************************************************************/ 2057931d332SJit Loon Lim void bl31_plat_arch_setup(void) 2067931d332SJit Loon Lim { 2077931d332SJit Loon Lim uint32_t boot_core = 0x00; 2087931d332SJit Loon Lim uint32_t cpuid = 0x00; 2097931d332SJit Loon Lim 210b3d28508SSieu Mun Tang cpuid = MPIDR_AFFLVL1_VAL(read_mpidr()); 211b3d28508SSieu Mun Tang boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10); 21229d1e29dSJit Loon Lim NOTICE("SOCFPGA: Boot Core = %x\n", boot_core); 21329d1e29dSJit Loon Lim NOTICE("SOCFPGA: CPU ID = %x\n", cpuid); 21429d1e29dSJit Loon Lim INFO("SOCFPGA: Invalidate Data cache\n"); 2153c640c12STanmay Kathpalia invalidate_dcache_all(); 216bf3877e0SSieu Mun Tang 217bf3877e0SSieu Mun Tang /* Invalidate for NS EL2 and EL1 */ 218bf3877e0SSieu Mun Tang invalidate_cache_low_el(); 2197931d332SJit Loon Lim } 2207931d332SJit Loon Lim 2217931d332SJit Loon Lim /* Get non-secure image entrypoint for BL33. Zephyr and Linux */ 2227931d332SJit Loon Lim uintptr_t plat_get_ns_image_entrypoint(void) 2237931d332SJit Loon Lim { 2247931d332SJit Loon Lim #ifdef PRELOADED_BL33_BASE 2257931d332SJit Loon Lim return PRELOADED_BL33_BASE; 2267931d332SJit Loon Lim #else 2277931d332SJit Loon Lim return PLAT_NS_IMAGE_OFFSET; 2287931d332SJit Loon Lim #endif 2297931d332SJit Loon Lim } 2307931d332SJit Loon Lim 2317931d332SJit Loon Lim /* Get non-secure SPSR for BL33. Zephyr and Linux */ 2327931d332SJit Loon Lim uint32_t arm_get_spsr_for_bl33_entry(void) 2337931d332SJit Loon Lim { 2347931d332SJit Loon Lim unsigned int mode; 2357931d332SJit Loon Lim uint32_t spsr; 2367931d332SJit Loon Lim 2377931d332SJit Loon Lim /* Figure out what mode we enter the non-secure world in */ 2387931d332SJit Loon Lim mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; 2397931d332SJit Loon Lim 2407931d332SJit Loon Lim /* 2417931d332SJit Loon Lim * TODO: Consider the possibility of specifying the SPSR in 2427931d332SJit Loon Lim * the FIP ToC and allowing the platform to have a say as 2437931d332SJit Loon Lim * well. 2447931d332SJit Loon Lim */ 2457931d332SJit Loon Lim spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 2467931d332SJit Loon Lim return spsr; 2477931d332SJit Loon Lim } 2487931d332SJit Loon Lim 2497931d332SJit Loon Lim /* SMP: Secondary cores BL31 setup reset vector */ 2507931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_entrypoint(unsigned int cpu_id) 2517931d332SJit Loon Lim { 2527931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2537931d332SJit Loon Lim unsigned int pchctlr_old = 0x00; 2547931d332SJit Loon Lim unsigned int pchctlr_new = 0x00; 2557931d332SJit Loon Lim uint32_t boot_core = 0x00; 2567931d332SJit Loon Lim 257646a9a16SJit Loon Lim /* Set bit for SMP secondary cores boot */ 258646a9a16SJit Loon Lim mmio_clrsetbits_32(L2_RESET_DONE_REG, BS_REG_MAGIC_KEYS_MASK, 259646a9a16SJit Loon Lim SMP_SEC_CORE_BOOT_REQ); 2607931d332SJit Loon Lim boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00); 2617931d332SJit Loon Lim /* Update the p-channel based on cpu id */ 2627931d332SJit Loon Lim pch_cpu = 1 << cpu_id; 2637931d332SJit Loon Lim 2647931d332SJit Loon Lim if (boot_core == 0x00) { 2657931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2667931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU2, 2677931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2687931d332SJit Loon Lim } else { 2697931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2707931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU0, 2717931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2727931d332SJit Loon Lim } 2737931d332SJit Loon Lim 2747931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2757931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU1, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2767931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU3, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2777931d332SJit Loon Lim 2787931d332SJit Loon Lim /* On all cores - temporary */ 2797931d332SJit Loon Lim pchctlr_old = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2807931d332SJit Loon Lim pchctlr_new = pchctlr_old | (pch_cpu<<1); 2817931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pchctlr_new); 2827931d332SJit Loon Lim 2837931d332SJit Loon Lim /* We will only release the target secondary CPUs */ 2847931d332SJit Loon Lim /* Bit mask for each CPU BIT0-3 */ 2857931d332SJit Loon Lim mmio_write_32(RSTMGR_CPUSTRELEASE_CPUx, pch_cpu); 2867931d332SJit Loon Lim } 2877931d332SJit Loon Lim 2887931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_off(void) 2897931d332SJit Loon Lim { 2907931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2917931d332SJit Loon Lim unsigned int pch_cpu_off = 0x00; 2927931d332SJit Loon Lim unsigned int cpu_id = plat_my_core_pos(); 2937931d332SJit Loon Lim 2947931d332SJit Loon Lim pch_cpu_off = 1 << cpu_id; 2957931d332SJit Loon Lim 2967931d332SJit Loon Lim pch_cpu = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2977931d332SJit Loon Lim pch_cpu = pch_cpu & ~(pch_cpu_off << 1); 2987931d332SJit Loon Lim 2997931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu); 3007931d332SJit Loon Lim } 3017931d332SJit Loon Lim 30229d1e29dSJit Loon Lim void bl31_plat_runtime_setup(void) 30329d1e29dSJit Loon Lim { 30429d1e29dSJit Loon Lim console_switch_state(CONSOLE_FLAG_RUNTIME|CONSOLE_FLAG_BOOT); 30529d1e29dSJit Loon Lim } 30629d1e29dSJit Loon Lim 3077931d332SJit Loon Lim void bl31_plat_enable_mmu(uint32_t flags) 3087931d332SJit Loon Lim { 3097931d332SJit Loon Lim /* TODO: Enable mmu when needed */ 3107931d332SJit Loon Lim } 311