diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
commit | be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b (patch) | |
tree | 779c248fb61c83f65d1f0dc867f2053d76b4e03a /plat/xilinx/versal | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream.tar.xz arm-trusted-firmware-upstream.zip |
Adding upstream version 2.10.0+dfsg.upstream/2.10.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/xilinx/versal')
-rw-r--r-- | plat/xilinx/versal/aarch64/versal_common.c | 80 | ||||
-rw-r--r-- | plat/xilinx/versal/aarch64/versal_helpers.S | 75 | ||||
-rw-r--r-- | plat/xilinx/versal/bl31_versal_setup.c | 238 | ||||
-rw-r--r-- | plat/xilinx/versal/include/plat_ipi.h | 70 | ||||
-rw-r--r-- | plat/xilinx/versal/include/plat_macros.S | 111 | ||||
-rw-r--r-- | plat/xilinx/versal/include/plat_pm_common.h | 24 | ||||
-rw-r--r-- | plat/xilinx/versal/include/plat_private.h | 43 | ||||
-rw-r--r-- | plat/xilinx/versal/include/platform_def.h | 128 | ||||
-rw-r--r-- | plat/xilinx/versal/include/versal_def.h | 129 | ||||
-rw-r--r-- | plat/xilinx/versal/plat_psci.c | 254 | ||||
-rw-r--r-- | plat/xilinx/versal/plat_topology.c | 14 | ||||
-rw-r--r-- | plat/xilinx/versal/plat_versal.c | 22 | ||||
-rw-r--r-- | plat/xilinx/versal/platform.mk | 118 | ||||
-rw-r--r-- | plat/xilinx/versal/pm_service/pm_client.c | 280 | ||||
-rw-r--r-- | plat/xilinx/versal/sip_svc_setup.c | 126 | ||||
-rw-r--r-- | plat/xilinx/versal/tsp/tsp-versal.mk | 10 | ||||
-rw-r--r-- | plat/xilinx/versal/versal_gicv3.c | 188 | ||||
-rw-r--r-- | plat/xilinx/versal/versal_ipi.c | 77 |
18 files changed, 1987 insertions, 0 deletions
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c new file mode 100644 index 0000000..aba190d --- /dev/null +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <plat/common/platform.h> + +#include <plat_common.h> +#include <plat_ipi.h> +#include <plat_private.h> +#include <pm_api_sys.h> +#include <versal_def.h> + +uint32_t platform_id, platform_version; + +/* + * Table of regions to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +const mmap_region_t plat_versal_mmap[] = { + MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PLAT_ARM_CCI_BASE, PLAT_ARM_CCI_SIZE, MT_DEVICE | MT_RW | + MT_SECURE), + { 0 } +}; + +const mmap_region_t *plat_get_mmap(void) +{ + return plat_versal_mmap; +} + +static void versal_print_platform_name(void) +{ + NOTICE("TF-A running on %s\n", PLATFORM_NAME); +} + +void versal_config_setup(void) +{ + /* Configure IPI data for versal */ + versal_ipi_config_table_init(); + + versal_print_platform_name(); + + generic_delay_timer_init(); +} + +uint32_t plat_get_syscnt_freq2(void) +{ + return VERSAL_CPU_CLOCK; +} + +void board_detection(void) +{ + uint32_t plat_info[2]; + + if (pm_get_chipid(plat_info) != PM_RET_SUCCESS) { + /* If the call is failed we cannot proceed with further + * setup. TF-A to panic in this situation. + */ + NOTICE("Failed to read the chip information"); + panic(); + } + + platform_id = FIELD_GET(PLATFORM_MASK, plat_info[1]); + platform_version = FIELD_GET(PLATFORM_VERSION_MASK, plat_info[1]); +} + +uint32_t get_uart_clk(void) +{ + return UART_CLOCK; +} diff --git a/plat/xilinx/versal/aarch64/versal_helpers.S b/plat/xilinx/versal/aarch64/versal_helpers.S new file mode 100644 index 0000000..350ddc4 --- /dev/null +++ b/plat/xilinx/versal/aarch64/versal_helpers.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include <arch.h> +#include <asm_macros.S> +#include <drivers/arm/gicv3.h> + +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl versal_calc_core_pos + .globl platform_mem_init + .globl plat_my_core_pos + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mrs x0, mpidr_el1 + + /* + * There is no sane reason to come out of this wfi. This + * cpu will be powered on and reset by the cpu_on pm api + */ + dsb sy + bl plat_panic_handler +endfunc plat_secondary_cold_boot_setup + +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + cmp x0, #VERSAL_PRIMARY_CPU + cset x0, eq + ret x9 +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the versal_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b versal_calc_core_pos +endfunc plat_my_core_pos + +func versal_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc versal_calc_core_pos + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on VERSAL + * platform. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c new file mode 100644 index 0000000..cd105c6 --- /dev/null +++ b/plat/xilinx/versal/bl31_versal_setup.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <errno.h> + +#include <bl31/bl31.h> +#include <common/bl_common.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_tables_v2.h> +#include <plat/common/platform.h> +#include <plat_arm.h> +#include <plat_console.h> + +#include <plat_fdt.h> +#include <plat_private.h> +#include <plat_startup.h> +#include "pm_api_sys.h" +#include "pm_client.h" +#include <pm_ipi.h> +#include <versal_def.h> + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + */ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + assert(sec_state_is_valid(type)); + + if (type == NON_SECURE) { + return &bl33_image_ep_info; + } + + return &bl32_image_ep_info; +} + +/* + * Set the build time defaults,if we can't find any config data. + */ +static inline void bl31_set_default_config(void) +{ + bl32_image_ep_info.pc = (uintptr_t)BL32_BASE; + bl32_image_ep_info.spsr = (uint32_t)arm_get_spsr_for_bl32_entry(); + bl33_image_ep_info.pc = (uintptr_t)plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = (uint32_t)SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} + +/* + * Perform any BL31 specific platform actions. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + */ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + uint64_t tfa_handoff_addr; + uint32_t payload[PAYLOAD_ARG_CNT], max_size = HANDOFF_PARAMS_MAX_SIZE; + enum pm_ret_status ret_status; + uint64_t addr[HANDOFF_PARAMS_MAX_SIZE]; + + setup_console(); + + /* Initialize the platform config for future decision making */ + versal_config_setup(); + + /* Get platform related information */ + board_detection(); + + /* + * Do initial security configuration to allow DRAM/device access. On + * Base VERSAL only DRAM security is programmable (via TrustZone), but + * other platforms might have more programmable security devices + * present. + */ + + /* Populate common information for BL32 and BL33 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, 1, PM_LOAD_GET_HANDOFF_PARAMS, + (uintptr_t)addr >> 32U, (uintptr_t)addr, max_size); + ret_status = pm_ipi_send_sync(primary_proc, payload, NULL, 0); + if (ret_status == PM_RET_SUCCESS) { + INFO("BL31: GET_HANDOFF_PARAMS call success=%d\n", ret_status); + tfa_handoff_addr = (uintptr_t)&addr; + } else { + ERROR("BL31: GET_HANDOFF_PARAMS Failed, read tfa_handoff_addr from reg\n"); + tfa_handoff_addr = mmio_read_32(PMC_GLOBAL_GLOB_GEN_STORAGE4); + } + + enum xbl_handoff ret = xbl_handover(&bl32_image_ep_info, + &bl33_image_ep_info, + tfa_handoff_addr); + if (ret == XBL_HANDOFF_NO_STRUCT || ret == XBL_HANDOFF_INVAL_STRUCT) { + bl31_set_default_config(); + } else if (ret == XBL_HANDOFF_TOO_MANY_PARTS) { + ERROR("BL31: Error too many partitions %u\n", ret); + } else if (ret != XBL_HANDOFF_SUCCESS) { + panic(); + } else { + INFO("BL31: PLM to TF-A handover success %u\n", ret); + + /* + * The BL32 load address is indicated as 0x0 in the handoff + * parameters, which is different from the default/user-provided + * load address of 0x60000000 but the flags are correctly + * configured. Consequently, in this scenario, set the PC + * to the requested BL32_BASE address. + */ + + /* TODO: Remove the following check once this is fixed from PLM */ + if (bl32_image_ep_info.pc == 0 && bl32_image_ep_info.spsr != 0) { + bl32_image_ep_info.pc = (uintptr_t)BL32_BASE; + } + } + + NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); + NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); +} + +static versal_intr_info_type_el3_t type_el3_interrupt_table[MAX_INTR_EL3]; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + static uint32_t index; + uint32_t i; + + /* Validate 'handler' and 'id' parameters */ + if (handler == NULL || index >= MAX_INTR_EL3) { + return -EINVAL; + } + + /* Check if a handler has already been registered */ + for (i = 0; i < index; i++) { + if (id == type_el3_interrupt_table[i].id) { + return -EALREADY; + } + } + + type_el3_interrupt_table[index].id = id; + type_el3_interrupt_table[index].handler = handler; + + index++; + + return 0; +} + +static uint64_t rdo_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + uint32_t intr_id; + uint32_t i; + interrupt_type_handler_t handler = NULL; + + intr_id = plat_ic_get_pending_interrupt_id(); + + for (i = 0; i < MAX_INTR_EL3; i++) { + if (intr_id == type_el3_interrupt_table[i].id) { + handler = type_el3_interrupt_table[i].handler; + } + } + + if (handler != NULL) { + return handler(intr_id, flags, handle, cookie); + } + + return 0; +} + +void bl31_platform_setup(void) +{ + prepare_dtb(); + + /* Initialize the gic cpu and distributor interfaces */ + plat_versal_gic_driver_init(); + plat_versal_gic_init(); +} + +void bl31_plat_runtime_setup(void) +{ + uint64_t flags = 0; + int32_t rc; + + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_EL3, + rdo_el3_interrupt_handler, flags); + if (rc != 0) { + panic(); + } + + console_switch_state(CONSOLE_FLAG_RUNTIME); +} + +/* + * Perform the very early platform specific architectural setup here. + */ +void bl31_plat_arch_setup(void) +{ + plat_arm_interconnect_init(); + plat_arm_interconnect_enter_coherency(); + + const mmap_region_t bl_regions[] = { +#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE) && \ + (!defined(PLAT_XLAT_TABLES_DYNAMIC))) + MAP_REGION_FLAT(XILINX_OF_BOARD_DTB_ADDR, XILINX_OF_BOARD_DTB_MAX_SIZE, + MT_MEMORY | MT_RW | MT_NS), +#endif + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE), + MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE), + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), + {0} + }; + + setup_page_tables(bl_regions, plat_get_mmap()); + enable_mmu(0); +} diff --git a/plat/xilinx/versal/include/plat_ipi.h b/plat/xilinx/versal/include/plat_ipi.h new file mode 100644 index 0000000..4f7cb5f --- /dev/null +++ b/plat/xilinx/versal/include/plat_ipi.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Versal IPI management enums and defines */ + +#ifndef PLAT_IPI_H +#define PLAT_IPI_H + +#include <stdint.h> + +#include <ipi.h> + +/********************************************************************* + * IPI agent IDs macros + ********************************************************************/ +#define IPI_ID_PMC 1U +#define IPI_ID_APU 2U +#define IPI_ID_RPU0 3U +#define IPI_ID_RPU1 4U +#define IPI_ID_3 5U +#define IPI_ID_4 6U +#define IPI_ID_5 7U + +/********************************************************************* + * IPI message buffers + ********************************************************************/ +#define IPI_BUFFER_BASEADDR 0xFF3F0000U + +#define IPI_LOCAL_ID IPI_ID_APU +#define IPI_REMOTE_ID IPI_ID_PMC + +#define IPI_BUFFER_LOCAL_BASE (IPI_BUFFER_BASEADDR + (IPI_LOCAL_ID * 0x200U)) +#define IPI_BUFFER_REMOTE_BASE (IPI_BUFFER_BASEADDR + (IPI_REMOTE_ID * 0x200U)) + +#define IPI_BUFFER_TARGET_LOCAL_OFFSET (IPI_LOCAL_ID * 0x40U) +#define IPI_BUFFER_TARGET_REMOTE_OFFSET (IPI_REMOTE_ID * 0x40U) + +#define IPI_BUFFER_MAX_WORDS 8 + +#define IPI_BUFFER_REQ_OFFSET 0x0U +#define IPI_BUFFER_RESP_OFFSET 0x20U + +/********************************************************************* + * Platform specific IPI API declarations + ********************************************************************/ + +/* Configure IPI table for versal */ +void versal_ipi_config_table_init(void); + +/* IPI registers and bitfields */ +#define PMC_REG_BASE U(0xFF320000) +#define PMC_IPI_TRIG_BIT (1U << 1U) +#define IPI0_REG_BASE U(0xFF330000) +#define IPI0_TRIG_BIT (1U << 2U) +#define IPI1_REG_BASE U(0xFF340000) +#define IPI1_TRIG_BIT (1U << 3U) +#define IPI2_REG_BASE U(0xFF350000) +#define IPI2_TRIG_BIT (1U << 4U) +#define IPI3_REG_BASE U(0xFF360000) +#define IPI3_TRIG_BIT (1U << 5U) +#define IPI4_REG_BASE U(0xFF370000) +#define IPI4_TRIG_BIT (1U << 5U) +#define IPI5_REG_BASE U(0xFF380000) +#define IPI5_TRIG_BIT (1U << 6U) + +#endif /* PLAT_IPI_H */ diff --git a/plat/xilinx/versal/include/plat_macros.S b/plat/xilinx/versal/include/plat_macros.S new file mode 100644 index 0000000..41193a5 --- /dev/null +++ b/plat/xilinx/versal/include/plat_macros.S @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <drivers/arm/gic_common.h> +#include <drivers/arm/gicv2.h> +#include <drivers/arm/gicv3.h> + +#include "../include/platform_def.h" + +.section .rodata.gic_reg_name, "aS" +/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */ +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" + +/* Applicable only to GICv3 with SRE enabled */ +icc_regs: + .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", "" + +/* Registers common to both GICv2 and GICv3 */ +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below utility macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31 on Versal platform. + * Expects: GICD base in x16, GICC base in x17 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro versal_print_gic_regs + /* Check for GICv3 system register access */ + mrs x7, id_aa64pfr0_el1 + ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH + cmp x7, #1 + b.ne print_gicv2 + + /* Check for SRE enable */ + mrs x8, ICC_SRE_EL3 + tst x8, #ICC_SRE_SRE_BIT + b.eq print_gicv2 + + /* Load the icc reg list to x6 */ + adr x6, icc_regs + /* Load the icc regs to gp regs used by str_in_crash_buf_print */ + mrs x8, ICC_HPPIR0_EL1 + mrs x9, ICC_HPPIR1_EL1 + mrs x10, ICC_CTLR_EL3 + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + b print_gic_common + +print_gicv2: + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + +print_gic_common: + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +gicd_ispendr_loop: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq exit_print_gic_regs + bl asm_print_hex + + adr x4, spacer + bl asm_print_str + + ldr x4, [x7], #8 + bl asm_print_hex + + adr x4, newline + bl asm_print_str + b gicd_ispendr_loop +exit_print_gic_regs: + .endm + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC and CCI registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x17, PLAT_GICD_BASE_VALUE + mov_imm x16, PLAT_GICR_BASE_VALUE + versal_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/xilinx/versal/include/plat_pm_common.h b/plat/xilinx/versal/include/plat_pm_common.h new file mode 100644 index 0000000..0b4a115 --- /dev/null +++ b/plat/xilinx/versal/include/plat_pm_common.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains platform specific definitions of commonly used macros data types + * for PU Power Management. This file should be common for all PU's. + */ + +#ifndef PLAT_PM_COMMON_H +#define PLAT_PM_COMMON_H + +#include <stdint.h> + +#include <common/debug.h> + +#include "pm_defs.h" + +#define NON_SECURE_FLAG 1U +#define SECURE_FLAG 0U + +#endif /* PLAT_PM_COMMON_H */ diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h new file mode 100644 index 0000000..a4210cd --- /dev/null +++ b/plat/xilinx/versal/include/plat_private.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include <bl31/interrupt_mgmt.h> +#include <lib/xlat_tables/xlat_tables_v2.h> + +typedef struct versal_intr_info_type_el3 { + uint32_t id; + interrupt_type_handler_t handler; +} versal_intr_info_type_el3_t; + +uint32_t get_uart_clk(void); +void versal_config_setup(void); + +const mmap_region_t *plat_get_mmap(void); + +extern uint32_t platform_id, platform_version; + +void board_detection(void); +void plat_versal_gic_driver_init(void); +void plat_versal_gic_init(void); +void plat_versal_gic_cpuif_enable(void); +void plat_versal_gic_cpuif_disable(void); +void plat_versal_gic_pcpu_init(void); +void plat_versal_gic_save(void); +void plat_versal_gic_resume(void); + +uint32_t versal_calc_core_pos(u_register_t mpidr); +/* + * Register handler to specific GIC entrance + * for INTR_TYPE_EL3 type of interrupt + */ +int32_t request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler); + +#endif /* PLAT_PRIVATE_H */ diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h new file mode 100644 index 0000000..286a706 --- /dev/null +++ b/plat/xilinx/versal/include/platform_def.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include "versal_def.h" + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE U(0x440) + +#define PLATFORM_CORE_COUNT U(2) +#define PLAT_MAX_PWR_LVL U(1) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#ifndef VERSAL_ATF_MEM_BASE +# define BL31_BASE U(0xfffe0000) +# define BL31_LIMIT U(0x100000000) +#else +# define BL31_BASE U(VERSAL_ATF_MEM_BASE) +# define BL31_LIMIT U(VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_SIZE) +# ifdef VERSAL_ATF_MEM_PROGBITS_SIZE +# define BL31_PROGBITS_LIMIT U(VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_PROGBITS_SIZE) +# endif +#endif + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#ifndef VERSAL_BL32_MEM_BASE +# define BL32_BASE U(0x60000000) +# define BL32_LIMIT U(0x80000000) +#else +# define BL32_BASE U(VERSAL_BL32_MEM_BASE) +# define BL32_LIMIT U(VERSAL_BL32_MEM_BASE + VERSAL_BL32_MEM_SIZE) +#endif + +/******************************************************************************* + * BL33 specific defines. + ******************************************************************************/ +#ifndef PRELOADED_BL33_BASE +# define PLAT_ARM_NS_IMAGE_BASE U(0x8000000) +#else +# define PLAT_ARM_NS_IMAGE_BASE U(PRELOADED_BL33_BASE) +#endif + +/******************************************************************************* + * TSP specific defines. + ******************************************************************************/ +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE) + +/* ID of the secure physical generic timer interrupt used by the TSP */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) + +#define XILINX_OF_BOARD_DTB_MAX_SIZE U(0x200000) + +#define PLAT_OCM_BASE U(0xFFFE0000) +#define PLAT_OCM_LIMIT U(0xFFFFFFFF) + +#define IS_TFA_IN_OCM(x) ((x >= PLAT_OCM_BASE) && (x < PLAT_OCM_LIMIT)) + +#ifndef MAX_MMAP_REGIONS +#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE)) +#define MAX_MMAP_REGIONS 9 +#else +#define MAX_MMAP_REGIONS 8 +#endif +#endif + +#ifndef MAX_XLAT_TABLES +#if !IS_TFA_IN_OCM(BL31_BASE) +#define MAX_XLAT_TABLES 9 +#else +#define MAX_XLAT_TABLES 5 +#endif +#endif + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define PLAT_GICD_BASE_VALUE U(0xF9000000) +#define PLAT_GICR_BASE_VALUE U(0xF9080000) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_VERSAL_G1S_IRQS VERSAL_IRQ_SEC_PHY_TIMER +#define PLAT_VERSAL_G0_IRQS VERSAL_IRQ_SEC_PHY_TIMER +#define PLAT_VERSAL_IPI_IRQ U(62) + +#define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_VERSAL_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_EDGE), \ + +#define IRQ_MAX 142U + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h new file mode 100644 index 0000000..92c0ba6 --- /dev/null +++ b/plat/xilinx/versal/include/versal_def.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VERSAL_DEF_H +#define VERSAL_DEF_H + +#include <plat/arm/common/smccc_def.h> +#include <plat/common/common_def.h> + +#define PLATFORM_MASK GENMASK(27U, 24U) +#define PLATFORM_VERSION_MASK GENMASK(31U, 28U) + +/* number of interrupt handlers. increase as required */ +#define MAX_INTR_EL3 2 +/* List all consoles */ +#define VERSAL_CONSOLE_ID_pl011 1 +#define VERSAL_CONSOLE_ID_pl011_0 1 +#define VERSAL_CONSOLE_ID_pl011_1 2 +#define VERSAL_CONSOLE_ID_dcc 3 + +#define CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE) + +/* List all supported platforms */ +#define VERSAL_PLATFORM_ID_versal_virt 1 +#define VERSAL_PLATFORM_ID_spp_itr6 2 +#define VERSAL_PLATFORM_ID_emu_itr6 3 +#define VERSAL_PLATFORM_ID_silicon 4 + +#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM) + +/* Firmware Image Package */ +#define VERSAL_PRIMARY_CPU 0 + +/******************************************************************************* + * memory map related constants + ******************************************************************************/ +#define DEVICE0_BASE 0xFF000000 +#define DEVICE0_SIZE 0x00E00000 +#define DEVICE1_BASE 0xF9000000 +#define DEVICE1_SIZE 0x00800000 + +/******************************************************************************* + * IRQ constants + ******************************************************************************/ +#define VERSAL_IRQ_SEC_PHY_TIMER U(29) +#define ARM_IRQ_SEC_PHY_TIMER 29 + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define PLAT_ARM_CCI_BASE 0xFD000000 +#define PLAT_ARM_CCI_SIZE 0x00100000 +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 4 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define VERSAL_UART0_BASE 0xFF000000 +#define VERSAL_UART1_BASE 0xFF010000 + +#if CONSOLE_IS(pl011) || CONSOLE_IS(dcc) +# define UART_BASE VERSAL_UART0_BASE +#elif CONSOLE_IS(pl011_1) +# define UART_BASE VERSAL_UART1_BASE +#else +# error "invalid VERSAL_CONSOLE" +#endif + +/******************************************************************************* + * Platform related constants + ******************************************************************************/ +#if VERSAL_PLATFORM_IS(versal_virt) +# define PLATFORM_NAME "Versal Virt" +# define UART_CLOCK 25000000 +# define UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 2720000 +#elif VERSAL_PLATFORM_IS(silicon) +# define PLATFORM_NAME "Versal Silicon" +# define UART_CLOCK 100000000 +# define UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 100000000 +#elif VERSAL_PLATFORM_IS(spp_itr6) +# define PLATFORM_NAME "SPP ITR6" +# define UART_CLOCK 25000000 +# define UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 2720000 +#elif VERSAL_PLATFORM_IS(emu_itr6) +# define PLATFORM_NAME "EMU ITR6" +# define UART_CLOCK 212000 +# define UART_BAUDRATE 9600 +# define VERSAL_CPU_CLOCK 212000 +#endif + +/* Access control register defines */ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + +/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ +#define CRF_BASE 0xFD1A0000 +#define CRF_SIZE 0x00600000 + +/* CRF registers and bitfields */ +#define CRF_RST_APU (CRF_BASE + 0X00000300) + +#define CRF_RST_APU_ACPU_RESET (1 << 0) +#define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10) + +/* APU registers and bitfields */ +#define FPD_APU_BASE 0xFD5C0000U +#define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20U) +#define FPD_APU_RVBAR_L_0 (FPD_APU_BASE + 0x40U) +#define FPD_APU_RVBAR_H_0 (FPD_APU_BASE + 0x44U) +#define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90U) + +#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8U +#define APU_0_PWRCTL_CPUPWRDWNREQ_MASK 1U +#define APU_1_PWRCTL_CPUPWRDWNREQ_MASK 2U + +/* PMC registers and bitfields */ +#define PMC_GLOBAL_BASE 0xF1110000U +#define PMC_GLOBAL_GLOB_GEN_STORAGE4 (PMC_GLOBAL_BASE + 0x40U) + +#endif /* VERSAL_DEF_H */ diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c new file mode 100644 index 0000000..56d98f7 --- /dev/null +++ b/plat/xilinx/versal/plat_psci.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <plat_arm.h> + +#include <plat_private.h> +#include "pm_api_sys.h" +#include "pm_client.h" +#include <pm_common.h> + +static uintptr_t versal_sec_entry; + +static int32_t versal_pwr_domain_on(u_register_t mpidr) +{ + int32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + const struct pm_proc *proc; + + VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); + + if (cpu_id == -1) { + return PSCI_E_INTERN_FAIL; + } + + proc = pm_get_proc((uint32_t)cpu_id); + + /* Send request to PMC to wake up selected ACPU core */ + (void)pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFFU) | 0x1U, + versal_sec_entry >> 32, 0, SECURE_FLAG); + + /* Clear power down request */ + pm_client_wakeup(proc); + + return PSCI_E_SUCCESS; +} + +/** + * versal_pwr_domain_suspend() - This function sends request to PMC to suspend + * core. + * @target_state: Targated state. + * + */ +static void versal_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + uint32_t state; + uint32_t cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) { + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + plat_versal_gic_cpuif_disable(); + + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_versal_gic_save(); + } + + state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ? + PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE; + + /* Send request to PMC to suspend this core */ + (void)pm_self_suspend(proc->node_id, MAX_LATENCY, state, versal_sec_entry, + SECURE_FLAG); + + /* APU is to be turned off */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + /* disable coherency */ + plat_arm_interconnect_exit_coherency(); + } +} + +/** + * versal_pwr_domain_suspend_finish() - This function performs actions to finish + * suspend procedure. + * @target_state: Targated state. + * + */ +static void versal_pwr_domain_suspend_finish( + const psci_power_state_t *target_state) +{ + uint32_t cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) { + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + /* Clear the APU power control register for this cpu */ + pm_client_wakeup(proc); + + /* enable coherency */ + plat_arm_interconnect_enter_coherency(); + + /* APU was turned off, so restore GIC context */ + if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) { + plat_versal_gic_resume(); + } + + plat_versal_gic_cpuif_enable(); +} + +void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Enable the gic cpu interface */ + plat_versal_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_versal_gic_cpuif_enable(); +} + +/** + * versal_system_off() - This function sends the system off request to firmware. + * This function does not return. + * + */ +static void __dead2 versal_system_off(void) +{ + /* Send the power down request to the PMC */ + (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN, + pm_get_shutdown_scope(), SECURE_FLAG); + + while (1) { + wfi(); + } +} + +/** + * versal_system_reset() - This function sends the reset request to firmware + * for the system to reset. This function does not + * return. + * + */ +static void __dead2 versal_system_reset(void) +{ + /* Send the system reset request to the PMC */ + (void)pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET, + pm_get_shutdown_scope(), SECURE_FLAG); + + while (1) { + wfi(); + } +} + +/** + * versal_pwr_domain_off() - This function performs actions to turn off core. + * @target_state: Targated state. + * + */ +static void versal_pwr_domain_off(const psci_power_state_t *target_state) +{ + uint32_t cpu_id = plat_my_core_pos(); + const struct pm_proc *proc = pm_get_proc(cpu_id); + + for (size_t i = 0U; i <= PLAT_MAX_PWR_LVL; i++) { + VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n", + __func__, i, target_state->pwr_domain_state[i]); + } + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_versal_gic_cpuif_disable(); + + /* + * Send request to PMC to power down the appropriate APU CPU + * core. + * According to PSCI specification, CPU_off function does not + * have resume address and CPU core can only be woken up + * invoking CPU_on function, during which resume address will + * be set. + */ + (void)pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0, + SECURE_FLAG); +} + +/** + * versal_validate_power_state() - This function ensures that the power state + * parameter in request is valid. + * @power_state: Power state of core. + * @req_state: Requested state. + * + * Return: Returns status, either success or reason. + * + */ +static int32_t versal_validate_power_state(uint32_t power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + uint32_t pstate = psci_get_pstate_type(power_state); + + assert(req_state); + + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + } else { + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE; + } + + /* We expect the 'state id' to be zero */ + if (psci_get_pstate_id(power_state) != 0U) { + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} + +/** + * versal_get_sys_suspend_power_state() - Get power state for system suspend. + * @req_state: Requested state. + * + */ +static void versal_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE; + req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE; +} + +static const struct plat_psci_ops versal_nopmc_psci_ops = { + .pwr_domain_on = versal_pwr_domain_on, + .pwr_domain_off = versal_pwr_domain_off, + .pwr_domain_on_finish = versal_pwr_domain_on_finish, + .pwr_domain_suspend = versal_pwr_domain_suspend, + .pwr_domain_suspend_finish = versal_pwr_domain_suspend_finish, + .system_off = versal_system_off, + .system_reset = versal_system_reset, + .validate_power_state = versal_validate_power_state, + .get_sys_suspend_power_state = versal_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + versal_sec_entry = sec_entrypoint; + + *psci_ops = &versal_nopmc_psci_ops; + + return 0; +} diff --git a/plat/xilinx/versal/plat_topology.c b/plat/xilinx/versal/plat_topology.c new file mode 100644 index 0000000..5f38599 --- /dev/null +++ b/plat/xilinx/versal/plat_topology.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +static const uint8_t plat_power_domain_tree_desc[] = {1, PLATFORM_CORE_COUNT}; + +const uint8_t *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c new file mode 100644 index 0000000..ba17b1d --- /dev/null +++ b/plat/xilinx/versal/plat_versal.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> + +#include <plat_private.h> + +int32_t plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if ((mpidr & MPIDR_CLUSTER_MASK) != 0U) { + return -1; + } + + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) { + return -1; + } + + return (int32_t)versal_calc_core_pos(mpidr); +} diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk new file mode 100644 index 0000000..7c53daa --- /dev/null +++ b/plat/xilinx/versal/platform.mk @@ -0,0 +1,118 @@ +# Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +override PROGRAMMABLE_RESET_ADDRESS := 1 +PSCI_EXTENDED_STATE_ID := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +SEPARATE_CODE_AND_RODATA := 1 +override RESET_TO_BL31 := 1 +PL011_GENERIC_UART := 1 +IPI_CRC_CHECK := 0 +HARDEN_SLS_ALL := 0 + +# A72 Erratum for SoC +ERRATA_A72_859971 := 1 +ERRATA_A72_1319367 := 1 + +ifdef VERSAL_ATF_MEM_BASE + $(eval $(call add_define,VERSAL_ATF_MEM_BASE)) + + ifndef VERSAL_ATF_MEM_SIZE + $(error "VERSAL_ATF_BASE defined without VERSAL_ATF_SIZE") + endif + $(eval $(call add_define,VERSAL_ATF_MEM_SIZE)) + + ifdef VERSAL_ATF_MEM_PROGBITS_SIZE + $(eval $(call add_define,VERSAL_ATF_MEM_PROGBITS_SIZE)) + endif +endif + +ifdef VERSAL_BL32_MEM_BASE + $(eval $(call add_define,VERSAL_BL32_MEM_BASE)) + + ifndef VERSAL_BL32_MEM_SIZE + $(error "VERSAL_BL32_BASE defined without VERSAL_BL32_SIZE") + endif + $(eval $(call add_define,VERSAL_BL32_MEM_SIZE)) +endif + +ifdef IPI_CRC_CHECK + $(eval $(call add_define,IPI_CRC_CHECK)) +endif + +VERSAL_PLATFORM ?= silicon +$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM})) + +ifdef XILINX_OF_BOARD_DTB_ADDR +$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR)) +endif + +PLAT_XLAT_TABLES_DYNAMIC := 0 +ifeq (${PLAT_XLAT_TABLES_DYNAMIC},1) +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) +endif + +# enable assert() for release/debug builds +ENABLE_ASSERTIONS := 1 + +PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ + -Iplat/xilinx/common/include/ \ + -Iplat/xilinx/common/ipi_mailbox_service/ \ + -Iplat/xilinx/versal/include/ \ + -Iplat/xilinx/versal/pm_service/ + +include lib/libfdt/libfdt.mk +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := drivers/arm/dcc/dcc_console.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + ${GICV3_SOURCES} \ + drivers/arm/pl011/aarch64/pl011_console.S \ + plat/common/aarch64/crash_console_helpers.S \ + plat/arm/common/arm_cci.c \ + plat/arm/common/arm_common.c \ + plat/common/plat_gicv3.c \ + plat/xilinx/versal/aarch64/versal_helpers.S \ + plat/xilinx/versal/aarch64/versal_common.c \ + ${XLAT_TABLES_LIB_SRCS} + +VERSAL_CONSOLE ?= pl011 +ifeq (${VERSAL_CONSOLE}, $(filter ${VERSAL_CONSOLE},pl011 pl011_0 pl011_1 dcc)) +else + $(error "Please define VERSAL_CONSOLE") +endif + +$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE})) + +BL31_SOURCES += drivers/arm/cci/cci.c \ + lib/cpus/aarch64/cortex_a72.S \ + common/fdt_wrappers.c \ + plat/common/plat_psci_common.c \ + plat/xilinx/common/ipi.c \ + plat/xilinx/common/plat_fdt.c \ + plat/xilinx/common/plat_console.c \ + plat/xilinx/common/plat_startup.c \ + plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \ + plat/xilinx/common/pm_service/pm_ipi.c \ + plat/xilinx/common/pm_service/pm_api_sys.c \ + plat/xilinx/common/pm_service/pm_svc_main.c \ + plat/xilinx/common/versal.c \ + plat/xilinx/versal/bl31_versal_setup.c \ + plat/xilinx/versal/plat_psci.c \ + plat/xilinx/versal/plat_versal.c \ + plat/xilinx/versal/plat_topology.c \ + plat/xilinx/versal/sip_svc_setup.c \ + plat/xilinx/versal/versal_gicv3.c \ + plat/xilinx/versal/versal_ipi.c \ + plat/xilinx/versal/pm_service/pm_client.c \ + common/fdt_fixup.c \ + ${LIBFDT_SRCS} + +ifeq ($(HARDEN_SLS_ALL), 1) +TF_CFLAGS_aarch64 += -mharden-sls=all +endif diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c new file mode 100644 index 0000000..ccbfe77 --- /dev/null +++ b/plat/xilinx/versal/pm_service/pm_client.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * APU specific definition of processors in the subsystem as well as functions + * for getting information about and changing state of the APU. + */ + +#include <assert.h> + +#include <drivers/arm/gic_common.h> +#include <drivers/arm/gicv3.h> +#include <lib/bakery_lock.h> +#include <lib/mmio.h> +#include <lib/utils.h> +#include <plat/common/platform.h> + +#include <plat_ipi.h> +#include <platform_def.h> +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_defs.h" +#include <versal_def.h> + +#define UNDEFINED_CPUID (~0) + +DEFINE_BAKERY_LOCK(pm_client_secure_lock); + +static const struct pm_ipi apu_ipi = { + .local_ipi_id = IPI_LOCAL_ID, + .remote_ipi_id = IPI_REMOTE_ID, + .buffer_base = IPI_BUFFER_LOCAL_BASE, +}; + +/* Order in pm_procs_all array must match cpu ids */ +static const struct pm_proc pm_procs_all[] = { + { + .node_id = XPM_DEVID_ACPU_0, + .ipi = &apu_ipi, + .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, + }, + { + .node_id = XPM_DEVID_ACPU_1, + .ipi = &apu_ipi, + .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, + } +}; + +const struct pm_proc *primary_proc = &pm_procs_all[0]; + +/** + * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number. + * @irq: Interrupt number + * + * Return: PM node index corresponding to the specified interrupt. + * + */ +enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq) +{ + enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN; + + assert(irq <= IRQ_MAX); + + switch (irq) { + case 13: + dev_idx = XPM_NODEIDX_DEV_GPIO; + break; + case 14: + dev_idx = XPM_NODEIDX_DEV_I2C_0; + break; + case 15: + dev_idx = XPM_NODEIDX_DEV_I2C_1; + break; + case 16: + dev_idx = XPM_NODEIDX_DEV_SPI_0; + break; + case 17: + dev_idx = XPM_NODEIDX_DEV_SPI_1; + break; + case 18: + dev_idx = XPM_NODEIDX_DEV_UART_0; + break; + case 19: + dev_idx = XPM_NODEIDX_DEV_UART_1; + break; + case 20: + dev_idx = XPM_NODEIDX_DEV_CAN_FD_0; + break; + case 21: + dev_idx = XPM_NODEIDX_DEV_CAN_FD_1; + break; + case 22: + case 23: + case 24: + case 25: + case 26: + dev_idx = XPM_NODEIDX_DEV_USB_0; + break; + case 37: + case 38: + case 39: + dev_idx = XPM_NODEIDX_DEV_TTC_0; + break; + case 40: + case 41: + case 42: + dev_idx = XPM_NODEIDX_DEV_TTC_1; + break; + case 43: + case 44: + case 45: + dev_idx = XPM_NODEIDX_DEV_TTC_2; + break; + case 46: + case 47: + case 48: + dev_idx = XPM_NODEIDX_DEV_TTC_3; + break; + case 56: + case 57: + dev_idx = XPM_NODEIDX_DEV_GEM_0; + break; + case 58: + case 59: + dev_idx = XPM_NODEIDX_DEV_GEM_1; + break; + case 60: + dev_idx = XPM_NODEIDX_DEV_ADMA_0; + break; + case 61: + dev_idx = XPM_NODEIDX_DEV_ADMA_1; + break; + case 62: + dev_idx = XPM_NODEIDX_DEV_ADMA_2; + break; + case 63: + dev_idx = XPM_NODEIDX_DEV_ADMA_3; + break; + case 64: + dev_idx = XPM_NODEIDX_DEV_ADMA_4; + break; + case 65: + dev_idx = XPM_NODEIDX_DEV_ADMA_5; + break; + case 66: + dev_idx = XPM_NODEIDX_DEV_ADMA_6; + break; + case 67: + dev_idx = XPM_NODEIDX_DEV_ADMA_7; + break; + case 74: + dev_idx = XPM_NODEIDX_DEV_USB_0; + break; + case 126: + case 127: + dev_idx = XPM_NODEIDX_DEV_SDIO_0; + break; + case 128: + case 129: + dev_idx = XPM_NODEIDX_DEV_SDIO_1; + break; + case 142: + dev_idx = XPM_NODEIDX_DEV_RTC; + break; + default: + dev_idx = XPM_NODEIDX_DEV_MIN; + break; + } + + return dev_idx; +} + +/** + * pm_client_suspend() - Client-specific suspend actions. + * @proc: processor which need to suspend. + * @state: desired suspend state. + * + * This function should contain any PU-specific actions + * required prior to sending suspend request to PMU + * Actions taken depend on the state system is suspending to. + * + */ +void pm_client_suspend(const struct pm_proc *proc, uint32_t state) +{ + bakery_lock_get(&pm_client_secure_lock); + + if (state == PM_STATE_SUSPEND_TO_RAM) { + pm_client_set_wakeup_sources((uint32_t)proc->node_id); + } + + /* Set powerdown request */ + mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | + (uint32_t)proc->pwrdn_mask); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_client_abort_suspend() - Client-specific abort-suspend actions. + * + * This function should contain any PU-specific actions + * required for aborting a prior suspend request. + * + */ +void pm_client_abort_suspend(void) +{ + /* Enable interrupts at processor level (for current cpu) */ + gicv3_cpuif_enable(plat_my_core_pos()); + + bakery_lock_get(&pm_client_secure_lock); + + /* Clear powerdown request */ + mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & + ~((uint32_t)primary_proc->pwrdn_mask)); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_get_cpuid() - get the local cpu ID for a global node ID. + * @nid: node id of the processor. + * + * Return: the cpu ID (starting from 0) for the subsystem. + * + */ +static uint32_t pm_get_cpuid(uint32_t nid) +{ + for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) { + if (pm_procs_all[i].node_id == nid) { + return i; + } + } + return UNDEFINED_CPUID; +} + +/** + * pm_client_wakeup() - Client-specific wakeup actions. + * @proc: Processor which need to wakeup. + * + * This function should contain any PU-specific actions + * required for waking up another APU core. + * + */ +void pm_client_wakeup(const struct pm_proc *proc) +{ + uint32_t cpuid = pm_get_cpuid(proc->node_id); + + if (cpuid == UNDEFINED_CPUID) { + return; + } + + bakery_lock_get(&pm_client_secure_lock); + + /* clear powerdown bit for affected cpu */ + uint32_t val = mmio_read_32(FPD_APU_PWRCTL); + val &= ~(proc->pwrdn_mask); + mmio_write_32(FPD_APU_PWRCTL, val); + + bakery_lock_release(&pm_client_secure_lock); +} + +/** + * pm_get_proc() - returns pointer to the proc structure. + * @cpuid: id of the cpu whose proc struct pointer should be returned. + * + * Return: pointer to a proc structure if proc is found, otherwise NULL. + * + */ +const struct pm_proc *pm_get_proc(uint32_t cpuid) +{ + if (cpuid < ARRAY_SIZE(pm_procs_all)) { + return &pm_procs_all[cpuid]; + } + + return NULL; +} diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c new file mode 100644 index 0000000..b30254d --- /dev/null +++ b/plat/xilinx/versal/sip_svc_setup.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */ + +#include <inttypes.h> + +#include <common/debug.h> +#include <common/runtime_svc.h> +#include <tools_share/uuid.h> + +#include "ipi_mailbox_svc.h" +#include "pm_svc_main.h" + +/* SMC function IDs for SiP Service queries */ +#define VERSAL_SIP_SVC_CALL_COUNT U(0x8200ff00) +#define VERSAL_SIP_SVC_UID U(0x8200ff01) +#define VERSAL_SIP_SVC_VERSION U(0x8200ff03) + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR U(0) +#define SIP_SVC_VERSION_MINOR U(1) + +/* These macros are used to identify PM calls from the SMC function ID */ +#define SIP_FID_MASK GENMASK(23, 16) +#define XLNX_FID_MASK GENMASK(23, 12) +#define PM_FID_VALUE 0u +#define IPI_FID_VALUE 0x1000u +#define is_pm_fid(_fid) (((_fid) & XLNX_FID_MASK) == PM_FID_VALUE) +#define is_ipi_fid(_fid) (((_fid) & XLNX_FID_MASK) == IPI_FID_VALUE) + +/* SiP Service UUID */ +DEFINE_SVC_UUID2(versal_sip_uuid, + 0x2ab9e4ecU, 0x93b9U, 0x11e7U, 0xa0U, 0x19U, + 0xdfU, 0xe0U, 0xdbU, 0xadU, 0x0aU, 0xe0U); + +/** + * sip_svc_setup() - Setup SiP Service + * + * Return: 0 on success,negative error code on failure. + * + * Invokes PM setup. + */ +static int32_t sip_svc_setup(void) +{ + /* PM implementation as SiP Service */ + (void)pm_setup(); + + return 0; +} + +/** + * sip_svc_smc_handler() - Top-level SiP Service SMC handler. + * @smc_fid: Function Identifier. + * @x1: SMC64 Arguments 1 from kernel. + * @x2: SMC64 Arguments 2 from kernel. + * @x3: SMC64 Arguments 3 from kernel(upper 32-bits). + * @x4: SMC64 Arguments 4 from kernel. + * @cookie: Unused + * @handle: Pointer to caller's context structure. + * @flags: SECURE_FLAG or NON_SECURE_FLAG. + * + * Handler for all SiP SMC calls. Handles standard SIP requests + * and calls PM SMC handler if the call is for a PM-API function. + * + * Return: Unused. + */ +uintptr_t sip_svc_smc_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + VERBOSE("SMCID: 0x%08x, x1: 0x%016" PRIx64 ", x2: 0x%016" PRIx64 ", x3: 0x%016" PRIx64 ", x4: 0x%016" PRIx64 "\n", + smc_fid, x1, x2, x3, x4); + + if (smc_fid & SIP_FID_MASK) { + WARN("SMC out of SiP assinged range: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } + + /* Let PM SMC handler deal with PM-related requests */ + if (is_pm_fid(smc_fid)) { + return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + + /* Let IPI SMC handler deal with IPI-related requests */ + if (is_ipi_fid(smc_fid)) { + return ipi_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } + + /* Let PM SMC handler deal with PM-related requests */ + switch (smc_fid) { + case VERSAL_SIP_SVC_CALL_COUNT: + /* PM functions + default functions */ + SMC_RET1(handle, 2); + + case VERSAL_SIP_SVC_UID: + SMC_UUID_RET(handle, versal_sip_uuid); + + case VERSAL_SIP_SVC_VERSION: + SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register PM Service Calls as runtime service */ +DECLARE_RT_SVC( + sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + sip_svc_setup, + sip_svc_smc_handler); diff --git a/plat/xilinx/versal/tsp/tsp-versal.mk b/plat/xilinx/versal/tsp/tsp-versal.mk new file mode 100644 index 0000000..bf32de3 --- /dev/null +++ b/plat/xilinx/versal/tsp/tsp-versal.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +# TSP source files specific to Versal platform + +PLAT_XILINX_COMMON := plat/xilinx/common/ + +include ${PLAT_XILINX_COMMON}/tsp/tsp.mk diff --git a/plat/xilinx/versal/versal_gicv3.c b/plat/xilinx/versal/versal_gicv3.c new file mode 100644 index 0000000..197d047 --- /dev/null +++ b/plat/xilinx/versal/versal_gicv3.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/interrupt_props.h> +#include <drivers/arm/gicv3.h> +#include <lib/utils.h> +#include <plat/common/platform.h> + +#include <plat_private.h> +#include <platform_def.h> + + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv3 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_versal_gic_driver_init +#pragma weak plat_versal_gic_init +#pragma weak plat_versal_gic_cpuif_enable +#pragma weak plat_versal_gic_cpuif_disable +#pragma weak plat_versal_gic_pcpu_init +#pragma weak plat_versal_gic_redistif_on +#pragma weak plat_versal_gic_redistif_off + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t versal_interrupt_props[] = { + PLAT_VERSAL_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_VERSAL_G0_IRQ_PROPS(INTR_GROUP0) +}; + +/* + * We save and restore the GICv3 context on system suspend. Allocate the + * data in the designated EL3 Secure carve-out memory. + */ +static gicv3_redist_ctx_t rdist_ctx __section(".versal_el3_tzc_dram"); +static gicv3_dist_ctx_t dist_ctx __section(".versal_el3_tzc_dram"); + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static uint32_t versal_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return versal_calc_core_pos(mpidr); +} + +static const gicv3_driver_data_t versal_gic_data __unused = { + .gicd_base = PLAT_GICD_BASE_VALUE, + .gicr_base = PLAT_GICR_BASE_VALUE, + .interrupt_props = versal_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(versal_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = versal_gicv3_mpidr_hash +}; + +void __init plat_versal_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if IMAGE_BL31 + gicv3_driver_init(&versal_gic_data); +#endif +} + +/****************************************************************************** + * Versal common helper to initialize the GIC. Only invoked by BL31 + *****************************************************************************/ +void __init plat_versal_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to enable the GIC CPU interface + *****************************************************************************/ +void plat_versal_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to disable the GIC CPU interface + *****************************************************************************/ +void plat_versal_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to initialize the per-cpu redistributor interface in + * GICv3 + *****************************************************************************/ +void plat_versal_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helpers to power GIC redistributor interface + *****************************************************************************/ +void plat_versal_gic_redistif_on(void) +{ + gicv3_rdistif_on(plat_my_core_pos()); +} + +void plat_versal_gic_redistif_off(void) +{ + gicv3_rdistif_off(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to save & restore the GICv3 on resume from system + * suspend + *****************************************************************************/ +void plat_versal_gic_save(void) +{ + /* + * If an ITS is available, save its context before + * the Redistributor using: + * gicv3_its_save_disable(gits_base, &its_ctx[i]) + * Additionnaly, an implementation-defined sequence may + * be required to save the whole ITS state. + */ + + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to save the context of the CPU that is issuing + * the SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); + + /* Save the GIC Distributor context */ + gicv3_distif_save(&dist_ctx); + + /* + * From here, all the components of the GIC can be safely powered down + * as long as there is an alternate way to handle wakeup interrupt + * sources. + */ +} + +void plat_versal_gic_resume(void) +{ + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(&dist_ctx); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to restore the context of the CPU that issued + * the SYSTEM SUSPEND call. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); + + /* + * If an ITS is available, restore its context after + * the Redistributor using: + * gicv3_its_restore(gits_base, &its_ctx[i]) + * An implementation-defined sequence may be required to + * restore the whole ITS state. The ITS must also be + * re-enabled after this sequence has been executed. + */ +} diff --git a/plat/xilinx/versal/versal_ipi.c b/plat/xilinx/versal/versal_ipi.c new file mode 100644 index 0000000..74b082d --- /dev/null +++ b/plat/xilinx/versal/versal_ipi.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Versal IPI agent registers access management + */ + +#include <lib/utils_def.h> + +#include <ipi.h> +#include <plat_ipi.h> + +/* versal ipi configuration table */ +static const struct ipi_config versal_ipi_table[] = { + /* PMC IPI */ + [IPI_ID_PMC] = { + .ipi_bit_mask = PMC_IPI_TRIG_BIT, + .ipi_reg_base = PMC_REG_BASE, + .secure_only = IPI_SECURE_MASK, + }, + + /* A72 IPI */ + [IPI_ID_APU] = { + .ipi_bit_mask = IPI0_TRIG_BIT, + .ipi_reg_base = IPI0_REG_BASE, + .secure_only = 0U, + }, + + /* RPU0 IPI */ + [IPI_ID_RPU0] = { + .ipi_bit_mask = IPI1_TRIG_BIT, + .ipi_reg_base = IPI1_REG_BASE, + .secure_only = 0U, + }, + + /* RPU1 IPI */ + [IPI_ID_RPU1] = { + .ipi_bit_mask = IPI2_TRIG_BIT, + .ipi_reg_base = IPI2_REG_BASE, + .secure_only = 0U, + }, + + /* IPI3 IPI */ + [IPI_ID_3] = { + .ipi_bit_mask = IPI3_TRIG_BIT, + .ipi_reg_base = IPI3_REG_BASE, + .secure_only = 0U, + }, + + /* IPI4 IPI */ + [IPI_ID_4] = { + .ipi_bit_mask = IPI4_TRIG_BIT, + .ipi_reg_base = IPI4_REG_BASE, + .secure_only = 0U, + }, + + /* IPI5 IPI */ + [IPI_ID_5] = { + .ipi_bit_mask = IPI5_TRIG_BIT, + .ipi_reg_base = IPI5_REG_BASE, + .secure_only = 0U, + }, +}; + +/* versal_ipi_config_table_init() - Initialize versal IPI configuration data. + * @ipi_config_table: IPI configuration table. + * @ipi_total: Total number of IPI available. + * + */ +void versal_ipi_config_table_init(void) +{ + ipi_config_table_init(versal_ipi_table, ARRAY_SIZE(versal_ipi_table)); +} |