Merge "docs(plat/marvell/a8k): document MSS_SUPPORT and SCP_BL2 build options" into integration
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 0a0d2f0..2dfaf78 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -283,6 +283,10 @@
For Cortex-A78 AE, the following errata build flags are defined :
+- ``ERRATA_A78_AE_1941500`` : This applies errata 1941500 workaround to Cortex-A78
+ AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is
+ still open.
+
- ``ERRATA_A78_AE_1951502`` : This applies errata 1951502 workaround to Cortex-A78
AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is
still open.
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index 913b96a..8af27b1 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -62,6 +62,7 @@
- a80x0_mcbin - MacchiatoBin
- a80x0_puzzle - IEI Puzzle-M801
- t9130 - CN913x
+ - t9130_cex7_eval - CN913x CEx7 Evaluation Board
- DEBUG
diff --git a/include/lib/cpus/aarch64/cortex_a78_ae.h b/include/lib/cpus/aarch64/cortex_a78_ae.h
index 24ae7ee..0c8adcf 100644
--- a/include/lib/cpus/aarch64/cortex_a78_ae.h
+++ b/include/lib/cpus/aarch64/cortex_a78_ae.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,4 +12,10 @@
#define CORTEX_A78_AE_MIDR U(0x410FD420)
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A78_AE_CPUECTLR_EL1 CORTEX_A78_CPUECTLR_EL1
+#define CORTEX_A78_AE_CPUECTLR_EL1_BIT_8 CORTEX_A78_CPUECTLR_EL1_BIT_8
+
#endif /* CORTEX_A78_AE_H */
diff --git a/include/lib/cpus/aarch64/cortex_demeter.h b/include/lib/cpus/aarch64/cortex_demeter.h
new file mode 100644
index 0000000..9dd0987
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_demeter.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_DEMETER_H
+#define CORTEX_DEMETER_H
+
+#define CORTEX_DEMETER_MIDR U(0x410FD4F0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_DEMETER_CPUECTLR_EL1 S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_DEMETER_CPUPWRCTLR_EL1 S3_0_C15_C2_7
+#define CORTEX_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
+
+#endif /* CORTEX_DEMETER_H */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 5426135..3d57a5c 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -125,7 +125,7 @@
#if ENABLE_PAUTH
CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof
(cpu_data_t, apiakey),
- assert_cpu_data_crash_stack_offset_mismatch);
+ assert_cpu_data_pauth_stack_offset_mismatch);
#endif
#if CRASH_REPORTING
diff --git a/lib/cpus/aarch64/cortex_a78_ae.S b/lib/cpus/aarch64/cortex_a78_ae.S
index c8cccf2..421c174 100644
--- a/lib/cpus/aarch64/cortex_a78_ae.S
+++ b/lib/cpus/aarch64/cortex_a78_ae.S
@@ -18,6 +18,36 @@
#endif
/* --------------------------------------------------
+ * Errata Workaround for A78 AE Erratum 1941500.
+ * This applies to revisions r0p0 and r0p1 of A78 AE.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_ae_1941500_wa
+ /* Compare x0 against revisions r0p0 - r0p1 */
+ mov x17, x30
+ bl check_errata_1941500
+ cbz x0, 1f
+
+ /* Set bit 8 in ECTLR_EL1 */
+ mrs x0, CORTEX_A78_AE_CPUECTLR_EL1
+ bic x0, x0, #CORTEX_A78_AE_CPUECTLR_EL1_BIT_8
+ msr CORTEX_A78_AE_CPUECTLR_EL1, x0
+ isb
+1:
+ ret x17
+endfunc errata_a78_ae_1941500_wa
+
+func check_errata_1941500
+ /* Applies to revisions r0p0 and r0p1. */
+ mov x1, #CPU_REV(0, 0)
+ mov x2, #CPU_REV(0, 1)
+ b cpu_rev_var_range
+endfunc check_errata_1941500
+
+/* --------------------------------------------------
* Errata Workaround for A78 AE Erratum 1951502.
* This applies to revisions r0p0 and r0p1 of A78 AE.
* Inputs:
@@ -78,6 +108,11 @@
bl cpu_get_rev_var
mov x18, x0
+#if ERRATA_A78_AE_1941500
+ mov x0, x18
+ bl errata_a78_ae_1941500_wa
+#endif
+
#if ERRATA_A78_AE_1951502
mov x0, x18
bl errata_a78_ae_1951502_wa
@@ -138,6 +173,7 @@
* Report all errata. The revision-variant information is passed to
* checking functions of each errata.
*/
+ report_errata ERRATA_A78_AE_1941500, cortex_a78_ae, 1941500
report_errata ERRATA_A78_AE_1951502, cortex_a78_ae, 1951502
ldp x8, x30, [sp], #16
diff --git a/lib/cpus/aarch64/cortex_demeter.S b/lib/cpus/aarch64/cortex_demeter.S
new file mode 100644
index 0000000..9ad8b86
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_demeter.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_demeter.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex Demeter must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex Demeter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+ /* ----------------------------------------------------
+ * HW will do the cache maintenance while powering down
+ * ----------------------------------------------------
+ */
+func cortex_demeter_core_pwr_dwn
+ /* ---------------------------------------------------
+ * Enable CPU power down bit in power control register
+ * ---------------------------------------------------
+ */
+ mrs x0, CORTEX_DEMETER_CPUPWRCTLR_EL1
+ orr x0, x0, #CORTEX_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+ msr CORTEX_DEMETER_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+endfunc cortex_demeter_core_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex Demeter. Must follow AAPCS.
+ */
+func cortex_demeter_errata_report
+ ret
+endfunc cortex_demeter_errata_report
+#endif
+
+func cortex_demeter_reset_func
+ /* Disable speculative loads */
+ msr SSBS, xzr
+ isb
+ ret
+endfunc cortex_demeter_reset_func
+
+ /* ---------------------------------------------
+ * This function provides Cortex Demeter-
+ * specific register information for crash
+ * reporting. It needs to return with x6
+ * pointing to a list of register names in ascii
+ * and x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.cortex_demeter_regs, "aS"
+cortex_demeter_regs: /* The ascii list of register names to be reported */
+ .asciz "cpuectlr_el1", ""
+
+func cortex_demeter_cpu_reg_dump
+ adr x6, cortex_demeter_regs
+ mrs x8, CORTEX_DEMETER_CPUECTLR_EL1
+ ret
+endfunc cortex_demeter_cpu_reg_dump
+
+declare_cpu_ops cortex_demeter, CORTEX_DEMETER_MIDR, \
+ cortex_demeter_reset_func, \
+ cortex_demeter_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index b366167..e81471e 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -311,6 +311,10 @@
# well but there is no workaround for that revision.
ERRATA_A78_1951500 ?=0
+# Flag to apply erratum 1941500 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
+ERRATA_A78_AE_1941500 ?=0
+
# Flag to apply erratum 1951502 workaround during reset. This erratum applies
# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
ERRATA_A78_AE_1951502 ?=0
@@ -650,6 +654,10 @@
$(eval $(call assert_boolean,ERRATA_A78_1951500))
$(eval $(call add_define,ERRATA_A78_1951500))
+# Process ERRATA_A78_AE_1941500 flag
+$(eval $(call assert_boolean,ERRATA_A78_AE_1941500))
+$(eval $(call add_define,ERRATA_A78_AE_1941500))
+
# Process ERRATA_A78_AE_1951502 flag
$(eval $(call assert_boolean,ERRATA_A78_AE_1951502))
$(eval $(call add_define,ERRATA_A78_AE_1951502))
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 56a2ad6..49951e0 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -25,7 +25,8 @@
#else /* !SUNXI_BL31_IN_DRAM */
-#define BL31_BASE (SUNXI_SRAM_A2_BASE + 0x4000)
+#define BL31_BASE (SUNXI_SRAM_A2_BASE + \
+ SUNXI_SRAM_A2_BL31_OFFSET)
#define BL31_LIMIT (SUNXI_SRAM_A2_BASE + \
SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
index f036816..ec50887 100644
--- a/plat/allwinner/common/include/sunxi_def.h
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -18,5 +18,6 @@
#define SUNXI_SOC_H5 0x1718
#define SUNXI_SOC_H6 0x1728
#define SUNXI_SOC_H616 0x1823
+#define SUNXI_SOC_R329 0x1851
#endif /* SUNXI_DEF_H */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index 72bfbd9..14049e8 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -128,6 +128,9 @@
case SUNXI_SOC_H616:
soc_name = "H616";
break;
+ case SUNXI_SOC_R329:
+ soc_name = "R329";
+ break;
default:
soc_name = "unknown";
break;
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index 420b507..46e7090 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -42,6 +42,7 @@
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
+ udelay(1);
}
/* We can't turn ourself off like this, but it works for other cores. */
@@ -75,7 +76,8 @@
/* Assert CPU power-on reset */
mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
/* Set CPU to start in AArch64 mode */
- mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core));
+ mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
+ BIT(SUNXI_AA64nAA32_OFFSET + core));
/* Apply power to the CPU */
sunxi_cpu_enable_power(cluster, core);
/* Release the core output clamps */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
index c3eeadb..aed3585 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -33,4 +33,7 @@
#define SUNXI_R_CPUCFG_SS_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a8)
#define SUNXI_R_CPUCFG_HP_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01ac)
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 24
+
#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index 6c847d3..6d10921 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -15,6 +15,7 @@
#define SUNXI_SRAM_A1_BASE 0x00010000
#define SUNXI_SRAM_A1_SIZE 0x00008000
#define SUNXI_SRAM_A2_BASE 0x00040000
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000
#define SUNXI_SRAM_A2_SIZE 0x00014000
#define SUNXI_SRAM_C_BASE 0x00018000
#define SUNXI_SRAM_C_SIZE 0x0001c000
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
index a2b94af..5bfda5d 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -29,4 +29,7 @@
#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144)
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 24
+
#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index 2d7b098..58216d8 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -15,6 +15,7 @@
#define SUNXI_SRAM_A1_BASE 0x00020000
#define SUNXI_SRAM_A1_SIZE 0x00008000
#define SUNXI_SRAM_A2_BASE 0x00100000
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000
#define SUNXI_SRAM_A2_SIZE 0x00018000
#define SUNXI_SRAM_C_BASE 0x00028000
#define SUNXI_SRAM_C_SIZE 0x0001e000
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
index a637554..dab663b 100644
--- a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
@@ -29,4 +29,7 @@
#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144)
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 24
+
#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_ccu.h b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
new file mode 100644
index 0000000..0e6b543
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..9478f32
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_C0_CPUXCFG_BASE + 0x0010)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_C0_CPUXCFG_BASE + 0x0014)
+#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_C0_CPUXCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_C0_CPUXCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_C0_CPUXCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_GEN_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
+ (c) * 0x10 + (n) * 4)
+
+#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_GEN_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET 4
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_mmap.h b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
new file mode 100644
index 0000000..a4469b5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+/*
+ * In fact all SRAM from 0x100000 is SRAM A2. However as it's too big for
+ * firmware, and the user manual gives a tip on a 2*64K/27*64K partition,
+ * only use the first 2*64K for firmwares now, with the SPL using the first
+ * 64K and BL3-1 using the second one.
+ *
+ * Only the used 2*64K SRAM is defined here, to prevent a gaint translation
+ * table to be generated.
+ */
+#define SUNXI_SRAM_BASE 0x00100000
+#define SUNXI_SRAM_SIZE 0x00020000
+#define SUNXI_SRAM_A1_BASE 0x00100000
+#define SUNXI_SRAM_A1_SIZE 0x00010000
+#define SUNXI_SRAM_A2_BASE 0x00110000
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00000000
+#define SUNXI_SRAM_A2_SIZE 0x00010000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x09000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_VIRT_BASE 0x0a000000
+
+/* Memory-mapped devices */
+#define SUNXI_WDOG_BASE 0x020000a0
+#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE
+#define SUNXI_PIO_BASE 0x02000400
+#define SUNXI_SPC_BASE 0x02000800
+#define SUNXI_CCU_BASE 0x02001000
+#define SUNXI_UART0_BASE 0x02500000
+#define SUNXI_SYSCON_BASE 0x03000000
+#define SUNXI_DMA_BASE 0x03002000
+#define SUNXI_SID_BASE 0x03006000
+#define SUNXI_GICD_BASE 0x03021000
+#define SUNXI_GICC_BASE 0x03022000
+#define SUNXI_SPI0_BASE 0x04025000
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_R_PRCM_BASE 0x07010000
+#define SUNXI_R_PIO_BASE 0x07022000
+#define SUNXI_R_UART_BASE 0x07080000
+#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_CPUCFG_BASE 0x08100000
+#define SUNXI_C0_CPUXCFG_BASE 0x09010000
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_spc.h b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
new file mode 100644
index 0000000..2c87bca
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+/* Get by REing stock ATF and checking initialization loop boundary */
+#define SUNXI_SPC_NUM_PORTS 11
+
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_r329/platform.mk b/plat/allwinner/sun50i_r329/platform.mk
new file mode 100644
index 0000000..05d7cde
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021 Sipeed
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Without a management processor there is no SCPI support.
+SUNXI_PSCI_USE_SCPI := 0
+SUNXI_PSCI_USE_NATIVE := 1
+
+# The differences between the platforms are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+# the above could be overwritten on the command line
+ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
+ $(error "R329 does not support SCPI PSCI ops")
+endif
+
+# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL.
+SEPARATE_NOBITS_REGION := 1
diff --git a/plat/allwinner/sun50i_r329/sunxi_power.c b/plat/allwinner/sun50i_r329/sunxi_power.c
new file mode 100644
index 0000000..96a24d5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/sunxi_power.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.h>
+#include <sunxi_private.h>
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ /* Currently known hardware has no PMIC */
+
+ return 0;
+}
+
+void sunxi_power_down(void)
+{
+}
+
+void sunxi_cpu_power_off_self(void)
+{
+ /* TODO: It's still unknown whether CPUIDLE exists on R329 */
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 10258ad..3c70eed 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -135,6 +135,7 @@
lib/cpus/aarch64/cortex_a710.S \
lib/cpus/aarch64/cortex_makalu.S \
lib/cpus/aarch64/cortex_makalu_elp_arm.S \
+ lib/cpus/aarch64/cortex_demeter.S \
lib/cpus/aarch64/cortex_a65.S \
lib/cpus/aarch64/cortex_a65ae.S \
lib/cpus/aarch64/cortex_a78c.S
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index 773b912..30e6280 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -80,7 +80,7 @@
drivers/arm/gic/v2/gicv2_helpers.c \
plat/common/plat_gicv2.c
-PLAT_INCLUDES := -I$(BOARD_DIR) \
+PLAT_INCLUDES += -I$(BOARD_DIR) \
-I$(BOARD_DIR)/board \
-I$(CURDIR)/drivers/marvell \
-I$(PLAT_COMMON_BASE)/include \
@@ -89,8 +89,10 @@
PLAT_BL_COMMON_SOURCES := $(PLAT_COMMON_BASE)/aarch64/a8k_common.c \
drivers/ti/uart/aarch64/16550_console.S
+ifndef BLE_PORTING_SOURCES
BLE_PORTING_SOURCES := $(BOARD_DIR)/board/dram_port.c \
$(BOARD_DIR)/board/marvell_plat_config.c
+endif
MARVELL_MOCHI_DRV += $(MARVELL_DRV_BASE)/mochi/cp110_setup.c
@@ -125,7 +127,9 @@
MARVELL_DRV += $(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
endif
+ifndef BL31_PORTING_SOURCES
BL31_PORTING_SOURCES := $(BOARD_DIR)/board/marvell_plat_config.c
+endif
ifeq ($(SYSTEM_POWER_SUPPORT),1)
BL31_PORTING_SOURCES += $(BOARD_DIR)/board/system_power.c
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
new file mode 100644
index 0000000..5bae8eb
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2021 Semihalf.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <mvebu_def.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map_cp0[] = {
+ /* CP0 SPI1 CS0 Direct Mode access */
+ {0xef00, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+struct addr_map_win amb_memory_map_cp1[] = {
+ /* CP1 SPI1 CS0 Direct Mode access */
+ {0xe800, 0x1000000, AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = amb_memory_map_cp0;
+ *size = ARRAY_SIZE(amb_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = amb_memory_map_cp1;
+ *size = ARRAY_SIZE(amb_memory_map_cp1);
+ return 0;
+ case MVEBU_CP_REGS_BASE(2):
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#if (CP_COUNT > 1)
+ /* SB (MCi0) internal regs */
+ {0x00000000f4000000, 0x2000000, MCI_0_TID},
+ /* SB (MCi0) PCIe0-2 on CP1 */
+ {0x00000000e2000000, 0x7000000, MCI_0_TID},
+ /*
+ * Due to lack of sufficient number of IO windows registers,
+ * below CP1 PCIE configuration must be performed in the
+ * later firmware stages. It should replace the MCI 0 indirect
+ * window, which becomes no longer needed.
+ */
+ /* {0x0000000890000000, 0x30000000, MCI_0_TID}, */
+#if (CP_COUNT > 2)
+ /* SB (MCi1) internal regs */
+ {0x00000000f6000000, 0x2000000, MCI_1_TID},
+ /* SB (MCi1) PCIe0-2 on CP2 */
+ {0x00000000e9000000, 0x6000000, MCI_1_TID},
+ /*
+ * Due to lack of sufficient number of IO windows registers,
+ * below CP2 PCIE configuration must be performed in the
+ * later firmware stages. It should replace the MCI 1 indirect
+ * window, which becomes no longer needed.
+ */
+ /* {0x00000008c0000000, 0x30000000, MCI_1_TID}, */
+#endif
+#endif
+#ifndef IMAGE_BLE
+ /* MCI 0 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(0), 0x100000, MCI_0_TID},
+ /* MCI 1 indirect window */
+ {MVEBU_MCI_REG_BASE_REMAP(1), 0x100000, MCI_1_TID},
+#endif
+};
+
+/* Global Control Register - window default target */
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+ /*
+ * PIDI == iMCIP AP to SB internal MoChi connection.
+ * In other words CP0
+ */
+ return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = io_win_memory_map;
+ if (*win == NULL)
+ *size = 0;
+ else
+ *size = ARRAY_SIZE(io_win_memory_map);
+
+ return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000ef000000, 0x1000000, RUNIT_TID},
+ /* PEX2_X1 window */
+ {0x00000000e1000000, 0x1000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e0000000, 0x1000000, PEX1_TID},
+ /* PEX0_X4 window */
+ {0x00000000c0000000, 0x20000000, PEX0_TID},
+ {0x0000000800000000, 0x90000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+ /* SPI1_CS0 (RUNIT) window */
+ {0x00000000e8000000, 0x1000000, RUNIT_TID},
+ /* PEX2_X1 window */
+ {0x00000000e6000000, 0x2000000, PEX2_TID},
+ {0x00000008b0000000, 0x10000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000e4000000, 0x2000000, PEX1_TID},
+ {0x00000008a0000000, 0x10000000, PEX1_TID},
+ /* PEX0_X2 window */
+ {0x00000000e2000000, 0x2000000, PEX0_TID},
+ {0x0000000890000000, 0x10000000, PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp2[] = {
+
+ /* PEX2_X1 window */
+ {0x00000000ed000000, 0x2000000, PEX2_TID},
+ {0x00000008e0000000, 0x10000000, PEX2_TID},
+ /* PEX1_X1 window */
+ {0x00000000eb000000, 0x2000000, PEX1_TID},
+ {0x00000008d0000000, 0x10000000, PEX1_TID},
+ /* PEX0_X1 window */
+ {0x00000000e9000000, 0x2000000, PEX0_TID},
+ {0x00000008c0000000, 0x10000000, PEX0_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+ uintptr_t base)
+{
+ switch (base) {
+ case MVEBU_CP_REGS_BASE(0):
+ *win = iob_memory_map_cp0;
+ *size = ARRAY_SIZE(iob_memory_map_cp0);
+ return 0;
+ case MVEBU_CP_REGS_BASE(1):
+ *win = iob_memory_map_cp1;
+ *size = ARRAY_SIZE(iob_memory_map_cp1);
+ return 0;
+ case MVEBU_CP_REGS_BASE(2):
+ *win = iob_memory_map_cp2;
+ *size = ARRAY_SIZE(iob_memory_map_cp2);
+ return 0;
+ default:
+ *size = 0;
+ *win = 0;
+ return 1;
+ }
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = { /* IO window */
+#ifdef IMAGE_BLE
+ {0x00000000f2000000, 0x6000000, IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+ {PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+ {0x00000000f2000000, 0xe000000, IO_0_TID}, /* IO window */
+ {0x00000000c0000000, 0x30000000, IO_0_TID}, /* IO window */
+ {0x0000000800000000, 0x100000000, IO_0_TID}, /* IO window */
+ {0x0000002000000000, 0x70e000000, IO_0_TID}, /* IO for CV-OS */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+ return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+ uint32_t *size)
+{
+ *win = ccu_memory_map;
+ *size = ARRAY_SIZE(ccu_memory_map);
+
+ return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_get_skip_image_data(void)
+{
+ /* No recovery button on CN-9130 board? */
+ return NULL;
+}
+#endif
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
new file mode 100644
index 0000000..ee55455
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+# Copyright (C) 2021 Semihalf.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT := 0
+
+CP_NUM := 1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC := tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV := drivers/marvell/mochi/ap807_setup.c
+
+BOARD_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))
+
+#
+# CN913X CEx7 Evaluation Board shares the DRAM connectivity
+# and SerDes settings with the CN913X DB - reuse relevant
+# board-specific files.
+#
+T9130_DIR := $(BOARD_DIR)/../t9130
+PLAT_INCLUDES := -I$(T9130_DIR) \
+ -I$(T9130_DIR)/board
+BLE_PORTING_SOURCES := $(T9130_DIR)/board/dram_port.c \
+ $(BOARD_DIR)/board/marvell_plat_config.c
+
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index 0891d80..c02eff9 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -80,8 +80,8 @@
#define SEC_ROM_BASE 0x00000000
#define SEC_ROM_SIZE 0x00020000
-#define NS_DRAM0_BASE 0x40000000
-#define NS_DRAM0_SIZE 0xc0000000
+#define NS_DRAM0_BASE ULL(0x40000000)
+#define NS_DRAM0_SIZE ULL(0xc0000000)
#define SEC_SRAM_BASE 0x0e000000
#define SEC_SRAM_SIZE 0x00060000
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index cfacd1f..5259859 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -201,6 +201,44 @@
enable_mmu_el3(0);
}
+/*
+ * Remove the FDT /memreserve/ entry that covers the region at the very
+ * beginning of memory (if that exists). This is where the secondaries
+ * originally spin, but we pull them out there.
+ * Having overlapping /reserved-memory and /memreserve/ regions confuses
+ * the Linux kernel, so we need to get rid of this one.
+ */
+static void remove_spintable_memreserve(void *dtb)
+{
+ uint64_t addr, size;
+ int regions = fdt_num_mem_rsv(dtb);
+ int i;
+
+ for (i = 0; i < regions; i++) {
+ if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) {
+ return;
+ }
+ if (size == 0U) {
+ return;
+ }
+ /* We only look for the region at the beginning of DRAM. */
+ if (addr != 0U) {
+ continue;
+ }
+ /*
+ * Currently the region in the existing DTs is exactly 4K
+ * in size. Should this value ever change, there is probably
+ * a reason for that, so inform the user about this.
+ */
+ if (size == 4096U) {
+ fdt_del_mem_rsv(dtb, i);
+ return;
+ }
+ WARN("Keeping unknown /memreserve/ region at 0, size: %lld\n",
+ size);
+ }
+}
+
static void rpi4_prepare_dtb(void)
{
void *dtb = (void *)rpi4_get_dtb_address();
@@ -227,7 +265,11 @@
return;
}
- /* Reserve memory used by Trusted Firmware. */
+ /*
+ * Remove the original reserved region (used for the spintable), and
+ * replace it with a region describing the whole of Trusted Firmware.
+ */
+ remove_spintable_memreserve(dtb);
if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
WARN("Failed to add reserved memory nodes to DT.\n");
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 3e179fb..b4c42fc 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -153,8 +153,6 @@
#ifdef AARCH32_SP_OPTEE
INFO("BL2 runs OP-TEE setup\n");
- /* Initialize tzc400 after DDR initialization */
- stm32mp1_security_setup();
#else
INFO("BL2 runs SP_MIN setup\n");
#endif
@@ -384,4 +382,9 @@
return err;
}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+ stm32mp1_security_setup();
+}
#endif
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index f165fb0..9c5af88 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -677,6 +677,10 @@
case IOCTL_AFI:
ret = pm_ioctl_afi(arg1, arg2);
break;
+ case IOCTL_SET_FEATURE_CONFIG:
+ case IOCTL_GET_FEATURE_CONFIG:
+ ret = pm_feature_config(ioctl_id, arg1, arg2, value);
+ break;
default:
ret = PM_RET_ERROR_NOTSUPPORTED;
break;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
index 337f732..f18dc00 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -15,28 +15,43 @@
//ioctl id
enum {
- IOCTL_GET_RPU_OPER_MODE,
- IOCTL_SET_RPU_OPER_MODE,
- IOCTL_RPU_BOOT_ADDR_CONFIG,
- IOCTL_TCM_COMB_CONFIG,
- IOCTL_SET_TAPDELAY_BYPASS,
- IOCTL_SET_SGMII_MODE,
- IOCTL_SD_DLL_RESET,
- IOCTL_SET_SD_TAPDELAY,
+ IOCTL_GET_RPU_OPER_MODE = 0,
+ IOCTL_SET_RPU_OPER_MODE = 1,
+ IOCTL_RPU_BOOT_ADDR_CONFIG = 2,
+ IOCTL_TCM_COMB_CONFIG = 3,
+ IOCTL_SET_TAPDELAY_BYPASS = 4,
+ IOCTL_SET_SGMII_MODE = 5,
+ IOCTL_SD_DLL_RESET = 6,
+ IOCTL_SET_SD_TAPDELAY = 7,
/* Ioctl for clock driver */
- IOCTL_SET_PLL_FRAC_MODE,
- IOCTL_GET_PLL_FRAC_MODE,
- IOCTL_SET_PLL_FRAC_DATA,
- IOCTL_GET_PLL_FRAC_DATA,
- IOCTL_WRITE_GGS,
- IOCTL_READ_GGS,
- IOCTL_WRITE_PGGS,
- IOCTL_READ_PGGS,
+ IOCTL_SET_PLL_FRAC_MODE = 8,
+ IOCTL_GET_PLL_FRAC_MODE = 9,
+ IOCTL_SET_PLL_FRAC_DATA = 10,
+ IOCTL_GET_PLL_FRAC_DATA = 11,
+ IOCTL_WRITE_GGS = 12,
+ IOCTL_READ_GGS = 13,
+ IOCTL_WRITE_PGGS = 14,
+ IOCTL_READ_PGGS = 15,
/* IOCTL for ULPI reset */
- IOCTL_ULPI_RESET,
+ IOCTL_ULPI_RESET = 16,
/* Set healthy bit value */
- IOCTL_SET_BOOT_HEALTH_STATUS,
- IOCTL_AFI,
+ IOCTL_SET_BOOT_HEALTH_STATUS = 17,
+ IOCTL_AFI = 18,
+ /* Probe counter read/write */
+ IOCTL_PROBE_COUNTER_READ = 19,
+ IOCTL_PROBE_COUNTER_WRITE = 20,
+ IOCTL_OSPI_MUX_SELECT = 21,
+ /* IOCTL for USB power request */
+ IOCTL_USB_SET_STATE = 22,
+ /* IOCTL to get last reset reason */
+ IOCTL_GET_LAST_RESET_REASON = 23,
+ /* AI engine NPI ISR clear */
+ IOCTL_AIE_ISR_CLEAR = 24,
+ /* Register SGI to ATF */
+ IOCTL_REGISTER_SGI = 25,
+ /* Runtime feature configuration */
+ IOCTL_SET_FEATURE_CONFIG = 26,
+ IOCTL_GET_FEATURE_CONFIG = 27,
};
//RPU operation mode
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 62260bc..5d9408c 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -1648,3 +1648,36 @@
EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
return pm_ipi_send_sync(primary_proc, payload, value, 1);
}
+
+/**
+ * pm_feature_config() - feature configuration at runtime
+ *
+ * This function is used to send IPI request to PMUFW to configure feature
+ * at runtime. The feature can be enable or disable as well as the feature
+ * can be configure at runtime using an IOCTL call.
+ *
+ * @ioctl_id The ioctl id for the feature configuration
+ * @config_id The config id of the feature to be configured
+ * @value The value to be configured
+ * @response Return to reference pointer
+ *
+ * @return Returns 0 on success or error value on failure
+ */
+enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
+ unsigned int config_id,
+ unsigned int value,
+ unsigned int *response)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_IOCTL, 0, ioctl_id, config_id, value);
+
+ if (ioctl_id == IOCTL_GET_FEATURE_CONFIG) {
+ return pm_ipi_send_sync(primary_proc, payload, response, 1);
+ } else if (ioctl_id == IOCTL_SET_FEATURE_CONFIG) {
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+ } else {
+ return PM_RET_ERROR_ARGS;
+ }
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index b0c2652..ca07cef 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -202,4 +202,9 @@
enum pm_ret_status em_remove_action(unsigned int *value);
enum pm_ret_status em_send_errors(unsigned int *value);
+enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
+ unsigned int config_id,
+ unsigned int value,
+ unsigned int *response);
+
#endif /* PM_API_SYS_H */