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. 4*3c640c12STanmay 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 21*3c640c12STanmay 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 init_ncore_ccu(); 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 1507931d332SJit Loon Lim static const 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 1667931d332SJit Loon Lim /* Initialize the gic cpu and distributor interfaces */ 1677931d332SJit Loon Lim gicv3_driver_init(&plat_gicv3_gic_data); 1687931d332SJit Loon Lim gicv3_distif_init(); 1697931d332SJit Loon Lim gicv3_rdistif_init(plat_my_core_pos()); 1707931d332SJit Loon Lim gicv3_cpuif_enable(plat_my_core_pos()); 1717931d332SJit Loon Lim mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); 1727931d332SJit Loon Lim } 1737931d332SJit Loon Lim 1747931d332SJit Loon Lim const mmap_region_t plat_agilex_mmap[] = { 1757931d332SJit Loon Lim MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), 1767931d332SJit Loon Lim MAP_REGION_FLAT(PSS_BASE, PSS_SIZE, MT_DEVICE | MT_RW | MT_NS), 1777931d332SJit Loon Lim MAP_REGION_FLAT(MPFE_BASE, MPFE_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1787931d332SJit Loon Lim MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, MT_NON_CACHEABLE | MT_RW | MT_SECURE), 1797931d332SJit Loon Lim MAP_REGION_FLAT(CCU_BASE, CCU_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1807931d332SJit Loon Lim MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS), 1817931d332SJit Loon Lim MAP_REGION_FLAT(GIC_BASE, GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1827931d332SJit Loon Lim {0} 1837931d332SJit Loon Lim }; 1847931d332SJit Loon Lim 1857931d332SJit Loon Lim /******************************************************************************* 1867931d332SJit Loon Lim * Perform the very early platform specific architectural setup here. At the 187998da640SHarrison Mutai * moment this is only initializes the mmu in a quick and dirty way. 1887931d332SJit Loon Lim ******************************************************************************/ 1897931d332SJit Loon Lim void bl31_plat_arch_setup(void) 1907931d332SJit Loon Lim { 1917931d332SJit Loon Lim uint32_t boot_core = 0x00; 1927931d332SJit Loon Lim uint32_t cpuid = 0x00; 1937931d332SJit Loon Lim 1947931d332SJit Loon Lim cpuid = read_mpidr(); 1957931d332SJit Loon Lim boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00); 1967931d332SJit Loon Lim NOTICE("BL31: Boot Core = %x\n", boot_core); 1977931d332SJit Loon Lim NOTICE("BL31: CPU ID = %x\n", cpuid); 198*3c640c12STanmay Kathpalia INFO("BL31: Invalidate Data cache\n"); 199*3c640c12STanmay Kathpalia invalidate_dcache_all(); 2007931d332SJit Loon Lim } 2017931d332SJit Loon Lim 2027931d332SJit Loon Lim /* Get non-secure image entrypoint for BL33. Zephyr and Linux */ 2037931d332SJit Loon Lim uintptr_t plat_get_ns_image_entrypoint(void) 2047931d332SJit Loon Lim { 2057931d332SJit Loon Lim #ifdef PRELOADED_BL33_BASE 2067931d332SJit Loon Lim return PRELOADED_BL33_BASE; 2077931d332SJit Loon Lim #else 2087931d332SJit Loon Lim return PLAT_NS_IMAGE_OFFSET; 2097931d332SJit Loon Lim #endif 2107931d332SJit Loon Lim } 2117931d332SJit Loon Lim 2127931d332SJit Loon Lim /* Get non-secure SPSR for BL33. Zephyr and Linux */ 2137931d332SJit Loon Lim uint32_t arm_get_spsr_for_bl33_entry(void) 2147931d332SJit Loon Lim { 2157931d332SJit Loon Lim unsigned int mode; 2167931d332SJit Loon Lim uint32_t spsr; 2177931d332SJit Loon Lim 2187931d332SJit Loon Lim /* Figure out what mode we enter the non-secure world in */ 2197931d332SJit Loon Lim mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; 2207931d332SJit Loon Lim 2217931d332SJit Loon Lim /* 2227931d332SJit Loon Lim * TODO: Consider the possibility of specifying the SPSR in 2237931d332SJit Loon Lim * the FIP ToC and allowing the platform to have a say as 2247931d332SJit Loon Lim * well. 2257931d332SJit Loon Lim */ 2267931d332SJit Loon Lim spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 2277931d332SJit Loon Lim return spsr; 2287931d332SJit Loon Lim } 2297931d332SJit Loon Lim 2307931d332SJit Loon Lim /* SMP: Secondary cores BL31 setup reset vector */ 2317931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_entrypoint(unsigned int cpu_id) 2327931d332SJit Loon Lim { 2337931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2347931d332SJit Loon Lim unsigned int pchctlr_old = 0x00; 2357931d332SJit Loon Lim unsigned int pchctlr_new = 0x00; 2367931d332SJit Loon Lim uint32_t boot_core = 0x00; 2377931d332SJit Loon Lim 2387931d332SJit Loon Lim boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00); 2397931d332SJit Loon Lim /* Update the p-channel based on cpu id */ 2407931d332SJit Loon Lim pch_cpu = 1 << cpu_id; 2417931d332SJit Loon Lim 2427931d332SJit Loon Lim if (boot_core == 0x00) { 2437931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2447931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU2, 2457931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2467931d332SJit Loon Lim } else { 2477931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2487931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU0, 2497931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2507931d332SJit Loon Lim } 2517931d332SJit Loon Lim 2527931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2537931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU1, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2547931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU3, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2557931d332SJit Loon Lim 2567931d332SJit Loon Lim /* On all cores - temporary */ 2577931d332SJit Loon Lim pchctlr_old = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2587931d332SJit Loon Lim pchctlr_new = pchctlr_old | (pch_cpu<<1); 2597931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pchctlr_new); 2607931d332SJit Loon Lim 2617931d332SJit Loon Lim /* We will only release the target secondary CPUs */ 2627931d332SJit Loon Lim /* Bit mask for each CPU BIT0-3 */ 2637931d332SJit Loon Lim mmio_write_32(RSTMGR_CPUSTRELEASE_CPUx, pch_cpu); 2647931d332SJit Loon Lim } 2657931d332SJit Loon Lim 2667931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_off(void) 2677931d332SJit Loon Lim { 2687931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2697931d332SJit Loon Lim unsigned int pch_cpu_off = 0x00; 2707931d332SJit Loon Lim unsigned int cpu_id = plat_my_core_pos(); 2717931d332SJit Loon Lim 2727931d332SJit Loon Lim pch_cpu_off = 1 << cpu_id; 2737931d332SJit Loon Lim 2747931d332SJit Loon Lim pch_cpu = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2757931d332SJit Loon Lim pch_cpu = pch_cpu & ~(pch_cpu_off << 1); 2767931d332SJit Loon Lim 2777931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu); 2787931d332SJit Loon Lim } 2797931d332SJit Loon Lim 2807931d332SJit Loon Lim void bl31_plat_enable_mmu(uint32_t flags) 2817931d332SJit Loon Lim { 2827931d332SJit Loon Lim /* TODO: Enable mmu when needed */ 2837931d332SJit Loon Lim } 284