feat(versal2): add support for AMD Versal Gen 2 platform

New SoC is a78 based with gicv3 and uart over pl011. Communication
interfaces are similar to Versal NET platform. System starts with AMD PLM
firmware which loads TF-A(bl31) to memory, which is already configured, and
jumps to it. PLM also prepare handoff structure for TF-A with information
what components were load and flags which indicate which EL level SW should
be started.

Change-Id: I5065b1b7ec4ee58e77dc4096747758480c84009c
Signed-off-by: Amit Nagal <amit.nagal@amd.com>
Signed-off-by: Akshay Belsare <akshay.belsare@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
This commit is contained in:
Amit Nagal 2024-06-05 12:32:38 +05:30 committed by Michal Šimek
parent c7d5e45d8f
commit c97857dba2
22 changed files with 2630 additions and 0 deletions

View file

@ -674,6 +674,13 @@ subsections:
- plat/zynqmp
- plat/xilinx/zynqmp
- title: AMD
scope: amd
subsections:
- title: Versal Gen 2
scope: versal2
- title: Nuvoton
scope: nuvoton

87
docs/plat/amd-versal2.rst Normal file
View file

@ -0,0 +1,87 @@
AMD Versal Gen 2
================
Trusted Firmware-A implements the EL3 firmware layer for AMD Versal Gen 2.
The platform only uses the runtime part of TF-A as AMD Versal Gen 2 already
has a BootROM (BL1) and PMC FW (BL2).
BL31 is TF-A.
BL32 is an optional Secure Payload.
BL33 is the non-secure world software (U-Boot, Linux etc).
To build:
```bash
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal2 bl31
```
To build TF-A for JTAG DCC console:
```bash
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal2 CONSOLE=dcc bl31
```
To build TF-A with Errata management interface
```bash
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal2 bl31 ERRATA_ABI_SUPPORT=1
```
To build TF-A with IPI CRC check:
```bash
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal2 bl31 IPI_CRC_CHECK=1
```
AMD Versal Gen 2 platform specific build options
-------------------------------------------------
* `MEM_BASE`: Specifies the base address of the bl31 binary.
* `MEM_SIZE`: Specifies the size of the memory region of the bl31 binary.
* `BL32_MEM_BASE`: Specifies the base address of the bl32 binary.
* `BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary.
* `CONSOLE`: Select the console driver. Options:
- `pl011`, `pl011_0`: ARM pl011 UART 0 (default)
- `pl011_1` : ARM pl011 UART 1
- `dcc` : JTAG Debug Communication Channel(DCC)
Reference DEN0028E SMC calling convention
------------------------------------------
Allocated subranges of Function Identifier to SIP services
------------------------------------------------------------
+-----------------------+-------------------------------------------------------+
| SMC Function | Identifier Service type |
+-----------------------+-------------------------------------------------------+
| 0xC2000000-0xC200FFFF | Fast SMC64 SiP Service Calls as per SMCCC Section 6.1 |
+-----------------------+-------------------------------------------------------+
IPI SMC call ranges
-------------------
+---------------------------+-----------------------------------------------------------+
| SMC Function Identifier | Service type |
+---------------------------+-----------------------------------------------------------+
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
PM SMC call ranges
------------------
+---------------------------+---------------------------------------------------------------------------+
| SMC Function Identifier | Service type |
+---------------------------+---------------------------------------------------------------------------+
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
SMC function IDs for SiP Service queries
----------------------------------------
+--------------+--------------+--------------+
| Service | Call UID | Revision |
+--------------+--------------+--------------+
| SiP Service | 0x8200_FF01 | 0x8200_FF03 |
+--------------+--------------+--------------+
Call UID Query Returns a unique identifier of the service provider.
Revision Query Returns revision details of the service implementor.

View file

@ -7,6 +7,7 @@ Platform Ports
:hidden:
allwinner
amd-versal2
arm/index
ast2700
meson-axg

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <common/runtime_svc.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 <def.h>
#include <plat_common.h>
#include <plat_ipi.h>
#include <plat_private.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_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(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(IPI_BASE, IPI_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
#if defined(TRANSFER_LIST)
MAP_REGION_FLAT(FW_HANDOFF_BASE, FW_HANDOFF_BASE + FW_HANDOFF_SIZE,
MT_MEMORY | MT_RW | MT_NS),
#endif
{ 0 }
};
const mmap_region_t *plat_get_mmap(void)
{
return plat_mmap;
}
/* For saving cpu clock for certain platform */
uint32_t cpu_clock;
const char *board_name_decode(void)
{
const char *platform;
switch (platform_id) {
case SPP:
platform = "IPP";
break;
case EMU:
platform = "EMU";
break;
case SILICON:
platform = "Silicon";
break;
case QEMU:
platform = "QEMU";
break;
default:
platform = "Unknown";
}
return platform;
}
void board_detection(void)
{
uint32_t version;
version = mmio_read_32(PMC_TAP_VERSION);
platform_id = FIELD_GET(PLATFORM_MASK, version);
platform_version = FIELD_GET(PLATFORM_VERSION_MASK, version);
if (platform_id == QEMU_COSIM) {
platform_id = QEMU;
}
/* Make sure that console is setup to see this message */
VERBOSE("Platform id: %d version: %d.%d\n", platform_id,
platform_version / 10U, platform_version % 10U);
}
uint32_t get_uart_clk(void)
{
uint32_t uart_clock = 0;
switch (platform_id) {
case SPP:
case SPP_MMD:
uart_clock = cpu_clock;
break;
case EMU:
case EMU_MMD:
uart_clock = 25000000;
break;
case QEMU:
/* Random values now */
uart_clock = 25000000;
break;
case SILICON:
uart_clock = 100000000;
break;
default:
panic();
}
return uart_clock;
}
void config_setup(void)
{
uint32_t val;
uintptr_t crl_base, iou_scntrs_base, psx_base;
crl_base = CRL;
iou_scntrs_base = IOU_SCNTRS;
psx_base = PSX_CRF;
/* Reset for system timestamp generator in FPX */
mmio_write_32(psx_base + PSX_CRF_RST_TIMESTAMP_OFFSET, 0);
/* Global timer init - Program time stamp reference clk */
val = mmio_read_32(crl_base + CRL_TIMESTAMP_REF_CTRL_OFFSET);
val |= CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
mmio_write_32(crl_base + CRL_TIMESTAMP_REF_CTRL_OFFSET, val);
/* Clear reset of timestamp reg */
mmio_write_32(crl_base + CRL_RST_TIMESTAMP_OFFSET, 0);
/* Program freq register in System counter and enable system counter. */
mmio_write_32(iou_scntrs_base + IOU_SCNTRS_BASE_FREQ_OFFSET,
cpu_clock);
mmio_write_32(iou_scntrs_base + IOU_SCNTRS_COUNTER_CONTROL_REG_OFFSET,
IOU_SCNTRS_CONTROL_EN);
generic_delay_timer_init();
/* Configure IPI data */
soc_ipi_config_table_init();
}
uint32_t plat_get_syscnt_freq2(void)
{
return cpu_clock;
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. 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 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, #PRIMARY_CPU
cset x0, eq
ret x9
endfunc plat_is_my_cpu_primary
/* -----------------------------------------------------
* unsigned int plat_my_core_pos(void)
* This function uses the plat_core_pos_by_mpidr()
* definition to get the index of the calling CPU.
* -----------------------------------------------------
*/
func plat_my_core_pos
mrs x0, mpidr_el1
b plat_core_pos_by_mpidr
endfunc plat_my_core_pos
/* ---------------------------------------------------------------------
* We don't need to carry out any memory initialization on platform
* The Secure RAM is accessible straight away.
* ---------------------------------------------------------------------
*/
func platform_mem_init
ret
endfunc platform_mem_init

View file

@ -0,0 +1,277 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, 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 <drivers/arm/dcc.h>
#include <drivers/arm/pl011.h>
#include <drivers/console.h>
#include <lib/cpus/cpu_ops.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <plat_arm.h>
#include <scmi.h>
#include <def.h>
#include <plat_fdt.h>
#include <plat_private.h>
#include <plat_startup.h>
#include <pm_api_sys.h>
#include <pm_client.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 = BL32_BASE;
bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
#if defined(SPD_opteed)
/* NS dtb addr passed to optee_os */
bl32_image_ep_info.args.arg3 = XILINX_OF_BOARD_DTB_ADDR;
#endif
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
bl33_image_ep_info.spsr = 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)
{
uint32_t uart_clock;
int32_t rc;
board_detection();
/* FIXME */
switch (platform_id) {
case SPP:
switch (platform_version) {
case SPP_PSXC_MMI_V2_0:
cpu_clock = 770000;
break;
case SPP_PSXC_MMI_V3_0:
cpu_clock = 908000;
break;
default:
panic();
}
break;
case SPP_MMD:
switch (platform_version) {
case SPP_PSXC_ISP_AIE_V2_0:
case SPP_PSXC_MMD_AIE_FRZ_EA:
case SPP_PSXC_MMD_AIE_V3_0:
cpu_clock = 760000;
break;
default:
panic();
}
break;
case EMU:
case EMU_MMD:
cpu_clock = 112203;
break;
case QEMU:
/* Random values now */
cpu_clock = 3333333;
break;
case SILICON:
cpu_clock = 100000000;
break;
default:
panic();
}
uart_clock = get_uart_clk();
if (CONSOLE_IS(pl011_0) || CONSOLE_IS(pl011_1)) {
static console_t _runtime_console;
/* Initialize the console to provide early debug support */
rc = console_pl011_register(UART_BASE, uart_clock,
UART_BAUDRATE,
&_runtime_console);
if (rc == 0) {
panic();
}
console_set_scope(&_runtime_console, CONSOLE_FLAG_BOOT |
CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
} else if (CONSOLE_IS(dcc)) {
/* Initialize the dcc console for debug.
* dcc is over jtag and does not configures uart0 or uart1.
*/
rc = console_dcc_register();
if (rc == 0) {
panic();
}
} else {
/* Making MISRA C 2012 15.7 compliant */
}
NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
platform_version / 10U, platform_version % 10U);
/* Initialize the platform config for future decision making */
config_setup();
/*
* Do initial security configuration to allow DRAM/device access. On
* Base 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);
bl31_set_default_config();
long rev_var = cpu_get_rev_var();
INFO("CPU Revision = 0x%lx\n", rev_var);
INFO("cpu_clock = %dHz, uart_clock = %dHz\n", cpu_clock, uart_clock);
NOTICE("BL31: Executing from 0x%x\n", BL31_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) {
(void)handler(intr_id, flags, handle, cookie);
}
return 0;
}
void bl31_platform_setup(void)
{
prepare_dtb();
/* Initialize the gic cpu and distributor interfaces */
plat_gic_driver_init();
plat_gic_init();
if (platform_id != EMU) {
init_scmi_server();
}
}
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();
}
}
/*
* Perform the very early platform specific architectural setup here.
*/
void bl31_plat_arch_setup(void)
{
const mmap_region_t bl_regions[] = {
#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
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(SMT_BUFFER_BASE, 0x1000,
MT_DEVICE | MT_RW | MT_NON_CACHEABLE | MT_EXECUTE_NEVER | MT_NS),
{0}
};
setup_page_tables(bl_regions, plat_get_mmap());
enable_mmu(0);
}

187
plat/amd/versal2/gicv3.c Normal file
View file

@ -0,0 +1,187 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <common/interrupt_props.h>
#include <drivers/arm/gicv3.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <plat_private.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_gic_driver_init
#pragma weak plat_gic_init
#pragma weak plat_gic_cpuif_enable
#pragma weak plat_gic_cpuif_disable
#pragma weak plat_gic_pcpu_init
#pragma weak plat_gic_redistif_on
#pragma weak plat_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 _interrupt_props[] = {
PLAT_G1S_IRQ_PROPS(INTR_GROUP1S),
PLAT_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("._el3_tzc_dram");
static gicv3_dist_ctx_t dist_ctx __section("._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 _gicv3_mpidr_hash(u_register_t mpidr)
{
mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
return plat_core_pos_by_mpidr(mpidr);
}
static const gicv3_driver_data_t _gic_data __unused = {
.gicd_base = PLAT_GICD_BASE_VALUE,
.gicr_base = PLAT_GICR_BASE_VALUE,
.interrupt_props = _interrupt_props,
.interrupt_props_num = ARRAY_SIZE(_interrupt_props),
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = rdistif_base_addrs,
.mpidr_to_core_pos = _gicv3_mpidr_hash
};
void __init plat_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(&_gic_data);
#endif
}
/******************************************************************************
* common helper to initialize the GIC. Only invoked by BL31
*****************************************************************************/
void __init plat_gic_init(void)
{
gicv3_distif_init();
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
}
/******************************************************************************
* common helper to enable the GIC CPU interface
*****************************************************************************/
void plat_gic_cpuif_enable(void)
{
gicv3_cpuif_enable(plat_my_core_pos());
}
/******************************************************************************
* common helper to disable the GIC CPU interface
*****************************************************************************/
void plat_gic_cpuif_disable(void)
{
gicv3_cpuif_disable(plat_my_core_pos());
}
/******************************************************************************
* common helper to initialize the per-cpu redistributor interface in GICv3
*****************************************************************************/
void plat_gic_pcpu_init(void)
{
gicv3_rdistif_init(plat_my_core_pos());
}
/******************************************************************************
* common helpers to power GIC redistributor interface
*****************************************************************************/
void plat_gic_redistif_on(void)
{
gicv3_rdistif_on(plat_my_core_pos());
}
void plat_gic_redistif_off(void)
{
gicv3_rdistif_off(plat_my_core_pos());
}
/******************************************************************************
* common helper to save & restore the GICv3 on resume from system suspend
*****************************************************************************/
void plat_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_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.
*/
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef DEF_H
#define DEF_H
#include <plat/arm/common/smccc_def.h>
#include <plat/common/common_def.h>
#define MAX_INTR_EL3 2
/* List all consoles */
#define CONSOLE_ID_pl011 U(1)
#define CONSOLE_ID_pl011_0 U(1)
#define CONSOLE_ID_pl011_1 U(2)
#define CONSOLE_ID_dcc U(3)
#define CONSOLE_IS(con) (CONSOLE_ID_ ## con == CONSOLE)
/* List all platforms */
#define SILICON U(0)
#define SPP U(1)
#define EMU U(2)
#define QEMU U(3)
#define SPP_MMD U(5)
#define EMU_MMD U(6)
#define QEMU_COSIM U(7)
/* For platform detection */
#define PMC_TAP U(0xF11A0000)
#define PMC_TAP_VERSION (PMC_TAP + 0x4U)
# define PLATFORM_MASK GENMASK(27U, 24U)
# define PLATFORM_VERSION_MASK GENMASK(31U, 28U)
/* Global timer reset */
#define PSX_CRF U(0xEC200000)
#define ACPU0_CLK_CTRL U(0x10C)
#define ACPU_CLK_CTRL_CLKACT BIT(25)
#define RST_APU0_OFFSET U(0x300)
#define RST_APU_COLD_RESET BIT(0)
#define RST_APU_WARN_RESET BIT(4)
#define RST_APU_CLUSTER_COLD_RESET BIT(8)
#define RST_APU_CLUSTER_WARM_RESET BIT(9)
#define PSX_CRF_RST_TIMESTAMP_OFFSET U(0x33C)
#define APU_PCLI (0xECB10000ULL)
#define APU_PCLI_CPU_STEP (0x30ULL)
#define APU_PCLI_CLUSTER_CPU_STEP (4ULL * APU_PCLI_CPU_STEP)
#define APU_PCLI_CLUSTER_OFFSET U(0x8000)
#define APU_PCLI_CLUSTER_STEP U(0x1000)
#define PCLI_PREQ_OFFSET U(0x4)
#define PREQ_CHANGE_REQUEST BIT(0)
#define PCLI_PSTATE_OFFSET U(0x8)
#define PCLI_PSTATE_VAL_SET U(0x48)
#define PCLI_PSTATE_VAL_CLEAR U(0x38)
/* Firmware Image Package */
#define PRIMARY_CPU U(0)
#define CORE_0_ISR_WAKE_OFFSET (0x00000020ULL)
#define APU_PCIL_CORE_X_ISR_WAKE_REG(cpu_id) (APU_PCLI + (CORE_0_ISR_WAKE_OFFSET + \
(APU_PCLI_CPU_STEP * (cpu_id))))
#define APU_PCIL_CORE_X_ISR_WAKE_MASK (0x00000001U)
#define CORE_0_IEN_WAKE_OFFSET (0x00000028ULL)
#define APU_PCIL_CORE_X_IEN_WAKE_REG(cpu_id) (APU_PCLI + (CORE_0_IEN_WAKE_OFFSET + \
(APU_PCLI_CPU_STEP * (cpu_id))))
#define APU_PCIL_CORE_X_IEN_WAKE_MASK (0x00000001U)
#define CORE_0_IDS_WAKE_OFFSET (0x0000002CULL)
#define APU_PCIL_CORE_X_IDS_WAKE_REG(cpu_id) (APU_PCLI + (CORE_0_IDS_WAKE_OFFSET + \
(APU_PCLI_CPU_STEP * (cpu_id))))
#define APU_PCIL_CORE_X_IDS_WAKE_MASK (0x00000001U)
#define CORE_0_ISR_POWER_OFFSET (0x00000010ULL)
#define APU_PCIL_CORE_X_ISR_POWER_REG(cpu_id) (APU_PCLI + (CORE_0_ISR_POWER_OFFSET + \
(APU_PCLI_CPU_STEP * (cpu_id))))
#define APU_PCIL_CORE_X_ISR_POWER_MASK U(0x00000001)
#define CORE_0_IEN_POWER_OFFSET (0x00000018ULL)
#define APU_PCIL_CORE_X_IEN_POWER_REG(cpu_id) (APU_PCLI + (CORE_0_IEN_POWER_OFFSET + \
(APU_PCLI_CPU_STEP * (cpu_id))))
#define APU_PCIL_CORE_X_IEN_POWER_MASK (0x00000001U)
#define CORE_0_IDS_POWER_OFFSET (0x0000001CULL)
#define APU_PCIL_CORE_X_IDS_POWER_REG(cpu_id) (APU_PCLI + (CORE_0_IDS_POWER_OFFSET + \
(APU_PCLI_CPU_STEP * (cpu_id))))
#define APU_PCIL_CORE_X_IDS_POWER_MASK (0x00000001U)
#define CORE_PWRDN_EN_BIT_MASK (0x1U)
/*******************************************************************************
* memory map related constants
******************************************************************************/
/* IPP 1.2/SPP 0.9 mapping */
#define DEVICE0_BASE U(0xE8000000) /* psx, crl, iou */
#define DEVICE0_SIZE U(0x08000000)
#define DEVICE1_BASE U(0xE2000000) /* gic */
#define DEVICE1_SIZE U(0x00800000)
#define DEVICE2_BASE U(0xF1000000) /* uart, pmc_tap */
#define DEVICE2_SIZE U(0x01000000)
#define CRF_BASE U(0xFD1A0000)
#define CRF_SIZE U(0x00600000)
#define IPI_BASE U(0xEB300000)
#define IPI_SIZE U(0x00100000)
/* CRL */
#define CRL U(0xEB5E0000)
#define CRL_TIMESTAMP_REF_CTRL_OFFSET U(0x14C)
#define CRL_RST_TIMESTAMP_OFFSET U(0x348)
#define CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1U << 25U)
/* IOU SCNTRS */
#define IOU_SCNTRS U(0xEC920000)
#define IOU_SCNTRS_COUNTER_CONTROL_REG_OFFSET U(0)
#define IOU_SCNTRS_BASE_FREQ_OFFSET U(0x20)
#define IOU_SCNTRS_CONTROL_EN U(1)
#define APU_CLUSTER0 U(0xECC00000)
#define APU_RVBAR_L_0 U(0x40)
#define APU_RVBAR_H_0 U(0x44)
#define APU_CLUSTER_STEP U(0x100000)
#define SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL U(0xF1060504)
/*******************************************************************************
* IRQ constants
******************************************************************************/
#define IRQ_SEC_PHY_TIMER U(29)
/*******************************************************************************
* UART related constants
******************************************************************************/
#define UART0_BASE U(0xF1920000)
#define UART1_BASE U(0xF1930000)
#define UART_BAUDRATE 115200
#if CONSOLE_IS(pl011_1)
#define UART_BASE UART1_BASE
#else
/* Default console is UART0 */
#define UART_BASE UART0_BASE
#endif
#endif /* DEF_H */

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* Versal Gen 2 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
#define IPI_ID_MAX 8U
/*********************************************************************
* IPI message buffers
********************************************************************/
#define IPI_BUFFER_BASEADDR (0xEB3F0000U)
#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 */
extern void soc_ipi_config_table_init(void);
/*******************************************************************************
* IPI registers and bitfields
******************************************************************************/
#define IPI0_REG_BASE (0xEB330000U)
#define IPI0_TRIG_BIT (1 << 2)
#define PMC_IPI_TRIG_BIT (1 << 1)
#define IPI1_REG_BASE (0xEB340000U)
#define IPI1_TRIG_BIT (1 << 3)
#define IPI2_REG_BASE (0xEB350000U)
#define IPI2_TRIG_BIT (1 << 4)
#define IPI3_REG_BASE (0xEB360000U)
#define IPI3_TRIG_BIT (1 << 5)
#define IPI4_REG_BASE (0xEB370000U)
#define IPI4_TRIG_BIT (1 << 6)
#define IPI5_REG_BASE (0xEB380000U)
#define IPI5_TRIG_BIT (1 << 7)
#endif /* PLAT_IPI_H */

View file

@ -0,0 +1,118 @@
/*
* Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, 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 platform.
* Expects: GICD base in x16, GICC base in x17
* Clobbers: x0 - x10, sp
* ---------------------------------------------
*/
.macro _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
/*
* Empty for now to handle more platforms variant.
* Uncomment it when versions are stable
*/
/*
mov_imm x17, PLAT_GICD_BASE_VALUE
mov_imm x16, PLAT_GICR_BASE_VALUE
_print_gic_regs
*/
.endm
#endif /* PLAT_MACROS_S */

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, 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 */

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, 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>
#define SPP_PSXC_MMI_V2_0 U(6)
#define SPP_PSXC_MMI_V3_0 U(8)
/* MMD */
#define SPP_PSXC_ISP_AIE_V2_0 U(3)
#define SPP_PSXC_MMD_AIE_FRZ_EA U(4)
#define SPP_PSXC_MMD_AIE_V3_0 U(5)
typedef struct versal_intr_info_type_el3 {
uint32_t id;
interrupt_type_handler_t handler;
} versal_intr_info_type_el3_t;
void config_setup(void);
uint32_t get_uart_clk(void);
const mmap_region_t *plat_get_mmap(void);
void plat_gic_driver_init(void);
void plat_gic_init(void);
void plat_gic_cpuif_enable(void);
void plat_gic_cpuif_disable(void);
void plat_gic_pcpu_init(void);
void plat_gic_save(void);
void plat_gic_resume(void);
void plat_gic_redistif_on(void);
void plat_gic_redistif_off(void);
extern uint32_t cpu_clock, platform_id, platform_version;
void board_detection(void);
const char *board_name_decode(void);
uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, void *cookie, void *handle, uint64_t flags);
int32_t sip_svc_setup_init(void);
/*
* Register handler to specific GIC entrance
* for INTR_TYPE_EL3 type of interrupt
*/
int request_intr_type_el3(uint32_t irq, interrupt_type_handler_t fiq_handler);
#endif /* PLAT_PRIVATE_H */

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, 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 "def.h"
/*******************************************************************************
* Generic platform constants
******************************************************************************/
/* Size of cacheable stacks */
#define PLATFORM_STACK_SIZE U(0x440)
#define PLATFORM_CLUSTER_COUNT U(4)
#define PLATFORM_CORE_COUNT_PER_CLUSTER U(2) /* 2 CPUs per cluster */
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * PLATFORM_CORE_COUNT_PER_CLUSTER)
#define PLAT_MAX_PWR_LVL U(2)
#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 MEM_BASE
# define BL31_BASE U(0xBBF00000)
# define BL31_LIMIT U(0xBC000000)
#else
# define BL31_BASE U(MEM_BASE)
# define BL31_LIMIT U(MEM_BASE + MEM_SIZE)
# ifdef MEM_PROGBITS_SIZE
# define BL31_PROGBITS_LIMIT U(MEM_BASE + \
MEM_PROGBITS_SIZE)
# endif
#endif
/*******************************************************************************
* BL32 specific defines.
******************************************************************************/
#ifndef BL32_MEM_BASE
# define BL32_BASE U(0x60000000)
# define BL32_LIMIT U(0x80000000)
#else
# define BL32_BASE U(BL32_MEM_BASE)
# define BL32_LIMIT U(BL32_MEM_BASE + 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 ARM_IRQ_SEC_PHY_TIMER U(29)
#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER
/*******************************************************************************
* Platform specific page table and MMU setup constants
******************************************************************************/
#define PLAT_DDR_LOWMEM_MAX U(0x80000000)
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32U)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32U)
#define XILINX_OF_BOARD_DTB_MAX_SIZE U(0x200000)
#define PLAT_OCM_BASE U(0xBBF00000)
#define PLAT_OCM_LIMIT U(0xBC000000)
#if defined(TRANSFER_LIST)
/*
* FIXME: This address should come from firmware before TF-A
* Having this to make sure the transfer list functionality works
*/
#define FW_HANDOFF_BASE U(0x70000000)
#define FW_HANDOFF_SIZE U(0x10000)
#endif
#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 11
#else
#define MAX_MMAP_REGIONS 10
#endif
#endif
#ifndef MAX_XLAT_TABLES
#define MAX_XLAT_TABLES U(12)
#endif
#define CACHE_WRITEBACK_SHIFT U(6)
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
#define PLAT_GICD_BASE_VALUE U(0xE2000000)
#define PLAT_GICR_BASE_VALUE U(0xE2060000)
/*
* 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_IPI_IRQ 89
#define PLAT_VERSAL_IPI_IRQ PLAT_IPI_IRQ
#define PLAT_G1S_IRQ_PROPS(grp) \
INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_LEVEL)
#define PLAT_G0_IRQ_PROPS(grp) \
INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_EDGE), \
#define IRQ_MAX 200U
#endif /* PLATFORM_DEF_H */

View file

@ -0,0 +1,20 @@
/*
* Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SCMI_H
#define SCMI_H
#include "versal2-scmi.h"
#define SIP_SCMI (0xC200ffffU)
#define SMT_BUFFER_BASE 0x7fffe000
void init_scmi_server(void);
#define SCMI_VENDOR "AMD"
#define SCMI_PRODUCT "Versal Gen 2"
#endif /* DEF_H */

View file

@ -0,0 +1,140 @@
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* Macros IDs for AMD Versal Gen 2
*
* Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* Michal Simek <michal.simek@amd.com>
*/
#ifndef _VERSAL2_SCMI_H
#define _VERSAL2_SCMI_H
#define CLK_GEM0_0 0
#define CLK_GEM0_1 1
#define CLK_GEM0_2 2
#define CLK_GEM0_3 3
#define CLK_GEM0_4 4
#define CLK_GEM1_0 5
#define CLK_GEM1_1 6
#define CLK_GEM1_2 7
#define CLK_GEM1_3 8
#define CLK_GEM1_4 9
#define CLK_SERIAL0_0 10
#define CLK_SERIAL0_1 11
#define CLK_SERIAL1_0 12
#define CLK_SERIAL1_1 13
#define CLK_UFS0_0 14
#define CLK_UFS0_1 15
#define CLK_UFS0_2 16
#define CLK_USB0_0 17
#define CLK_USB0_1 18
#define CLK_USB0_2 19
#define CLK_USB1_0 20
#define CLK_USB1_1 21
#define CLK_USB1_2 22
#define CLK_MMC0_0 23
#define CLK_MMC0_1 24
#define CLK_MMC0_2 25
#define CLK_MMC1_0 26
#define CLK_MMC1_1 27
#define CLK_MMC1_2 28
#define CLK_TTC0_0 29
#define CLK_TTC1_0 30
#define CLK_TTC2_0 31
#define CLK_TTC3_0 32
#define CLK_TTC4_0 33
#define CLK_TTC5_0 34
#define CLK_TTC6_0 35
#define CLK_TTC7_0 36
#define CLK_I2C0_0 37
#define CLK_I2C1_0 38
#define CLK_I2C2_0 39
#define CLK_I2C3_0 40
#define CLK_I2C4_0 41
#define CLK_I2C5_0 42
#define CLK_I2C6_0 43
#define CLK_I2C7_0 44
#define CLK_OSPI0_0 45
#define CLK_QSPI0_0 46
#define CLK_QSPI0_1 47
#define CLK_WWDT0_0 48
#define CLK_WWDT1_0 49
#define CLK_WWDT2_0 50
#define CLK_WWDT3_0 51
#define CLK_ADMA0_0 52
#define CLK_ADMA0_1 53
#define CLK_ADMA1_0 54
#define CLK_ADMA1_1 55
#define CLK_ADMA2_0 56
#define CLK_ADMA2_1 57
#define CLK_ADMA3_0 58
#define CLK_ADMA3_1 59
#define CLK_ADMA4_0 60
#define CLK_ADMA4_1 61
#define CLK_ADMA5_0 62
#define CLK_ADMA5_1 63
#define CLK_ADMA6_0 64
#define CLK_ADMA6_1 65
#define CLK_ADMA7_0 66
#define CLK_ADMA7_1 67
#define CLK_CAN0_0 68
#define CLK_CAN0_1 69
#define CLK_CAN1_0 70
#define CLK_CAN1_1 71
#define CLK_CAN2_0 72
#define CLK_CAN2_1 73
#define CLK_CAN3_0 74
#define CLK_CAN3_1 75
#define CLK_PS_GPIO_0 76
#define CLK_PMC_GPIO_0 77
#define CLK_SPI0_0 78
#define CLK_SPI0_1 79
#define CLK_SPI1_0 80
#define CLK_SPI1_1 81
#define CLK_I3C0_0 82
#define CLK_I3C1_0 83
#define CLK_I3C2_0 84
#define CLK_I3C3_0 85
#define CLK_I3C4_0 86
#define CLK_I3C5_0 87
#define CLK_I3C6_0 88
#define CLK_I3C7_0 89
#define RESET_GEM0_0 0
#define RESET_GEM1_0 1
#define RESET_SERIAL0_0 2
#define RESET_SERIAL1_0 3
#define RESET_UFS0_0 4
#define RESET_I2C0_0 5
#define RESET_I2C1_0 6
#define RESET_I2C2_0 7
#define RESET_I2C3_0 8
#define RESET_I2C4_0 9
#define RESET_I2C5_0 10
#define RESET_I2C6_0 11
#define RESET_I2C7_0 12
#define RESET_I2C8_0 13
#define RESET_OSPI0_0 14
#define RESET_USB0_0 15
#define RESET_USB0_1 16
#define RESET_USB0_2 17
#define RESET_USB1_0 18
#define RESET_USB1_1 19
#define RESET_USB1_2 20
#define RESET_MMC0_0 21
#define RESET_MMC1_0 22
#define RESET_SPI0_0 23
#define RESET_SPI1_0 24
#define RESET_QSPI0_0 25
#define RESET_I3C0_0 26
#define RESET_I3C1_0 27
#define RESET_I3C2_0 28
#define RESET_I3C3_0 29
#define RESET_I3C4_0 30
#define RESET_I3C5_0 31
#define RESET_I3C6_0 32
#define RESET_I3C7_0 33
#define RESET_I3C8_0 34
#endif /* _VERSAL2_SCMI_H */

View file

@ -0,0 +1,210 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <common/runtime_svc.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_defs.h>
#define PM_RET_ERROR_NOFEATURE U(19)
#define ALWAYSTRUE true
static uintptr_t _sec_entry;
static void zynqmp_cpu_standby(plat_local_state_t cpu_state)
{
dsb();
wfi();
}
#define MPIDR_MT_BIT (24)
static int32_t zynqmp_nopmu_pwr_domain_on(u_register_t mpidr)
{
uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr) & ~BIT(MPIDR_MT_BIT);
uint32_t cpu = cpu_id % PLATFORM_CORE_COUNT_PER_CLUSTER;
uint32_t cluster = cpu_id / PLATFORM_CORE_COUNT_PER_CLUSTER;
uintptr_t apu_cluster_base = 0, apu_pcli_base, apu_pcli_cluster = 0;
uintptr_t rst_apu_cluster = PSX_CRF + RST_APU0_OFFSET + ((uint64_t)cluster * 0x4U);
VERBOSE("%s: mpidr: 0x%lx, cpuid: %x, cpu: %x, cluster: %x\n",
__func__, mpidr, cpu_id, cpu, cluster);
if (cpu_id == -1) {
return PSCI_E_INTERN_FAIL;
}
if (cluster > 3) {
panic();
}
apu_pcli_cluster = APU_PCLI + APU_PCLI_CLUSTER_OFFSET + ((uint64_t)cluster * APU_PCLI_CLUSTER_STEP);
apu_cluster_base = APU_CLUSTER0 + ((uint64_t)cluster * APU_CLUSTER_STEP);
/* Enable clock */
mmio_setbits_32(PSX_CRF + ACPU0_CLK_CTRL + ((uint64_t)cluster * 0x4U), ACPU_CLK_CTRL_CLKACT);
/* Enable cluster states */
mmio_setbits_32(apu_pcli_cluster + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_SET);
mmio_setbits_32(apu_pcli_cluster + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
/* assert core reset */
mmio_setbits_32(rst_apu_cluster, ((RST_APU_COLD_RESET|RST_APU_WARN_RESET) << cpu));
/* program RVBAR */
mmio_write_32(apu_cluster_base + APU_RVBAR_L_0 + (cpu << 3),
(uint32_t)_sec_entry);
mmio_write_32(apu_cluster_base + APU_RVBAR_H_0 + (cpu << 3),
_sec_entry >> 32);
/* de-assert core reset */
mmio_clrbits_32(rst_apu_cluster, ((RST_APU_COLD_RESET|RST_APU_WARN_RESET) << cpu));
/* clear cluster resets */
mmio_clrbits_32(rst_apu_cluster, RST_APU_CLUSTER_WARM_RESET);
mmio_clrbits_32(rst_apu_cluster, RST_APU_CLUSTER_COLD_RESET);
apu_pcli_base = APU_PCLI + (APU_PCLI_CPU_STEP * cpu) +
(APU_PCLI_CLUSTER_CPU_STEP * cluster);
mmio_write_32(apu_pcli_base + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_CLEAR);
mmio_write_32(apu_pcli_base + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
return PSCI_E_SUCCESS;
}
static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state)
{
plat_gic_cpuif_disable();
}
static void __dead2 zynqmp_nopmu_system_reset(void)
{
while (ALWAYSTRUE) {
wfi();
}
}
static int32_t zynqmp_validate_ns_entrypoint(uint64_t ns_entrypoint)
{
VERBOSE("Validate ns_entry point %lx\n", ns_entrypoint);
if ((ns_entrypoint) != 0U) {
return PSCI_E_SUCCESS;
} else {
return PSCI_E_INVALID_ADDRESS;
}
}
static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
plat_gic_pcpu_init();
plat_gic_cpuif_enable();
}
static void __dead2 zynqmp_system_off(void)
{
while (ALWAYSTRUE) {
wfi();
}
}
static int32_t zynqmp_validate_power_state(uint32_t power_state, psci_power_state_t *req_state)
{
return PSCI_E_SUCCESS;
}
static const struct plat_psci_ops _nopmc_psci_ops = {
.cpu_standby = zynqmp_cpu_standby,
.pwr_domain_on = zynqmp_nopmu_pwr_domain_on,
.pwr_domain_off = zynqmp_nopmu_pwr_domain_off,
.system_reset = zynqmp_nopmu_system_reset,
.validate_ns_entrypoint = zynqmp_validate_ns_entrypoint,
.pwr_domain_on_finish = zynqmp_pwr_domain_on_finish,
.system_off = zynqmp_system_off,
.validate_power_state = zynqmp_validate_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)
{
_sec_entry = sec_entrypoint;
VERBOSE("Setting up entry point %lx\n", _sec_entry);
*psci_ops = &_nopmc_psci_ops;
return 0;
}
int sip_svc_setup_init(void)
{
return 0;
}
static int32_t no_pm_ioctl(uint32_t device_id, uint32_t ioctl_id,
uint32_t arg1, uint32_t arg2)
{
VERBOSE("%s: ioctl_id: %x, arg1: %x\n", __func__, ioctl_id, arg1);
if (ioctl_id == IOCTL_OSPI_MUX_SELECT) {
mmio_write_32(SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL, arg1);
return 0;
}
return PM_RET_ERROR_NOFEATURE;
}
static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
uint64_t x4, void *cookie, void *handle, uint64_t flags)
{
int32_t ret;
uint32_t arg[4], api_id;
arg[0] = (uint32_t)x1;
arg[1] = (uint32_t)(x1 >> 32);
arg[2] = (uint32_t)x2;
arg[3] = (uint32_t)(x2 >> 32);
api_id = smc_fid & FUNCID_NUM_MASK;
VERBOSE("%s: smc_fid: %x, api_id=0x%x\n", __func__, smc_fid, api_id);
switch (api_id) {
case PM_IOCTL:
{
ret = no_pm_ioctl(arg[0], arg[1], arg[2], arg[3]);
SMC_RET1(handle, (uint64_t)ret);
}
case PM_GET_CHIPID:
{
uint32_t idcode, version;
idcode = mmio_read_32(PMC_TAP);
version = mmio_read_32(PMC_TAP_VERSION);
SMC_RET2(handle, ((uint64_t)idcode << 32), version);
}
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
}
uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
void *cookie, void *handle, uint64_t flags)
{
return no_pm_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <plat_private.h>
static const uint8_t plat_power_domain_tree_desc[] = {
/* Number of root nodes */
1,
/* Number of clusters */
PLATFORM_CLUSTER_COUNT,
/* Number of children for the first cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER,
/* Number of children for the second cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER,
/* Number of children for the third cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER,
/* Number of children for the fourth cluster node */
PLATFORM_CORE_COUNT_PER_CLUSTER,
};
const uint8_t *plat_get_power_domain_tree_desc(void)
{
return plat_power_domain_tree_desc;
}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
* generic layer and the platform that allows the former to query the platform
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
* in case the MPIDR is invalid.
******************************************************************************/
int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
{
uint32_t cluster_id, cpu_id;
mpidr &= MPIDR_AFFINITY_MASK;
cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
return -3;
}
/*
* Validate cpu_id by checking whether it represents a CPU in
* one of the two clusters present on the platform.
*/
if (cpu_id >= PLATFORM_CORE_COUNT_PER_CLUSTER) {
return -1;
}
return (cpu_id + (cluster_id * PLATFORM_CORE_COUNT_PER_CLUSTER));
}

View file

@ -0,0 +1,127 @@
# Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
# Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
# Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
PLAT_PATH := plat/amd/versal2
# A78 Erratum for SoC
ERRATA_A78_AE_1941500 := 1
ERRATA_A78_AE_1951502 := 1
ERRATA_A78_AE_2376748 := 1
ERRATA_A78_AE_2395408 := 1
ERRATA_ABI_SUPPORT := 1
# Platform Supports Armv8.2 extensions
ARM_ARCH_MAJOR := 8
ARM_ARCH_MINOR := 2
override PROGRAMMABLE_RESET_ADDRESS := 1
PSCI_EXTENDED_STATE_ID := 1
SEPARATE_CODE_AND_RODATA := 1
override RESET_TO_BL31 := 1
PL011_GENERIC_UART := 1
IPI_CRC_CHECK := 0
GIC_ENABLE_V4_EXTN := 0
GICV3_SUPPORT_GIC600 := 1
override CTX_INCLUDE_AARCH32_REGS := 0
ifdef MEM_BASE
$(eval $(call add_define,MEM_BASE))
ifndef MEM_SIZE
$(error "ATF_BASE defined without ATF_SIZE")
endif
$(eval $(call add_define,MEM_SIZE))
ifdef MEM_PROGBITS_SIZE
$(eval $(call add_define,MEM_PROGBITS_SIZE))
endif
endif
ifdef BL32_MEM_BASE
$(eval $(call add_define,BL32_MEM_BASE))
ifndef BL32_MEM_SIZE
$(error "BL32_BASE defined without BL32_SIZE")
endif
$(eval $(call add_define,BL32_MEM_SIZE))
endif
ifdef IPI_CRC_CHECK
$(eval $(call add_define,IPI_CRC_CHECK))
endif
USE_COHERENT_MEM := 0
HW_ASSISTED_COHERENCY := 1
CONSOLE ?= pl011
ifeq (${CONSOLE}, $(filter ${CONSOLE},pl011 pl011_0 pl011_1 dcc))
else
$(error Please define CONSOLE)
endif
$(eval $(call add_define_val,CONSOLE,CONSOLE_ID_${CONSOLE}))
ifdef XILINX_OF_BOARD_DTB_ADDR
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
endif
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
-Iplat/xilinx/common/include/ \
-Iplat/xilinx/common/ipi_mailbox_service/ \
-I${PLAT_PATH}/include/ \
-Iplat/xilinx/versal/pm_service/
# Include GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk
include lib/xlat_tables_v2/xlat_tables.mk
include lib/libfdt/libfdt.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_common.c \
plat/common/plat_gicv3.c \
${PLAT_PATH}/aarch64/helpers.S \
${PLAT_PATH}/aarch64/common.c \
${PLAT_PATH}/plat_topology.c \
${XLAT_TABLES_LIB_SRCS}
BL31_SOURCES += drivers/arm/cci/cci.c \
lib/cpus/aarch64/cortex_a78_ae.S \
lib/cpus/aarch64/cortex_a78.S \
plat/common/plat_psci_common.c \
drivers/scmi-msg/base.c \
drivers/scmi-msg/entry.c \
drivers/scmi-msg/smt.c \
drivers/scmi-msg/clock.c \
drivers/scmi-msg/power_domain.c \
drivers/scmi-msg/reset_domain.c \
${PLAT_PATH}/scmi.c
BL31_SOURCES += ${PLAT_PATH}/plat_psci.c
BL31_SOURCES += plat/xilinx/common/plat_fdt.c \
plat/xilinx/common/plat_startup.c \
plat/xilinx/common/ipi.c \
plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \
${PLAT_PATH}/soc_ipi.c \
plat/xilinx/common/versal.c \
${PLAT_PATH}/bl31_setup.c \
common/fdt_fixup.c \
${LIBFDT_SRCS} \
${PLAT_PATH}/sip_svc_setup.c \
${PLAT_PATH}/gicv3.c
ifeq (${ERRATA_ABI_SUPPORT}, 1)
# enable the cpu macros for errata abi interface
CORTEX_A78_AE_H_INC := 1
$(eval $(call add_define, CORTEX_A78_AE_H_INC))
endif

531
plat/amd/versal2/scmi.c Normal file
View file

@ -0,0 +1,531 @@
/*
* Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <drivers/scmi-msg.h>
#include <drivers/scmi.h>
#include <lib/utils_def.h>
#include <platform_def.h>
#include <scmi.h>
#include "plat_private.h"
#define HIGH (1)
#define LOW (0)
struct scmi_clk {
unsigned long clock_id;
unsigned long rate;
const char *name;
bool enabled;
};
#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled, _rate) \
[_scmi_id] = { \
.clock_id = (_id), \
.name = (_name), \
.enabled = (_init_enabled), \
.rate = (_rate), \
}
static struct scmi_clk scmi0_clock[] = {
CLOCK_CELL(CLK_GEM0_0, CLK_GEM0_0, "gem0_pclk", true, 100000000),
CLOCK_CELL(CLK_GEM0_1, CLK_GEM0_1, "gem0_hclk", true, 100000000),
CLOCK_CELL(CLK_GEM0_2, CLK_GEM0_2, "gem0_tx_clk", true, 125000000),
CLOCK_CELL(CLK_GEM0_3, CLK_GEM0_3, "gem0_rx_clk", true, 100000000),
CLOCK_CELL(CLK_GEM0_4, CLK_GEM0_4, "gem0_tsu_clk", true, 100000000),
CLOCK_CELL(CLK_GEM1_0, CLK_GEM1_0, "gem1_pclk", true, 100000000),
CLOCK_CELL(CLK_GEM1_1, CLK_GEM1_1, "gem1_hclk", true, 100000000),
CLOCK_CELL(CLK_GEM1_2, CLK_GEM1_2, "gem1_tx_clk", true, 125000000),
CLOCK_CELL(CLK_GEM1_3, CLK_GEM1_3, "gem1_rx_clk", true, 100000000),
CLOCK_CELL(CLK_GEM1_4, CLK_GEM1_4, "gem1_tsu_clk", true, 100000000),
CLOCK_CELL(CLK_SERIAL0_0, CLK_SERIAL0_0, "uart0_uartclk", true, 100000000),
CLOCK_CELL(CLK_SERIAL0_1, CLK_SERIAL0_1, "uart0_apb_pclk", true, 100000000),
CLOCK_CELL(CLK_SERIAL1_0, CLK_SERIAL1_0, "uart1_uartclk", true, 100000000),
CLOCK_CELL(CLK_SERIAL1_1, CLK_SERIAL1_1, "uart1_apb_pclk", true, 100000000),
CLOCK_CELL(CLK_UFS0_0, CLK_UFS0_0, "ufs_core_clk", true, 100000000),
CLOCK_CELL(CLK_UFS0_1, CLK_UFS0_1, "ufs_phy_clk", true, 100000000),
CLOCK_CELL(CLK_UFS0_2, CLK_UFS0_2, "ufs_ref_pclk", true, 100000000),
CLOCK_CELL(CLK_USB0_0, CLK_USB0_0, "usb0_bus_clk", true, 100000000),
CLOCK_CELL(CLK_USB0_1, CLK_USB0_1, "usb0_ref_clk", true, 100000000),
CLOCK_CELL(CLK_USB0_2, CLK_USB0_2, "usb0_dwc_clk", true, 100000000),
CLOCK_CELL(CLK_USB1_0, CLK_USB1_0, "usb1_bus_clk", true, 100000000),
CLOCK_CELL(CLK_USB1_1, CLK_USB1_1, "usb1_ref_clk", true, 100000000),
CLOCK_CELL(CLK_USB1_2, CLK_USB1_2, "usb1_dwc_clk", true, 100000000),
CLOCK_CELL(CLK_MMC0_0, CLK_MMC0_0, "mmc0_xin_clk", true, 100000000),
CLOCK_CELL(CLK_MMC0_1, CLK_MMC0_1, "mmc0_ahb_clk", true, 100000000),
CLOCK_CELL(CLK_MMC0_2, CLK_MMC0_2, "mmc0_gate_clk", true, 100000000),
CLOCK_CELL(CLK_MMC1_0, CLK_MMC1_0, "mmc1_xin_clk", true, 100000000),
CLOCK_CELL(CLK_MMC1_1, CLK_MMC1_1, "mmc1_ahb_clk", true, 100000000),
CLOCK_CELL(CLK_MMC1_2, CLK_MMC1_2, "mmc1_gate_clk", true, 100000000),
CLOCK_CELL(CLK_TTC0_0, CLK_TTC0_0, "ttc0_clk", true, 100000000),
CLOCK_CELL(CLK_TTC1_0, CLK_TTC1_0, "ttc1_clk", true, 100000000),
CLOCK_CELL(CLK_TTC2_0, CLK_TTC2_0, "ttc2_clk", true, 100000000),
CLOCK_CELL(CLK_TTC3_0, CLK_TTC3_0, "ttc3_clk", true, 100000000),
CLOCK_CELL(CLK_TTC4_0, CLK_TTC4_0, "ttc4_clk", true, 100000000),
CLOCK_CELL(CLK_TTC5_0, CLK_TTC5_0, "ttc5_clk", true, 100000000),
CLOCK_CELL(CLK_TTC6_0, CLK_TTC6_0, "ttc6_clk", true, 100000000),
CLOCK_CELL(CLK_TTC7_0, CLK_TTC7_0, "ttc7_clk", true, 100000000),
CLOCK_CELL(CLK_I2C0_0, CLK_I2C0_0, "i2c0_clk", true, 100000000),
CLOCK_CELL(CLK_I2C1_0, CLK_I2C1_0, "i2c1_clk", true, 100000000),
CLOCK_CELL(CLK_I2C2_0, CLK_I2C2_0, "i2c2_clk", true, 100000000),
CLOCK_CELL(CLK_I2C3_0, CLK_I2C3_0, "i2c3_clk", true, 100000000),
CLOCK_CELL(CLK_I2C4_0, CLK_I2C4_0, "i2c4_clk", true, 100000000),
CLOCK_CELL(CLK_I2C5_0, CLK_I2C5_0, "i2c5_clk", true, 100000000),
CLOCK_CELL(CLK_I2C6_0, CLK_I2C6_0, "i2c6_clk", true, 100000000),
CLOCK_CELL(CLK_I2C7_0, CLK_I2C7_0, "i2c7_clk", true, 100000000),
CLOCK_CELL(CLK_OSPI0_0, CLK_OSPI0_0, "ospi0_clk", true, 100000000),
CLOCK_CELL(CLK_QSPI0_0, CLK_QSPI0_0, "qpsi0_ref_clk", true, 100000000),
CLOCK_CELL(CLK_QSPI0_1, CLK_QSPI0_1, "qspi0_pclk", true, 100000000),
CLOCK_CELL(CLK_WWDT0_0, CLK_WWDT0_0, "wwdt0_clk", true, 100000000),
CLOCK_CELL(CLK_WWDT1_0, CLK_WWDT1_0, "wwdt1_clk", true, 100000000),
CLOCK_CELL(CLK_WWDT2_0, CLK_WWDT2_0, "wwdt2_clk", true, 100000000),
CLOCK_CELL(CLK_WWDT3_0, CLK_WWDT3_0, "wwdt3_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA0_0, CLK_ADMA0_0, "adma0_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA0_1, CLK_ADMA0_1, "adma0_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA1_0, CLK_ADMA1_0, "adma1_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA1_1, CLK_ADMA1_1, "adma1_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA2_0, CLK_ADMA2_0, "adma2_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA2_1, CLK_ADMA2_1, "adma2_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA3_0, CLK_ADMA3_0, "adma3_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA3_1, CLK_ADMA3_1, "adma3_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA4_0, CLK_ADMA4_0, "adma4_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA4_1, CLK_ADMA4_1, "adma4_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA5_0, CLK_ADMA5_0, "adma5_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA5_1, CLK_ADMA5_1, "adma5_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA6_0, CLK_ADMA6_0, "adma6_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA6_1, CLK_ADMA6_1, "adma6_apb_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA7_0, CLK_ADMA7_0, "adma7_main_clk", true, 100000000),
CLOCK_CELL(CLK_ADMA7_1, CLK_ADMA7_1, "adma7_apb_clk", true, 100000000),
CLOCK_CELL(CLK_CAN0_0, CLK_CAN0_0, "can0_can_clk", true, 100000000),
CLOCK_CELL(CLK_CAN0_1, CLK_CAN0_1, "can0_axi_clk", true, 100000000),
CLOCK_CELL(CLK_CAN1_0, CLK_CAN1_0, "can1_can_clk", true, 100000000),
CLOCK_CELL(CLK_CAN1_1, CLK_CAN1_1, "can1_axi_clk", true, 100000000),
CLOCK_CELL(CLK_CAN2_0, CLK_CAN2_0, "can2_can_clk", true, 100000000),
CLOCK_CELL(CLK_CAN2_1, CLK_CAN2_1, "can2_axi_clk", true, 100000000),
CLOCK_CELL(CLK_CAN3_0, CLK_CAN3_0, "can3_can_clk", true, 100000000),
CLOCK_CELL(CLK_CAN3_1, CLK_CAN3_1, "can3_axi_clk", true, 100000000),
CLOCK_CELL(CLK_PS_GPIO_0, CLK_PS_GPIO_0, "ps_gpio_clk", true, 100000000),
CLOCK_CELL(CLK_PMC_GPIO_0, CLK_PMC_GPIO_0, "pmc_gpio_clk", true, 100000000),
CLOCK_CELL(CLK_SPI0_0, CLK_SPI0_0, "spi0_ref_clk", true, 100000000),
CLOCK_CELL(CLK_SPI0_1, CLK_SPI0_1, "spi0_pclk", true, 100000000),
CLOCK_CELL(CLK_SPI1_0, CLK_SPI1_0, "spi1_ref_clk", true, 100000000),
CLOCK_CELL(CLK_SPI1_1, CLK_SPI1_1, "spi1_pclk", true, 100000000),
CLOCK_CELL(CLK_I3C0_0, CLK_I3C0_0, "i3c0_clk", true, 100000000),
CLOCK_CELL(CLK_I3C1_0, CLK_I3C1_0, "i3c1_clk", true, 100000000),
CLOCK_CELL(CLK_I3C2_0, CLK_I3C2_0, "i3c2_clk", true, 100000000),
CLOCK_CELL(CLK_I3C3_0, CLK_I3C3_0, "i3c3_clk", true, 100000000),
CLOCK_CELL(CLK_I3C4_0, CLK_I3C4_0, "i3c4_clk", true, 100000000),
CLOCK_CELL(CLK_I3C5_0, CLK_I3C5_0, "i3c5_clk", true, 100000000),
CLOCK_CELL(CLK_I3C6_0, CLK_I3C6_0, "i3c6_clk", true, 100000000),
CLOCK_CELL(CLK_I3C7_0, CLK_I3C7_0, "i3c7_clk", true, 100000000),
};
/*
* struct scmi_reset - Data for the exposed reset controller
* @reset_id: Reset identifier in RCC reset driver
* @name: Reset string ID exposed to agent
*/
struct scmi_reset {
unsigned long reset_id;
const char *name;
};
#define RESET_CELL(_scmi_id, _id, _name) \
[_scmi_id] = { \
.reset_id = (_id), \
.name = (_name), \
}
static struct scmi_reset scmi0_reset[] = {
RESET_CELL(RESET_GEM0_0, RESET_GEM0_0, "gem0"),
RESET_CELL(RESET_GEM1_0, RESET_GEM1_0, "gem1"),
RESET_CELL(RESET_SERIAL0_0, RESET_SERIAL0_0, "serial0"),
RESET_CELL(RESET_SERIAL1_0, RESET_SERIAL1_0, "serial1"),
RESET_CELL(RESET_UFS0_0, RESET_UFS0_0, "ufs0"),
RESET_CELL(RESET_I2C0_0, RESET_I2C0_0, "i2c0"),
RESET_CELL(RESET_I2C1_0, RESET_I2C1_0, "i2c1"),
RESET_CELL(RESET_I2C2_0, RESET_I2C2_0, "i2c2"),
RESET_CELL(RESET_I2C3_0, RESET_I2C3_0, "i2c3"),
RESET_CELL(RESET_I2C4_0, RESET_I2C4_0, "i2c4"),
RESET_CELL(RESET_I2C5_0, RESET_I2C5_0, "i2c5"),
RESET_CELL(RESET_I2C6_0, RESET_I2C6_0, "i2c6"),
RESET_CELL(RESET_I2C7_0, RESET_I2C7_0, "i2c7"),
RESET_CELL(RESET_I2C8_0, RESET_I2C8_0, "i2c8"),
RESET_CELL(RESET_OSPI0_0, RESET_OSPI0_0, "ospi"),
RESET_CELL(RESET_USB0_0, RESET_USB0_0, "usb0_0"),
RESET_CELL(RESET_USB0_1, RESET_USB0_1, "usb0_1"),
RESET_CELL(RESET_USB0_2, RESET_USB0_2, "usb0_2"),
RESET_CELL(RESET_USB1_0, RESET_USB1_0, "usb1_0"),
RESET_CELL(RESET_USB1_1, RESET_USB1_1, "usb1_1"),
RESET_CELL(RESET_USB1_2, RESET_USB1_2, "usb1_2"),
RESET_CELL(RESET_MMC0_0, RESET_MMC0_0, "mmc0"),
RESET_CELL(RESET_MMC1_0, RESET_MMC1_0, "mmc1"),
RESET_CELL(RESET_SPI0_0, RESET_SPI0_0, "spi0"),
RESET_CELL(RESET_SPI1_0, RESET_SPI1_0, "spi1"),
RESET_CELL(RESET_QSPI0_0, RESET_QSPI0_0, "qspi"),
RESET_CELL(RESET_I3C0_0, RESET_I3C0_0, "i3c0"),
RESET_CELL(RESET_I3C1_0, RESET_I3C1_0, "i3c1"),
RESET_CELL(RESET_I3C2_0, RESET_I3C2_0, "i3c2"),
RESET_CELL(RESET_I3C3_0, RESET_I3C3_0, "i3c3"),
RESET_CELL(RESET_I3C4_0, RESET_I3C4_0, "i3c4"),
RESET_CELL(RESET_I3C5_0, RESET_I3C5_0, "i3c5"),
RESET_CELL(RESET_I3C6_0, RESET_I3C6_0, "i3c6"),
RESET_CELL(RESET_I3C7_0, RESET_I3C7_0, "i3c7"),
RESET_CELL(RESET_I3C8_0, RESET_I3C8_0, "i3c8"),
};
struct scmi_resources {
struct scmi_clk *clock;
size_t clock_count;
struct scmi_reset *reset;
size_t reset_count;
};
static const struct scmi_resources resources[] = {
[0] = {
.clock = scmi0_clock,
.clock_count = ARRAY_SIZE(scmi0_clock),
.reset = scmi0_reset,
.reset_count = ARRAY_SIZE(scmi0_reset),
},
};
static const struct scmi_resources *find_resource(unsigned int agent_id)
{
assert(agent_id < ARRAY_SIZE(resources));
return &resources[agent_id];
}
static struct scmi_clk *clk_find(unsigned int agent_id, unsigned int scmi_id)
{
const struct scmi_resources *resource = find_resource(agent_id);
size_t n = 0U;
struct scmi_clk *ret = NULL;
if (resource != NULL) {
for (n = 0U; n < resource->clock_count; n++) {
if (n == scmi_id) {
ret = &resource->clock[n];
break;
}
}
}
return ret;
}
size_t plat_scmi_clock_count(unsigned int agent_id)
{
const struct scmi_resources *resource = find_resource(agent_id);
size_t ret;
if (resource == NULL) {
ret = 0U;
} else {
VERBOSE("SCMI: CLK: %d clocks\n", (unsigned int)resource->clock_count);
ret = resource->clock_count;
}
return ret;
}
const char *plat_scmi_clock_get_name(unsigned int agent_id, unsigned int scmi_id)
{
struct scmi_clk *clock = clk_find(agent_id, scmi_id);
const char *ret;
if (clock == NULL) {
ret = NULL;
} else {
VERBOSE("SCMI: CLK: id: %d, get_name: %s\n", scmi_id, clock->name);
ret = clock->name;
}
return ret;
};
/* Called by Linux */
int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
unsigned long *array, size_t *nb_elts,
uint32_t start_idx)
{
struct scmi_clk *clock = clk_find(agent_id, scmi_id);
if (clock == NULL) {
return SCMI_NOT_FOUND;
}
if (start_idx > 0) {
return SCMI_OUT_OF_RANGE;
}
if (array == NULL) {
*nb_elts = 1U;
} else if (*nb_elts == 1U) {
*array = clock->rate;
VERBOSE("SCMI: CLK: id: %d, clk_name: %s, get_rate %lu\n",
scmi_id, clock->name, *array);
} else {
return SCMI_GENERIC_ERROR;
}
return SCMI_SUCCESS;
}
unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, unsigned int scmi_id)
{
struct scmi_clk *clock = clk_find(agent_id, scmi_id);
unsigned long ret;
if ((clock == NULL)) {
ret = SCMI_NOT_FOUND;
} else {
VERBOSE("SCMI: CLK: id: %d, get_rate: %lu\n", scmi_id, clock->rate);
ret = clock->rate;
}
return ret;
}
int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id,
unsigned long rate)
{
struct scmi_clk *clock = clk_find(agent_id, scmi_id);
unsigned long ret = UL(SCMI_SUCCESS);
if ((clock == NULL)) {
ret = SCMI_NOT_FOUND;
} else {
VERBOSE("SCMI: CLK: id: %d, set_rate: %lu\n", scmi_id, rate);
clock->rate = rate;
}
return ret;
}
int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
{
struct scmi_clk *clock = clk_find(agent_id, scmi_id);
int32_t ret;
if ((clock == NULL)) {
ret = SCMI_NOT_FOUND;
} else {
VERBOSE("SCMI: CLK: id: %d, get_state: %d\n", scmi_id, clock->enabled);
if (clock->enabled) {
ret = HIGH;
} else {
ret = LOW;
}
}
return ret;
}
int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
bool enable_not_disable)
{
struct scmi_clk *clock = clk_find(agent_id, scmi_id);
int32_t ret;
if (clock == NULL) {
ret = SCMI_NOT_FOUND;
} else {
if (enable_not_disable) {
if (!clock->enabled) {
VERBOSE("SCMI: clock: %u enable\n", scmi_id);
clock->enabled = true;
}
} else {
if (clock->enabled) {
VERBOSE("SCMI: clock: %u disable\n", scmi_id);
clock->enabled = false;
}
}
VERBOSE("SCMI: CLK: id: %d, set_state: %d\n", scmi_id, clock->enabled);
ret = SCMI_SUCCESS;
}
return ret;
}
/*
* Platform SCMI reset domains
*/
static struct scmi_reset *find_reset(unsigned int agent_id,
unsigned int scmi_id)
{
const struct scmi_resources *resource = find_resource(agent_id);
size_t n;
if (resource != NULL) {
for (n = 0U; n < resource->reset_count; n++) {
if (n == scmi_id) {
return &resource->reset[n];
}
}
}
return NULL;
}
const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
{
const struct scmi_reset *reset = find_reset(agent_id, scmi_id);
if (reset == NULL) {
return NULL;
}
return reset->name;
}
size_t plat_scmi_rstd_count(unsigned int agent_id)
{
const struct scmi_resources *resource = find_resource(agent_id);
if (resource == NULL) {
return 0U;
}
return resource->reset_count;
}
int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
uint32_t state)
{
const struct scmi_reset *reset = find_reset(agent_id, scmi_id);
if (reset == NULL) {
return SCMI_NOT_FOUND;
}
/* Supports only reset with context loss */
if (state != 0U) {
return SCMI_NOT_SUPPORTED;
}
NOTICE("SCMI reset on ID %lu/%s\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
return SCMI_SUCCESS;
}
int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
bool assert_not_deassert)
{
const struct scmi_reset *reset = find_reset(agent_id, scmi_id);
if (reset == NULL) {
return SCMI_NOT_FOUND;
}
if (assert_not_deassert) {
NOTICE("SCMI reset %lu/%s set\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
} else {
NOTICE("SCMI reset %lu/%s release\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
}
return SCMI_SUCCESS;
}
/* Currently only one channel is supported. Expectation is that channel 0 is used by NS SW */
static struct scmi_msg_channel scmi_channel[] = {
[0] = {
.shm_addr = SMT_BUFFER_BASE,
.shm_size = SMT_BUF_SLOT_SIZE,
},
};
struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
{
assert(agent_id < ARRAY_SIZE(scmi_channel));
VERBOSE("%d: SCMI asking for channel\n", agent_id);
/* Just in case that code is reused */
return &scmi_channel[agent_id];
}
/* Base protocol implementations */
const char *plat_scmi_vendor_name(void)
{
return SCMI_VENDOR;
}
const char *plat_scmi_sub_vendor_name(void)
{
return SCMI_PRODUCT;
}
/* Currently supporting Clocks and Reset Domains */
static const uint8_t plat_protocol_list[] = {
SCMI_PROTOCOL_ID_BASE,
SCMI_PROTOCOL_ID_CLOCK,
SCMI_PROTOCOL_ID_RESET_DOMAIN,
/*
*SCMI_PROTOCOL_ID_POWER_DOMAIN,
*SCMI_PROTOCOL_ID_SENSOR,
*/
0U /* Null termination */
};
size_t plat_scmi_protocol_count(void)
{
const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
VERBOSE("SCMI: Protocol count: %d\n", (int32_t)count);
return count;
}
const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
{
return plat_protocol_list;
}
void init_scmi_server(void)
{
size_t i;
int32_t ret;
for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++)
scmi_smt_init_agent_channel(&scmi_channel[i]);
INFO("SCMI: Server initialized\n");
if (platform_id == QEMU) {
/* default setting is for QEMU */
} else if (platform_id == SPP) {
for (i = 0U; i < ARRAY_SIZE(scmi0_clock); i++) {
/* Keep i2c on 100MHz to calculate rates properly */
if (i >= CLK_I2C0_0 && i <= CLK_I2C7_0)
continue;
/*
* SPP supports multiple versions.
* The cpu_clock value is set to corresponding SPP
* version in early platform setup, resuse the same
* value here.
*/
ret = plat_scmi_clock_set_rate(0, i, cpu_clock);
if (ret < 0) {
NOTICE("Failed to set clock rate for SPP scmi_id=%ld\n", i);
}
}
} else {
/* Making MISRA C 2012 15.7 compliant */
}
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, 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 <errno.h>
#include <inttypes.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <drivers/scmi-msg.h>
#include <scmi.h>
#include <tools_share/uuid.h>
#include "ipi_mailbox_svc.h"
#include "plat_private.h"
#include "pm_svc_main.h"
/* SMC function IDs for SiP Service queries */
#define SIP_SVC_UID (0x8200ff01U)
#define SIP_SVC_VERSION (0x8200ff03U)
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR (0U)
#define SIP_SVC_VERSION_MINOR (1U)
/* 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(_sip_uuid,
0x0499eb70, 0x5ed0, 0x11ee, 0xb3, 0x0a,
0x87, 0xd1, 0x1d, 0x4f, 0x8a, 0x9b);
/**
* sip_svc_setup() - Setup SiP Service
*
* Return: 0 on success, negative error code on failure.
*
*/
static int32_t sip_svc_setup(void)
{
return sip_svc_setup_init();
}
/*
* sip_svc_smc_handler() - Top-level SiP Service SMC handler
*
* Handler for all SiP SMC calls. Handles standard SIP requests
* and calls PM SMC handler if the call is for a PM-API function.
*/
static 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) != 0) {
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 smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
}
/* Let IPI SMC handler deal with IPI-related requests if platform */
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 SIP_SVC_UID:
SMC_UUID_RET(handle, _sip_uuid);
case SIP_SVC_VERSION:
SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR);
case SIP_SCMI:
if (platform_id != EMU) {
scmi_smt_fastcall_smc_entry(0);
SMC_RET1(handle, 0);
}
WARN("SCMI is not working on EMU\n");
SMC_RET1(handle, SMC_UNK);
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);

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2022, Xilinx, Inc. All rights reserved.
* Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* SoC IPI agent registers access management
*/
#include <lib/utils_def.h>
#include <plat_ipi.h>
/* versal2 ipi configuration table */
static const struct ipi_config ipi_table[IPI_ID_MAX] = {
/* A78 IPI */
[IPI_ID_APU] = {
.ipi_bit_mask = IPI0_TRIG_BIT,
.ipi_reg_base = IPI0_REG_BASE,
.secure_only = 0,
},
/* PMC IPI */
[IPI_ID_PMC] = {
.ipi_bit_mask = PMC_IPI_TRIG_BIT,
.ipi_reg_base = IPI0_REG_BASE,
.secure_only = IPI_SECURE_MASK,
},
/* RPU0 IPI */
[IPI_ID_RPU0] = {
.ipi_bit_mask = IPI1_TRIG_BIT,
.ipi_reg_base = IPI1_REG_BASE,
.secure_only = 0,
},
/* RPU1 IPI */
[IPI_ID_RPU1] = {
.ipi_bit_mask = IPI2_TRIG_BIT,
.ipi_reg_base = IPI2_REG_BASE,
.secure_only = 0,
},
/* IPI3 IPI */
[IPI_ID_3] = {
.ipi_bit_mask = IPI3_TRIG_BIT,
.ipi_reg_base = IPI3_REG_BASE,
.secure_only = 0,
},
/* IPI4 IPI */
[IPI_ID_4] = {
.ipi_bit_mask = IPI4_TRIG_BIT,
.ipi_reg_base = IPI4_REG_BASE,
.secure_only = 0,
},
/* IPI5 IPI */
[IPI_ID_5] = {
.ipi_bit_mask = IPI5_TRIG_BIT,
.ipi_reg_base = IPI5_REG_BASE,
.secure_only = 0,
},
};
/**
* soc_ipi_config_table_init() - Initialize versal2 IPI configuration data.
*/
void soc_ipi_config_table_init(void)
{
ipi_config_table_init(ipi_table, ARRAY_SIZE(ipi_table));
}

View file

@ -0,0 +1,10 @@
#
# Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# TSP source files specific to Versal Gen 2 platform
PLAT_XILINX_COMMON := plat/xilinx/common/
include ${PLAT_XILINX_COMMON}/tsp/tsp.mk