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 64458b40dfSJit Loon Lim /* Enable TF-A BL31 logs when running from non-secure world also. */ 65458b40dfSJit Loon Lim console_set_scope(&console, 66458b40dfSJit Loon Lim (CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH)); 67458b40dfSJit Loon Lim 687931d332SJit Loon Lim setup_smmu_stream_id(); 697931d332SJit Loon Lim 707931d332SJit Loon Lim /* 717931d332SJit Loon Lim * Check params passed from BL31 should not be NULL, 727931d332SJit Loon Lim */ 737931d332SJit Loon Lim void *from_bl2 = (void *) arg0; 747931d332SJit Loon Lim 757931d332SJit Loon Lim #if RESET_TO_BL31 767931d332SJit Loon Lim /* There are no parameters from BL2 if BL31 is a reset vector */ 777931d332SJit Loon Lim assert(from_bl2 == NULL); 787931d332SJit Loon Lim void *plat_params_from_bl2 = (void *) arg3; 797931d332SJit Loon Lim 807931d332SJit Loon Lim assert(plat_params_from_bl2 == NULL); 817931d332SJit Loon Lim 827931d332SJit Loon Lim /* Populate entry point information for BL33 */ 837931d332SJit Loon Lim SET_PARAM_HEAD(&bl33_image_ep_info, 847931d332SJit Loon Lim PARAM_EP, 857931d332SJit Loon Lim VERSION_1, 867931d332SJit Loon Lim 0); 877931d332SJit Loon Lim 887931d332SJit Loon Lim # if ARM_LINUX_KERNEL_AS_BL33 897931d332SJit Loon Lim /* 907931d332SJit Loon Lim * According to the file ``Documentation/arm64/booting.txt`` of the 917931d332SJit Loon Lim * Linux kernel tree, Linux expects the physical address of the device 927931d332SJit Loon Lim * tree blob (DTB) in x0, while x1-x3 are reserved for future use and 937931d332SJit Loon Lim * must be 0. 947931d332SJit Loon Lim */ 957931d332SJit Loon Lim bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; 967931d332SJit Loon Lim bl33_image_ep_info.args.arg1 = 0U; 977931d332SJit Loon Lim bl33_image_ep_info.args.arg2 = 0U; 987931d332SJit Loon Lim bl33_image_ep_info.args.arg3 = 0U; 997931d332SJit Loon Lim # endif 1007931d332SJit Loon Lim 1017931d332SJit Loon Lim #else /* RESET_TO_BL31 */ 1027931d332SJit Loon Lim bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; 1037931d332SJit Loon Lim 1047931d332SJit Loon Lim assert(params_from_bl2 != NULL); 1057931d332SJit Loon Lim 1067931d332SJit Loon Lim /* 1077931d332SJit Loon Lim * Copy BL32 (if populated by BL31) and BL33 entry point information. 1087931d332SJit Loon Lim * They are stored in Secure RAM, in BL31's address space. 1097931d332SJit Loon Lim */ 1107931d332SJit Loon Lim 1117931d332SJit Loon Lim if (params_from_bl2->h.type == PARAM_BL_PARAMS && 1127931d332SJit Loon Lim params_from_bl2->h.version >= VERSION_2) { 1137931d332SJit Loon Lim 1147931d332SJit Loon Lim bl_params_node_t *bl_params = params_from_bl2->head; 1157931d332SJit Loon Lim 1167931d332SJit Loon Lim while (bl_params) { 1177931d332SJit Loon Lim if (bl_params->image_id == BL33_IMAGE_ID) { 1187931d332SJit Loon Lim bl33_image_ep_info = *bl_params->ep_info; 1197931d332SJit Loon Lim } 1207931d332SJit Loon Lim bl_params = bl_params->next_params_info; 1217931d332SJit Loon Lim } 1227931d332SJit Loon Lim } else { 1237931d332SJit Loon Lim struct socfpga_bl31_params *arg_from_bl2 = 1247931d332SJit Loon Lim (struct socfpga_bl31_params *) from_bl2; 1257931d332SJit Loon Lim 1267931d332SJit Loon Lim assert(arg_from_bl2->h.type == PARAM_BL31); 1277931d332SJit Loon Lim assert(arg_from_bl2->h.version >= VERSION_1); 1287931d332SJit Loon Lim 1297931d332SJit Loon Lim bl32_image_ep_info = *arg_from_bl2->bl32_ep_info; 1307931d332SJit Loon Lim bl33_image_ep_info = *arg_from_bl2->bl33_ep_info; 1317931d332SJit Loon Lim } 1327931d332SJit Loon Lim 1337931d332SJit Loon Lim bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE; 1347931d332SJit Loon Lim bl33_image_ep_info.args.arg1 = 0U; 1357931d332SJit Loon Lim bl33_image_ep_info.args.arg2 = 0U; 1367931d332SJit Loon Lim bl33_image_ep_info.args.arg3 = 0U; 1377931d332SJit Loon Lim #endif 1387931d332SJit Loon Lim 1397931d332SJit Loon Lim /* 1407931d332SJit Loon Lim * Tell BL31 where the non-trusted software image 1417931d332SJit Loon Lim * is located and the entry state information 1427931d332SJit Loon Lim */ 1437931d332SJit Loon Lim bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); 1447931d332SJit Loon Lim bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); 1457931d332SJit Loon Lim 1467931d332SJit Loon Lim SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); 1477931d332SJit Loon Lim } 1487931d332SJit Loon Lim 1497931d332SJit Loon Lim static const interrupt_prop_t agx5_interrupt_props[] = { 1507931d332SJit Loon Lim PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(INTR_GROUP1S), 1517931d332SJit Loon Lim PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(INTR_GROUP0) 1527931d332SJit Loon Lim }; 1537931d332SJit Loon Lim 15429d1e29dSJit Loon Lim gicv3_driver_data_t plat_gicv3_gic_data = { 1557931d332SJit Loon Lim .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, 1567931d332SJit Loon Lim .gicr_base = PLAT_INTEL_SOCFPGA_GICR_BASE, 1577931d332SJit Loon Lim .interrupt_props = agx5_interrupt_props, 1587931d332SJit Loon Lim .interrupt_props_num = ARRAY_SIZE(agx5_interrupt_props), 1597931d332SJit Loon Lim .rdistif_num = PLATFORM_CORE_COUNT, 1607931d332SJit Loon Lim .rdistif_base_addrs = rdistif_base_addrs, 1617931d332SJit Loon Lim }; 1627931d332SJit Loon Lim 1637931d332SJit Loon Lim /******************************************************************************* 1647931d332SJit Loon Lim * Perform any BL3-1 platform setup code 1657931d332SJit Loon Lim ******************************************************************************/ 1667931d332SJit Loon Lim void bl31_platform_setup(void) 1677931d332SJit Loon Lim { 1687931d332SJit Loon Lim socfpga_delay_timer_init(); 1697931d332SJit Loon Lim 17029d1e29dSJit Loon Lim /* TODO: DTB not available */ 17129d1e29dSJit Loon Lim // socfpga_dt_populate_gicv3_config(SOCFPGA_DTB_BASE, &plat_gicv3_gic_data); 17229d1e29dSJit Loon Lim // NOTICE("SOCFPGA: GIC GICD base address 0x%lx\n", plat_gicv3_gic_data.gicd_base); 17329d1e29dSJit Loon Lim // NOTICE("SOCFPGA: GIC GICR base address 0x%lx\n", plat_gicv3_gic_data.gicr_base); 17429d1e29dSJit Loon Lim 1757931d332SJit Loon Lim /* Initialize the gic cpu and distributor interfaces */ 1767931d332SJit Loon Lim gicv3_driver_init(&plat_gicv3_gic_data); 1777931d332SJit Loon Lim gicv3_distif_init(); 1787931d332SJit Loon Lim gicv3_rdistif_init(plat_my_core_pos()); 1797931d332SJit Loon Lim gicv3_cpuif_enable(plat_my_core_pos()); 180204d5e67SSieu Mun Tang 181204d5e67SSieu Mun Tang #if SIP_SVC_V3 182204d5e67SSieu Mun Tang /* 183204d5e67SSieu Mun Tang * Re-initialize the mailbox to include V3 specific routines. 184204d5e67SSieu Mun Tang * In V3, this re-initialize is required because prior to BL31, U-Boot 185204d5e67SSieu Mun Tang * SPL has its own mailbox settings and this initialization will 186204d5e67SSieu Mun Tang * override to those settings as required by the V3 framework. 187204d5e67SSieu Mun Tang */ 188204d5e67SSieu Mun Tang mailbox_init(); 189204d5e67SSieu Mun Tang #endif 190204d5e67SSieu Mun Tang 1917931d332SJit Loon Lim mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); 1927931d332SJit Loon Lim } 1937931d332SJit Loon Lim 1947931d332SJit Loon Lim const mmap_region_t plat_agilex_mmap[] = { 1957931d332SJit Loon Lim MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), 1967931d332SJit Loon Lim MAP_REGION_FLAT(PSS_BASE, PSS_SIZE, MT_DEVICE | MT_RW | MT_NS), 1977931d332SJit Loon Lim MAP_REGION_FLAT(MPFE_BASE, MPFE_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 1987931d332SJit Loon Lim MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE, MT_NON_CACHEABLE | MT_RW | MT_SECURE), 1997931d332SJit Loon Lim MAP_REGION_FLAT(CCU_BASE, CCU_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 2007931d332SJit Loon Lim MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE, MT_DEVICE | MT_RW | MT_NS), 2017931d332SJit Loon Lim MAP_REGION_FLAT(GIC_BASE, GIC_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 2027931d332SJit Loon Lim {0} 2037931d332SJit Loon Lim }; 2047931d332SJit Loon Lim 2057931d332SJit Loon Lim /******************************************************************************* 2067931d332SJit Loon Lim * Perform the very early platform specific architectural setup here. At the 207998da640SHarrison Mutai * moment this is only initializes the mmu in a quick and dirty way. 2087931d332SJit Loon Lim ******************************************************************************/ 2097931d332SJit Loon Lim void bl31_plat_arch_setup(void) 2107931d332SJit Loon Lim { 2117931d332SJit Loon Lim uint32_t boot_core = 0x00; 2127931d332SJit Loon Lim uint32_t cpuid = 0x00; 2137931d332SJit Loon Lim 214b3d28508SSieu Mun Tang cpuid = MPIDR_AFFLVL1_VAL(read_mpidr()); 215b3d28508SSieu Mun Tang boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10); 21629d1e29dSJit Loon Lim NOTICE("SOCFPGA: Boot Core = %x\n", boot_core); 21729d1e29dSJit Loon Lim NOTICE("SOCFPGA: CPU ID = %x\n", cpuid); 21829d1e29dSJit Loon Lim INFO("SOCFPGA: Invalidate Data cache\n"); 2193c640c12STanmay Kathpalia invalidate_dcache_all(); 220bf3877e0SSieu Mun Tang /* Invalidate for NS EL2 and EL1 */ 221bf3877e0SSieu Mun Tang invalidate_cache_low_el(); 222bb9e34f9SJit Loon Lim 223bb9e34f9SJit Loon Lim NOTICE("SOCFPGA: Setting CLUSTERECTRL_EL1\n"); 224bb9e34f9SJit Loon Lim setup_clusterectlr_el1(); 2257931d332SJit Loon Lim } 2267931d332SJit Loon Lim 2277931d332SJit Loon Lim /* Get non-secure image entrypoint for BL33. Zephyr and Linux */ 2287931d332SJit Loon Lim uintptr_t plat_get_ns_image_entrypoint(void) 2297931d332SJit Loon Lim { 2307931d332SJit Loon Lim #ifdef PRELOADED_BL33_BASE 2317931d332SJit Loon Lim return PRELOADED_BL33_BASE; 2327931d332SJit Loon Lim #else 2337931d332SJit Loon Lim return PLAT_NS_IMAGE_OFFSET; 2347931d332SJit Loon Lim #endif 2357931d332SJit Loon Lim } 2367931d332SJit Loon Lim 2377931d332SJit Loon Lim /* Get non-secure SPSR for BL33. Zephyr and Linux */ 2387931d332SJit Loon Lim uint32_t arm_get_spsr_for_bl33_entry(void) 2397931d332SJit Loon Lim { 2407931d332SJit Loon Lim unsigned int mode; 2417931d332SJit Loon Lim uint32_t spsr; 2427931d332SJit Loon Lim 2437931d332SJit Loon Lim /* Figure out what mode we enter the non-secure world in */ 2447931d332SJit Loon Lim mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; 2457931d332SJit Loon Lim 2467931d332SJit Loon Lim /* 2477931d332SJit Loon Lim * TODO: Consider the possibility of specifying the SPSR in 2487931d332SJit Loon Lim * the FIP ToC and allowing the platform to have a say as 2497931d332SJit Loon Lim * well. 2507931d332SJit Loon Lim */ 2517931d332SJit Loon Lim spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); 2527931d332SJit Loon Lim return spsr; 2537931d332SJit Loon Lim } 2547931d332SJit Loon Lim 2557931d332SJit Loon Lim /* SMP: Secondary cores BL31 setup reset vector */ 2567931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_entrypoint(unsigned int cpu_id) 2577931d332SJit Loon Lim { 2587931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 2597931d332SJit Loon Lim unsigned int pchctlr_old = 0x00; 2607931d332SJit Loon Lim unsigned int pchctlr_new = 0x00; 2617931d332SJit Loon Lim uint32_t boot_core = 0x00; 2627931d332SJit Loon Lim 263646a9a16SJit Loon Lim /* Set bit for SMP secondary cores boot */ 264646a9a16SJit Loon Lim mmio_clrsetbits_32(L2_RESET_DONE_REG, BS_REG_MAGIC_KEYS_MASK, 265646a9a16SJit Loon Lim SMP_SEC_CORE_BOOT_REQ); 2667931d332SJit Loon Lim boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00); 2677931d332SJit Loon Lim /* Update the p-channel based on cpu id */ 2687931d332SJit Loon Lim pch_cpu = 1 << cpu_id; 2697931d332SJit Loon Lim 2707931d332SJit Loon Lim if (boot_core == 0x00) { 2717931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2727931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU2, 2737931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2747931d332SJit Loon Lim } else { 2757931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2767931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU0, 2777931d332SJit Loon Lim (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2787931d332SJit Loon Lim } 2797931d332SJit Loon Lim 2807931d332SJit Loon Lim /* Update reset vector to 0x00 */ 2817931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU1, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2827931d332SJit Loon Lim mmio_write_64(RSTMGR_CPUxRESETBASELOW_CPU3, (uint64_t) plat_secondary_cpus_bl31_entry >> 2); 2837931d332SJit Loon Lim 2847931d332SJit Loon Lim /* On all cores - temporary */ 2857931d332SJit Loon Lim pchctlr_old = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 2867931d332SJit Loon Lim pchctlr_new = pchctlr_old | (pch_cpu<<1); 2877931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pchctlr_new); 2887931d332SJit Loon Lim 2897931d332SJit Loon Lim /* We will only release the target secondary CPUs */ 2907931d332SJit Loon Lim /* Bit mask for each CPU BIT0-3 */ 2917931d332SJit Loon Lim mmio_write_32(RSTMGR_CPUSTRELEASE_CPUx, pch_cpu); 2927931d332SJit Loon Lim } 2937931d332SJit Loon Lim 294*8f7575efSBoon Khai Ng void bl31_plat_reset_secondary_cpu(unsigned int cpu_id) 295*8f7575efSBoon Khai Ng { 296*8f7575efSBoon Khai Ng uint32_t mask = 0x1; 297*8f7575efSBoon Khai Ng uint32_t value = 0; 298*8f7575efSBoon Khai Ng uint32_t pwrctlr_addr = 0; 299*8f7575efSBoon Khai Ng uint32_t pwrstat_addr = 0; 300*8f7575efSBoon Khai Ng uint32_t ret = 0; 301*8f7575efSBoon Khai Ng 302*8f7575efSBoon Khai Ng mask <<= cpu_id; 303*8f7575efSBoon Khai Ng 304*8f7575efSBoon Khai Ng switch (cpu_id) { 305*8f7575efSBoon Khai Ng case 0: 306*8f7575efSBoon Khai Ng pwrctlr_addr = AGX5_PWRMGR(CPU_PWRCTLR0); 307*8f7575efSBoon Khai Ng pwrstat_addr = AGX5_PWRMGR(CPU_PWRSTAT0); 308*8f7575efSBoon Khai Ng break; 309*8f7575efSBoon Khai Ng case 1: 310*8f7575efSBoon Khai Ng pwrctlr_addr = AGX5_PWRMGR(CPU_PWRCTLR1); 311*8f7575efSBoon Khai Ng pwrstat_addr = AGX5_PWRMGR(CPU_PWRSTAT1); 312*8f7575efSBoon Khai Ng break; 313*8f7575efSBoon Khai Ng case 2: 314*8f7575efSBoon Khai Ng pwrctlr_addr = AGX5_PWRMGR(CPU_PWRCTLR2); 315*8f7575efSBoon Khai Ng pwrstat_addr = AGX5_PWRMGR(CPU_PWRSTAT2); 316*8f7575efSBoon Khai Ng break; 317*8f7575efSBoon Khai Ng case 3: 318*8f7575efSBoon Khai Ng pwrctlr_addr = AGX5_PWRMGR(CPU_PWRCTLR3); 319*8f7575efSBoon Khai Ng pwrstat_addr = AGX5_PWRMGR(CPU_PWRSTAT3); 320*8f7575efSBoon Khai Ng break; 321*8f7575efSBoon Khai Ng default: 322*8f7575efSBoon Khai Ng ERROR("BL31: %s: Invalid CPU ID\n", __func__); 323*8f7575efSBoon Khai Ng break; 324*8f7575efSBoon Khai Ng } 325*8f7575efSBoon Khai Ng 326*8f7575efSBoon Khai Ng /* Poll for CPU WFI */ 327*8f7575efSBoon Khai Ng SOCFPGA_POLL(!((AGX5_PWRMGR_CPU_CORE_IN_STRRUN_STS( 328*8f7575efSBoon Khai Ng mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_WARM_9))) & 329*8f7575efSBoon Khai Ng mask) == 0), AGX5_PWRMGR_CPU_POLL_COUNT, 330*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_DELAY_10_US, udelay, ret); 331*8f7575efSBoon Khai Ng 332*8f7575efSBoon Khai Ng if (ret != 0) 333*8f7575efSBoon Khai Ng ERROR("BL31: %s: Timeout when polling CPU for WFI\n", __func__); 334*8f7575efSBoon Khai Ng 335*8f7575efSBoon Khai Ng /* PSTATE = 0, RUN_PCH = 1 */ 336*8f7575efSBoon Khai Ng mmio_write_32(pwrctlr_addr, AGX5_PWRMGR_CPU_RUN_PCH(1)); 337*8f7575efSBoon Khai Ng 338*8f7575efSBoon Khai Ng /* Poll for CPU OFF */ 339*8f7575efSBoon Khai Ng SOCFPGA_POLL(!((AGX5_PWRMGR_CPU_RUN_PCH( 340*8f7575efSBoon Khai Ng mmio_read_32(pwrstat_addr)) == 0) || 341*8f7575efSBoon Khai Ng (AGX5_PWRMGR_CPU_SINGLE_FSM_STATE( 342*8f7575efSBoon Khai Ng mmio_read_32(pwrstat_addr)) != 0)), 343*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_POLL_COUNT, 344*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_DELAY_10_US, udelay, ret); 345*8f7575efSBoon Khai Ng 346*8f7575efSBoon Khai Ng if (ret != 0) 347*8f7575efSBoon Khai Ng ERROR("BL31: %s: Timeout when polling for CPU OFF\n", __func__); 348*8f7575efSBoon Khai Ng 349*8f7575efSBoon Khai Ng /* Performs the warm reset CPUx */ 350*8f7575efSBoon Khai Ng value = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_WARM_9)); 351*8f7575efSBoon Khai Ng mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_WARM_9), value | mask); 352*8f7575efSBoon Khai Ng udelay(1); 353*8f7575efSBoon Khai Ng mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_WARM_9), value & ~mask); 354*8f7575efSBoon Khai Ng udelay(1); 355*8f7575efSBoon Khai Ng 356*8f7575efSBoon Khai Ng /* Power up sequence */ 357*8f7575efSBoon Khai Ng mmio_write_32(pwrctlr_addr, AGX5_PWRMGR_CPU_PROG_CPU_ON_STATE | 358*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_RUN_PCH(1)); 359*8f7575efSBoon Khai Ng 360*8f7575efSBoon Khai Ng /* Poll for CPU ON */ 361*8f7575efSBoon Khai Ng SOCFPGA_POLL(!((AGX5_PWRMGR_CPU_RUN_PCH( 362*8f7575efSBoon Khai Ng mmio_read_32(pwrstat_addr)) == 0) || 363*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_SINGLE_FSM_STATE( 364*8f7575efSBoon Khai Ng mmio_read_32(pwrstat_addr)) == 0), 365*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_POLL_COUNT, 366*8f7575efSBoon Khai Ng AGX5_PWRMGR_CPU_DELAY_10_US, udelay, ret); 367*8f7575efSBoon Khai Ng if (ret !=0 ) 368*8f7575efSBoon Khai Ng ERROR("BL31: %s: Timeout when polling for CPU ON\n", __func__); 369*8f7575efSBoon Khai Ng } 370*8f7575efSBoon Khai Ng 3717931d332SJit Loon Lim void bl31_plat_set_secondary_cpu_off(void) 3727931d332SJit Loon Lim { 3737931d332SJit Loon Lim unsigned int pch_cpu = 0x00; 3747931d332SJit Loon Lim unsigned int pch_cpu_off = 0x00; 3757931d332SJit Loon Lim unsigned int cpu_id = plat_my_core_pos(); 3767931d332SJit Loon Lim 3777931d332SJit Loon Lim pch_cpu_off = 1 << cpu_id; 3787931d332SJit Loon Lim 3797931d332SJit Loon Lim pch_cpu = mmio_read_32(AGX5_PWRMGR(MPU_PCHCTLR)); 3807931d332SJit Loon Lim pch_cpu = pch_cpu & ~(pch_cpu_off << 1); 3817931d332SJit Loon Lim 3827931d332SJit Loon Lim mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu); 3837931d332SJit Loon Lim } 3847931d332SJit Loon Lim 385bb9e34f9SJit Loon Lim void setup_clusterectlr_el1(void) 386bb9e34f9SJit Loon Lim { 387bb9e34f9SJit Loon Lim uint64_t value = 0; 388bb9e34f9SJit Loon Lim 389bb9e34f9SJit Loon Lim /* Read CLUSTERECTLR_EL1 */ 390bb9e34f9SJit Loon Lim asm volatile("mrs %0, S3_0_C15_C3_4" : "=r"(value)); 391bb9e34f9SJit Loon Lim 392bb9e34f9SJit Loon Lim /* Disable broadcasting atomics */ 393bb9e34f9SJit Loon Lim value |= 0x80; /* set bit 7 */ 394bb9e34f9SJit Loon Lim /* Disable sending data with clean evicts */ 395bb9e34f9SJit Loon Lim value &= 0xFFFFBFFF; /* Mask out bit 14 */ 396bb9e34f9SJit Loon Lim 397bb9e34f9SJit Loon Lim /* Write CLUSTERECTLR_EL1 */ 398bb9e34f9SJit Loon Lim asm volatile("msr S3_0_C15_C3_4, %0" :: "r"(value)); 399bb9e34f9SJit Loon Lim } 400bb9e34f9SJit Loon Lim 40129d1e29dSJit Loon Lim void bl31_plat_runtime_setup(void) 40229d1e29dSJit Loon Lim { 403458b40dfSJit Loon Lim /* Dummy override function. */ 40429d1e29dSJit Loon Lim } 40529d1e29dSJit Loon Lim 4067931d332SJit Loon Lim void bl31_plat_enable_mmu(uint32_t flags) 4077931d332SJit Loon Lim { 4087931d332SJit Loon Lim /* TODO: Enable mmu when needed */ 4097931d332SJit Loon Lim } 410