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. 43c640c12STanmay Kathpalia * Copyright (c) 2024, 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" 247931d332SJit Loon Lim #include "socfpga_mailbox.h" 257931d332SJit Loon Lim #include "socfpga_private.h" 267931d332SJit Loon Lim #include "socfpga_reset_manager.h" 277931d332SJit Loon Lim 287931d332SJit Loon Lim /* Get non-secure SPSR for BL33. Zephyr and Linux */ 297931d332SJit Loon Lim uint32_t arm_get_spsr_for_bl33_entry(void); 307931d332SJit Loon Lim 317931d332SJit Loon Lim static entry_point_info_t bl32_image_ep_info; 327931d332SJit Loon Lim static entry_point_info_t bl33_image_ep_info; 337931d332SJit Loon Lim 347931d332SJit Loon Lim /* The GICv3 driver only needs to be initialized in EL3 */ 357931d332SJit Loon Lim static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 367931d332SJit Loon Lim 377931d332SJit Loon Lim #define SMMU_SDMMC 387931d332SJit Loon Lim 397931d332SJit Loon Lim entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) 407931d332SJit Loon Lim { 417931d332SJit Loon Lim entry_point_info_t *next_image_info; 427931d332SJit Loon Lim 437931d332SJit Loon Lim next_image_info = (type == NON_SECURE) ? 447931d332SJit Loon Lim &bl33_image_ep_info : &bl32_image_ep_info; 457931d332SJit Loon Lim 467931d332SJit Loon Lim /* None of the images on this platform can have 0x0 as the entrypoint */ 477931d332SJit Loon Lim if (next_image_info->pc) 487931d332SJit Loon Lim return next_image_info; 497931d332SJit Loon Lim else 507931d332SJit Loon Lim return NULL; 517931d332SJit Loon Lim } 527931d332SJit Loon Lim 537931d332SJit Loon Lim void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, 547931d332SJit Loon Lim u_register_t arg2, u_register_t arg3) 557931d332SJit Loon Lim { 567931d332SJit Loon Lim static console_t console; 577931d332SJit Loon Lim 587931d332SJit Loon Lim mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY); 597931d332SJit Loon Lim 607931d332SJit Loon Lim console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK, 617931d332SJit Loon Lim PLAT_BAUDRATE, &console); 627931d332SJit Loon Lim 637931d332SJit Loon Lim setup_smmu_stream_id(); 647931d332SJit Loon Lim 657931d332SJit Loon Lim /* 667931d332SJit Loon Lim * Check params passed from BL31 should not be NULL, 677931d332SJit Loon Lim */ 687931d332SJit Loon Lim void *from_bl2 = (void *) arg0; 697931d332SJit Loon Lim 707931d332SJit Loon Lim #if RESET_TO_BL31 717931d332SJit Loon Lim /* There are no parameters from BL2 if BL31 is a reset vector */ 727931d332SJit Loon Lim assert(from_bl2 == NULL); 737931d332SJit Loon Lim void *plat_params_from_bl2 = (void *) arg3; 747931d332SJit Loon Lim 757931d332SJit Loon Lim assert(plat_params_from_bl2 == NULL); 767931d332SJit Loon Lim 777931d332SJit Loon Lim /* Populate entry point information for BL33 */ 787931d332SJit Loon Lim SET_PARAM_HEAD(&bl33_image_ep_info, 797931d332SJit Loon Lim PARAM_EP, 807931d332SJit Loon Lim VERSION_1, 817931d332SJit Loon Lim 0); 827931d332SJit Loon Lim 837931d332SJit Loon Lim # if ARM_LINUX_KERNEL_AS_BL33 847931d332SJit Loon Lim /* 857931d332SJit Loon Lim * According to the file ``Documentation/arm64/booting.txt`` of the 867931d332SJit Loon Lim * Linux kernel tree, Linux expects the physical address of the device 877931d332SJit Loon Lim * tree blob (DTB) in x0, while x1-x3 are reserved for future use and 887931d332SJit Loon Lim * must be 0. 897931d332SJit Loon Lim */ 907931d332SJit Loon Lim bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; 917931d332SJit Loon Lim bl33_image_ep_info.args.arg1 = 0U; 927931d332SJit Loon Lim bl33_image_ep_info.args.arg2 = 0U; 937931d332SJit Loon Lim bl33_image_ep_info.args.arg3 = 0U; 947931d332SJit Loon Lim # endif 957931d332SJit Loon Lim 967931d332SJit Loon Lim #else /* RESET_TO_BL31 */ 977931d332SJit Loon Lim bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; 987931d332SJit Loon Lim 997931d332SJit Loon Lim assert(params_from_bl2 != NULL); 1007931d332SJit Loon Lim 1017931d332SJit Loon Lim /* 1027931d332SJit Loon Lim * Copy BL32 (if populated by BL31) and BL33 entry point information. 1037931d332SJit Loon Lim * They are stored in Secure RAM, in BL31's address space. 1047931d332SJit Loon Lim */ 1057931d332SJit Loon Lim 1067931d332SJit Loon Lim if (params_from_bl2->h.type == PARAM_BL_PARAMS && 1077931d332SJit Loon Lim params_from_bl2->h.version >= VERSION_2) { 1087931d332SJit Loon Lim 1097931d332SJit Loon Lim bl_params_node_t *bl_params = params_from_bl2->head; 1107931d332SJit Loon Lim 1117931d332SJit Loon Lim while (bl_params) { 1127931d332SJit Loon Lim if (bl_params->image_id == BL33_IMAGE_ID) { 1137931d332SJit Loon Lim bl33_image_ep_info = *bl_params->ep_info; 1147931d332SJit Loon Lim } 1157931d332SJit Loon Lim bl_params = bl_params->next_params_info; 1167931d332SJit Loon Lim } 1177931d332SJit Loon Lim } else { 1187931d332SJit Loon Lim struct socfpga_bl31_params *arg_from_bl2 = 1197931d332SJit Loon Lim (struct socfpga_bl31_params *) from_bl2; 1207931d332SJit Loon Lim 1217931d332SJit Loon Lim assert(arg_from_bl2->h.type == PARAM_BL31); 1227931d332SJit Loon Lim assert(arg_from_bl2->h.version >= VERSION_1); 1237931d332SJit Loon Lim 1247931d332SJit Loon Lim bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; 1257931d332SJit Loon Lim bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; 1267931d332SJit Loon Lim } 1277931d332SJit Loon Lim 1287931d332SJit Loon Lim bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; 1297931d332SJit Loon Lim bl33_image_ep_info.args.arg1 = 0U; 1307931d332SJit Loon Lim bl33_image_ep_info.args.arg2 = 0U; 1317931d332SJit Loon Lim bl33_image_ep_info.args.arg3 = 0U; 1327931d332SJit Loon Lim #endif 1337931d332SJit Loon Lim 1347931d332SJit Loon Lim /* 1357931d332SJit Loon Lim * Tell BL31 where the non-trusted software image 1367931d332SJit Loon Lim * is located and the entry state information 1377931d332SJit Loon Lim */ 1387931d332SJit Loon Lim bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); 1397931d332SJit Loon Lim bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); 1407931d332SJit Loon Lim 1417931d332SJit Loon Lim SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); 1427931d332SJit Loon Lim } 1437931d332SJit Loon Lim 1447931d332SJit Loon Lim static const interrupt_prop_t agx5_interrupt_props[] = { 1457931d332SJit Loon Lim PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(INTR_GROUP1S), 1467931d332SJit Loon Lim PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(INTR_GROUP0) 1477931d332SJit Loon Lim }; 1487931d332SJit Loon Lim 1497931d332SJit Loon Lim static const gicv3_driver_data_t plat_gicv3_gic_data = { 1507931d332SJit Loon Lim .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, 1517931d332SJit Loon Lim .gicr_base = PLAT_INTEL_SOCFPGA_GICR_BASE, 1527931d332SJit Loon Lim .interrupt_props = agx5_interrupt_props, 1537931d332SJit Loon Lim .interrupt_props_num = ARRAY_SIZE(agx5_interrupt_props), 1547931d332SJit Loon Lim .rdistif_num = PLATFORM_CORE_COUNT, 1557931d332SJit Loon Lim .rdistif_base_addrs = rdistif_base_addrs, 1567931d332SJit Loon Lim }; 1577931d332SJit Loon Lim 1587931d332SJit Loon Lim /******************************************************************************* 1597931d332SJit Loon Lim * Perform any BL3-1 platform setup code 1607931d332SJit Loon Lim ******************************************************************************/ 1617931d332SJit Loon Lim void bl31_platform_setup(void) 1627931d332SJit Loon Lim { 1637931d332SJit Loon Lim socfpga_delay_timer_init(); 1647931d332SJit Loon Lim 1657931d332SJit Loon Lim /* Initialize the gic cpu and distributor interfaces */ 1667931d332SJit Loon Lim gicv3_driver_init(&plat_gicv3_gic_data); 1677931d332SJit Loon Lim gicv3_distif_init(); 1687931d332SJit Loon Lim gicv3_rdistif_init(plat_my_core_pos()); 1697931d332SJit Loon Lim gicv3_cpuif_enable(plat_my_core_pos()); 1707931d332SJit Loon Lim mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); 1717931d332SJit Loon Lim } 1727931d332SJit Loon Lim 1737931d332SJit Loon Lim const mmap_region_t plat_agilex_mmap[] = { 1747931d332SJit Loon Lim MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), 1757931d332SJit Loon Lim MAP_REGION_FLAT(PSS_BASE, PSS_SIZE, MT_DEVICE | MT_RW | MT_NS), 1767931d332SJit Loon Lim MAP_REGION_FLAT(MPFE_BASE, MPFE_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1777931d332SJit Loon Lim MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, MT_NON_CACHEABLE | MT_RW | MT_SECURE), 1787931d332SJit Loon Lim MAP_REGION_FLAT(CCU_BASE, CCU_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1797931d332SJit Loon Lim MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS), 1807931d332SJit Loon Lim MAP_REGION_FLAT(GIC_BASE, GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1817931d332SJit Loon Lim {0} 1827931d332SJit Loon Lim }; 1837931d332SJit Loon Lim 1847931d332SJit Loon Lim /******************************************************************************* 1857931d332SJit Loon Lim * Perform the very early platform specific architectural setup here. At the 186998da640SHarrison Mutai * moment this is only initializes the mmu in a quick and dirty way. 1877931d332SJit Loon Lim ******************************************************************************/ 1887931d332SJit Loon Lim void bl31_plat_arch_setup(void) 1897931d332SJit Loon Lim { 1907931d332SJit Loon Lim uint32_t boot_core = 0x00; 1917931d332SJit Loon Lim uint32_t cpuid = 0x00; 1927931d332SJit Loon Lim 193b3d28508SSieu Mun Tang cpuid = MPIDR_AFFLVL1_VAL(read_mpidr()); 194b3d28508SSieu Mun Tang boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10); 1957931d332SJit Loon Lim NOTICE("BL31: Boot Core = %x\n", boot_core); 1967931d332SJit Loon Lim NOTICE("BL31: CPU ID = %x\n", cpuid); 1973c640c12STanmay Kathpalia INFO("BL31: Invalidate Data cache\n"); 1983c640c12STanmay Kathpalia invalidate_dcache_all(); 199*bf3877e0SSieu Mun Tang 200*bf3877e0SSieu Mun Tang /* Invalidate for NS EL2 and EL1 */ 201*bf3877e0SSieu Mun Tang invalidate_cache_low_el(); 2027931d332SJit Loon Lim } 2037931d332SJit Loon Lim 2047931d332SJit Loon Lim /* Get non-secure image entrypoint for BL33. Zephyr and Linux */ 2057931d332SJit Loon Lim uintptr_t plat_get_ns_image_entrypoint(void) 2067931d332SJit Loon Lim { 2077931d332SJit Loon Lim #ifdef PRELOADED_BL33_BASE 2087931d332SJit Loon Lim return PRELOADED_BL33_BASE; 2097931d332SJit Loon Lim #else 2107931d332SJit Loon Lim return PLAT_NS_IMAGE_OFFSET; 2117931d332SJit Loon Lim #endif 2127931d332SJit Loon Lim } 2137931d332SJit Loon Lim 2147931d332SJit Loon Lim /* Get non-secure SPSR for BL33. Zephyr and Linux */ 2157931d332SJit Loon Lim uint32_t arm_get_spsr_for_bl33_entry(void) 2167931d332SJit Loon Lim { 2177931d332SJit Loon Lim unsigned int mode; 2187931d332SJit Loon Lim uint32_t spsr; 2197931d332SJit Loon Lim 2207931d332SJit Loon Lim /* Figure out what mode we enter the non-secure world in */ 2217931d332SJit Loon Lim mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; 2227931d332SJit Loon Lim 2237931d332SJit Loon Lim /* 2247931d332SJit Loon Lim * TODO: Consider the possibility of specifying the SPSR in 2257931d332SJit Loon Lim * the FIP ToC and allowing the platform to have a say as 2267931d332SJit Loon Lim * well. 2277931d332SJit Loon Lim */ 2287931d332SJit Loon Lim spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 2297931d332SJit Loon Lim return spsr; 2307931d332SJit Loon Lim } 2317931d332SJit Loon Lim 2327931d332SJit Loon Lim /* SMP: Secondary cores BL31 setup reset vector */ 2337931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_entrypoint(unsigned int cpu_id) 2347931d332SJit Loon Lim { 2357931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2367931d332SJit Loon Lim unsigned int pchctlr_old = 0x00; 2377931d332SJit Loon Lim unsigned int pchctlr_new = 0x00; 2387931d332SJit Loon Lim uint32_t boot_core = 0x00; 2397931d332SJit Loon Lim 240c1253b24SSieu Mun Tang /* Store magic number for SMP secondary cores boot */ 241c1253b24SSieu Mun Tang mmio_write_32(L2_RESET_DONE_REG, SMP_SEC_CORE_BOOT_REQ); 242c1253b24SSieu Mun Tang 2437931d332SJit Loon Lim boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00); 2447931d332SJit Loon Lim /* Update the p-channel based on cpu id */ 2457931d332SJit Loon Lim pch_cpu = 1 << cpu_id; 2467931d332SJit Loon Lim 2477931d332SJit Loon Lim if (boot_core == 0x00) { 2487931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2497931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU2, 2507931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2517931d332SJit Loon Lim } else { 2527931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2537931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU0, 2547931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2557931d332SJit Loon Lim } 2567931d332SJit Loon Lim 2577931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2587931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU1, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2597931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU3, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2607931d332SJit Loon Lim 2617931d332SJit Loon Lim /* On all cores - temporary */ 2627931d332SJit Loon Lim pchctlr_old = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2637931d332SJit Loon Lim pchctlr_new = pchctlr_old | (pch_cpu<<1); 2647931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pchctlr_new); 2657931d332SJit Loon Lim 2667931d332SJit Loon Lim /* We will only release the target secondary CPUs */ 2677931d332SJit Loon Lim /* Bit mask for each CPU BIT0-3 */ 2687931d332SJit Loon Lim mmio_write_32(RSTMGR_CPUSTRELEASE_CPUx, pch_cpu); 2697931d332SJit Loon Lim } 2707931d332SJit Loon Lim 2717931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_off(void) 2727931d332SJit Loon Lim { 2737931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2747931d332SJit Loon Lim unsigned int pch_cpu_off = 0x00; 2757931d332SJit Loon Lim unsigned int cpu_id = plat_my_core_pos(); 2767931d332SJit Loon Lim 2777931d332SJit Loon Lim pch_cpu_off = 1 << cpu_id; 2787931d332SJit Loon Lim 2797931d332SJit Loon Lim pch_cpu = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2807931d332SJit Loon Lim pch_cpu = pch_cpu & ~(pch_cpu_off << 1); 2817931d332SJit Loon Lim 2827931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu); 2837931d332SJit Loon Lim } 2847931d332SJit Loon Lim 2857931d332SJit Loon Lim void bl31_plat_enable_mmu(uint32_t flags) 2867931d332SJit Loon Lim { 2877931d332SJit Loon Lim /* TODO: Enable mmu when needed */ 2887931d332SJit Loon Lim } 289