[PATCH 0/5] board: sl28: add basic PSCI implementation

Add PSCI support to reset and power-off the board. Because this board can be used without TF-A, supply a (mandatory) PSCI implementation.
The armv8 u-boot part already contains most bits for the implementation, it is just, that it isn't compatible with the layerscape parts. Thus, we first need to clean that up and then we can add our three little functions for the PSCI support.
Michael Walle (5): armv8: include psci_update_dt() unconditionally armv8: layerscape: get rid of smc_call() armv8: psci: skip setup code if we are not EL3 armv8: psci: add ARMV8_PSCI_RELOCATE Kconfig option board: sl28: add basic PSCI implementation
arch/arm/cpu/armv8/Kconfig | 30 +++++++++----- arch/arm/cpu/armv8/cpu-dt.c | 7 ++-- arch/arm/cpu/armv8/cpu.c | 3 ++ arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 3 ++ arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 49 +++++++++-------------- arch/arm/cpu/armv8/fsl-layerscape/mp.c | 11 ++--- arch/arm/cpu/armv8/sec_firmware.c | 19 ++++----- board/freescale/ls1043ardb/Kconfig | 8 ---- board/kontron/sl28/Makefile | 2 + board/kontron/sl28/psci.c | 42 +++++++++++++++++++ 10 files changed, 103 insertions(+), 71 deletions(-) create mode 100644 board/kontron/sl28/psci.c

psci_update_dt() is also required if CONFIG_ARMV8_PSCI is set, that is, if u-boot is the PSCI provider. Guard the check which is intended to call into the PSCI implementation in the secure firmware, by the proper macro SEC_FIRMWARE_ARMV8_PSCI.
Signed-off-by: Michael Walle michael@walle.cc --- arch/arm/cpu/armv8/cpu-dt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/arm/cpu/armv8/cpu-dt.c b/arch/arm/cpu/armv8/cpu-dt.c index 61c38b17cb..1bf8fbaae3 100644 --- a/arch/arm/cpu/armv8/cpu-dt.c +++ b/arch/arm/cpu/armv8/cpu-dt.c @@ -8,8 +8,8 @@ #include <asm/psci.h> #include <asm/system.h> #include <asm/armv8/sec_firmware.h> +#include <linux/libfdt.h>
-#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT) int psci_update_dt(void *fdt) { /* @@ -18,8 +18,10 @@ int psci_update_dt(void *fdt) * number to support detecting PSCI dynamically and then switching * the SMP boot method between PSCI and spin-table. */ - if (sec_firmware_support_psci_version() == PSCI_INVALID_VER) + if (CONFIG_IS_ENABLED(SEC_FIRMWARE_ARMV8_PSCI) && + sec_firmware_support_psci_version() == PSCI_INVALID_VER) return 0; + fdt_psci(fdt);
#if defined(CONFIG_ARMV8_PSCI) && !defined(CONFIG_ARMV8_SECURE_BASE) @@ -30,4 +32,3 @@ int psci_update_dt(void *fdt)
return 0; } -#endif

-----Original Message----- From: U-Boot u-boot-bounces@lists.denx.de On Behalf Of Michael Walle Sent: Friday, November 26, 2021 10:04 PM To: u-boot@lists.denx.de Cc: Mingkai Hu mingkai.hu@nxp.com; Rajesh Bhagat rajesh.bhagat@nxp.com; Michael Walle michael@walle.cc Subject: [PATCH 1/5] armv8: include psci_update_dt() unconditionally
psci_update_dt() is also required if CONFIG_ARMV8_PSCI is set, that is, if u-boot is the PSCI provider. Guard the check which is intended to call into the PSCI implementation in the secure firmware, by the proper macro SEC_FIRMWARE_ARMV8_PSCI.
Signed-off-by: Michael Walle michael@walle.cc
arch/arm/cpu/armv8/cpu-dt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/arm/cpu/armv8/cpu-dt.c b/arch/arm/cpu/armv8/cpu-dt.c index 61c38b17cb..1bf8fbaae3 100644 --- a/arch/arm/cpu/armv8/cpu-dt.c +++ b/arch/arm/cpu/armv8/cpu-dt.c @@ -8,8 +8,8 @@ #include <asm/psci.h> #include <asm/system.h> #include <asm/armv8/sec_firmware.h> +#include <linux/libfdt.h>
-#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT) int psci_update_dt(void *fdt) { /* @@ -18,8 +18,10 @@ int psci_update_dt(void *fdt) * number to support detecting PSCI dynamically and then switching * the SMP boot method between PSCI and spin-table. */
- if (sec_firmware_support_psci_version() == PSCI_INVALID_VER)
- if (CONFIG_IS_ENABLED(SEC_FIRMWARE_ARMV8_PSCI) &&
return 0;sec_firmware_support_psci_version() == PSCI_INVALID_VER)
- fdt_psci(fdt);
#if defined(CONFIG_ARMV8_PSCI) && !defined(CONFIG_ARMV8_SECURE_BASE) @@ -30,4 +32,3 @@ int psci_update_dt(void *fdt)
return 0; }
-#endif
2.30.2
Kindly fix build for renesas platforms
2022-02-25T15:26:42.0514001Z Summary of current source for 17 boards (2 threads, 1 job per thread) 2022-02-25T15:26:42.0515545Z aarch64: w+ r8a77980_condor r8a77995_draak r8a77970_eagle r8a77990_ebisu rcar3_salvator-x rcar3_ulcb + r8a779a0_falcon 2022-02-25T15:26:42.0516492Z arm: w+ alt blanche gose koelsch lager porter silk stout 2022-02-25T15:26:42.0516894Z sh: w+ r2dplus 2022-02-25T15:26:42.0517553Z +srec_cat: warning: option "-Little_Endian_CONSTant" is deprecated, please use 2022-02-25T15:26:42.0518178Z + "-CONSTant_Little_Endian" instead 2022-02-25T15:26:42.0518870Z +aarch64-linux-ld.bfd: arch/arm/mach-rmobile/psci-r8a779a0.o: in function `psci_update_dt': 2022-02-25T15:26:42.0520304Z +arch/arm/mach-rmobile/psci-r8a779a0.c:49: multiple definition of `psci_update_dt'; arch/arm/cpu/armv8/cpu-dt.o:arch/arm/cpu/armv8/cpu-dt.c:14: first defined here 2022-02-25T15:26:42.0521147Z +make[1]: *** [Makefile:1801: u-boot] Error 1 2022-02-25T15:26:42.0521728Z +make: *** [Makefile:177: sub-make] Error 2
Regards Priyanka

There are two different implementations to do a secure monitor call: smc_call() and arm_smccc_smc(). The former is defined in fwcall.c and seems to be an ad-hoc implementation. The latter is imported from linux.
smc_call() is also only available if CONFIG_ARMV8_PSCI is not defined. This makes it impossible to have both PSCI calls and PSCI implementation in one u-boot build. The layerscape SoC code decide at runtime via check_psci() if there is a PSCI support. Therefore, this is a prerequisite patch to add PSCI implementation support for the layerscape SoCs.
Note, for the TFA part, this is only compile time tested with (ls1028ardb_tfa_defconfig).
Signed-off-by: Michael Walle michael@walle.cc --- arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 1 + arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 49 +++++++++-------------- arch/arm/cpu/armv8/fsl-layerscape/mp.c | 11 ++--- arch/arm/cpu/armv8/sec_firmware.c | 19 ++++----- 4 files changed, 31 insertions(+), 49 deletions(-)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 1a057f7059..14ef07e74f 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -321,6 +321,7 @@ menu "Layerscape architecture"
config FSL_LAYERSCAPE bool + select ARM_SMCCC
config HAS_FEATURE_GIC64K_ALIGN bool diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 1a359d060e..38bef4432d 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -17,6 +17,7 @@ #include <asm/global_data.h> #include <asm/io.h> #include <asm/ptrace.h> +#include <linux/arm-smccc.h> #include <linux/errno.h> #include <asm/system.h> #include <fm_eth.h> @@ -766,7 +767,7 @@ enum boot_src __get_boot_src(u32 porsr1)
enum boot_src get_boot_src(void) { - struct pt_regs regs; + struct arm_smccc_res res; u32 porsr1 = 0;
#if defined(CONFIG_FSL_LSCH3) @@ -776,11 +777,9 @@ enum boot_src get_boot_src(void) #endif
if (current_el() == 2) { - regs.regs[0] = SIP_SVC_RCW; - - smc_call(®s); - if (!regs.regs[0]) - porsr1 = regs.regs[1]; + arm_smccc_smc(SIP_SVC_RCW, 0, 0, 0, 0, 0, 0, 0, &res); + if (!res.a0) + porsr1 = res.a1; }
if (current_el() == 3 || !porsr1) { @@ -1079,9 +1078,9 @@ static void config_core_prefetch(void) char *buf = NULL; char buffer[HWCONFIG_BUFFER_SIZE]; const char *prefetch_arg = NULL; + struct arm_smccc_res res; size_t arglen; unsigned int mask; - struct pt_regs regs;
if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0) buf = buffer; @@ -1099,11 +1098,10 @@ static void config_core_prefetch(void) }
#define SIP_PREFETCH_DISABLE_64 0xC200FF13 - regs.regs[0] = SIP_PREFETCH_DISABLE_64; - regs.regs[1] = mask; - smc_call(®s); + arm_smccc_smc(SIP_PREFETCH_DISABLE_64, mask, 0, 0, 0, 0, 0, 0, + &res);
- if (regs.regs[0]) + if (res.a0) printf("Prefetch disable config failed for mask "); else printf("Prefetch disable config passed for mask "); @@ -1343,25 +1341,20 @@ phys_size_t get_effective_memsize(void) #ifdef CONFIG_TFABOOT phys_size_t tfa_get_dram_size(void) { - struct pt_regs regs; - phys_size_t dram_size = 0; - - regs.regs[0] = SMC_DRAM_BANK_INFO; - regs.regs[1] = -1; + struct arm_smccc_res res;
- smc_call(®s); - if (regs.regs[0]) + arm_smccc_smc(SMC_DRAM_BANK_INFO, -1, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) return 0;
- dram_size = regs.regs[1]; - return dram_size; + return res.a1; }
static int tfa_dram_init_banksize(void) { int i = 0, ret = 0; - struct pt_regs regs; phys_size_t dram_size = tfa_get_dram_size(); + struct arm_smccc_res res;
debug("dram_size %llx\n", dram_size);
@@ -1369,19 +1362,15 @@ static int tfa_dram_init_banksize(void) return -EINVAL;
do { - regs.regs[0] = SMC_DRAM_BANK_INFO; - regs.regs[1] = i; - - smc_call(®s); - if (regs.regs[0]) { + arm_smccc_smc(SMC_DRAM_BANK_INFO, i, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) { ret = -EINVAL; break; }
- debug("bank[%d]: start %lx, size %lx\n", i, regs.regs[1], - regs.regs[2]); - gd->bd->bi_dram[i].start = regs.regs[1]; - gd->bd->bi_dram[i].size = regs.regs[2]; + debug("bank[%d]: start %lx, size %lx\n", i, res.a1, res.a2); + gd->bd->bi_dram[i].start = res.a1; + gd->bd->bi_dram[i].size = res.a2;
dram_size -= gd->bd->bi_dram[i].size;
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/mp.c b/arch/arm/cpu/armv8/fsl-layerscape/mp.c index d28ab26533..c6d76034b6 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/mp.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/mp.c @@ -301,6 +301,7 @@ int cpu_release(u32 nr, int argc, char *const argv[]) u64 boot_addr; u64 *table = get_spin_tbl_addr(); int pos; + int ret;
boot_addr = simple_strtoull(argv[0], NULL, 16);
@@ -325,16 +326,10 @@ int cpu_release(u32 nr, int argc, char *const argv[]) asm volatile("sev"); } else { /* Use PSCI to kick the core */ - struct pt_regs regs; - printf("begin to kick cpu core #%d to address %llx\n", nr, boot_addr); - regs.regs[0] = PSCI_0_2_FN64_CPU_ON; - regs.regs[1] = nr; - regs.regs[2] = boot_addr; - regs.regs[3] = 0; - smc_call(®s); - if (regs.regs[0]) + ret = invoke_psci_fn(PSCI_0_2_FN64_CPU_ON, nr, boot_addr, 0); + if (ret) return -1; }
diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c index e62e9dc380..d0ad6eeb0a 100644 --- a/arch/arm/cpu/armv8/sec_firmware.c +++ b/arch/arm/cpu/armv8/sec_firmware.c @@ -13,6 +13,7 @@ #include <asm/global_data.h> #include <asm/ptrace.h> #include <linux/kernel.h> +#include <linux/arm-smccc.h> #include <asm/io.h> #include <asm/system.h> #include <asm/types.h> @@ -374,29 +375,25 @@ bool sec_firmware_support_hwrng(void) */ int sec_firmware_get_random(uint8_t *rand, int bytes) { + struct arm_smccc_res res; unsigned long long num; - struct pt_regs regs; int param1;
if (!bytes || bytes > 8) { printf("Max Random bytes genration supported is 8\n"); return -1; } -#define SIP_RNG_64 0xC200FF11 - regs.regs[0] = SIP_RNG_64; - if (bytes <= 4) param1 = 0; else param1 = 1; - regs.regs[1] = param1; - - smc_call(®s);
- if (regs.regs[0]) +#define SIP_RNG_64 0xC200FF11 + arm_smccc_smc(SIP_RNG_64, param1, 0, 0, 0, 0, 0, 0, &res); + if (res.a0) return -1;
- num = regs.regs[1]; + num = res.a1; memcpy(rand, &num, bytes);
return 0; @@ -473,8 +470,8 @@ int fdt_fixup_kaslr(void *fdt) return 1; }
- ret = sec_firmware_get_random(rand, 8); - if (ret < 0) { + err = sec_firmware_get_random(rand, 8); + if (err < 0) { printf("WARNING: No random number to set kaslr-seed\n"); return 1; }

If we are running in EL2 skip PSCI implementation setup. This avoids an exception if CONFIG_ARMV8_PSCI is set, but u-boot is started by TF-A.
Signed-off-by: Michael Walle michael@walle.cc --- arch/arm/cpu/armv8/cpu.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/cpu/armv8/cpu.c b/arch/arm/cpu/armv8/cpu.c index ea40c55dd2..db5d460eb4 100644 --- a/arch/arm/cpu/armv8/cpu.c +++ b/arch/arm/cpu/armv8/cpu.c @@ -79,6 +79,9 @@ static void relocate_secure_section(void)
void armv8_setup_psci(void) { + if (current_el() != 3) + return; + relocate_secure_section(); secure_ram_addr(psci_setup_vectors)(); secure_ram_addr(psci_arch_init)();

There is an user-selectable SYS_HAS_ARMV8_SECURE_BASE, which has the same meaning but is just for the ls1043ardb board. As no in-tree config uses this, drop it and replace it with something more sophiticated: ARMV8_PSCI_RELOCATE. This option will then enable the ARMV8_SECURE_BASE option which is used as the base to relocate the PSCI code (or any code in the secure region, but that is only PSCI). A SoC (or board) can now opt-in into having such a secure region by enabling SYS_HAS_ARMV8_SECURE_BASE. Enable it for the LS1043A SoC, where it was possible to relocate the PSCI code before as well as on the LS1028A SoC where there will be PSCI support soon.
Additionally, make ARMV8_PSCI and SEC_FIRMWARE_ARMV8_PSCI exclusive.
Signed-off-by: Michael Walle michael@walle.cc --- arch/arm/cpu/armv8/Kconfig | 30 ++++++++++++++--------- arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 2 ++ board/freescale/ls1043ardb/Kconfig | 8 ------ 3 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig index 0a3fdfa471..9289526230 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -84,6 +84,7 @@ config SPL_RECOVER_DATA_SECTION config SEC_FIRMWARE_ARMV8_PSCI bool "PSCI implementation in secure monitor firmware" depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT + depends on ARMV8_PSCI=n help This config enables the ARMv8 PSCI implementation in secure monitor firmware. This is a private PSCI implementation and different from @@ -125,6 +126,9 @@ config PSCI_RESET
Select Y here to make use of PSCI calls for system reset
+config SYS_HAS_ARMV8_SECURE_BASE + bool + config ARMV8_PSCI bool "Enable PSCI support" if EXPERT help @@ -152,23 +156,27 @@ config ARMV8_PSCI_CPUS_PER_CLUSTER A value 0 or no definition of it works for single cluster system. System with multi-cluster should difine their own exact value.
-config ARMV8_EA_EL3_FIRST - bool "External aborts and SError interrupt exception are taken in EL3" +config ARMV8_PSCI_RELOCATE + bool "Relocate PSCI code" + depends on ARMV8_PSCI + depends on SYS_HAS_ARMV8_SECURE_BASE help - Exception handling at all exception levels for External Abort and - SError interrupt exception are taken in EL3. - -if SYS_HAS_ARMV8_SECURE_BASE + Relocate PSCI code, for example to a secure memory on the SoC. If not + set, the PSCI sections are placed together with the u-boot and the + regions will be marked as reserved before linux is started.
config ARMV8_SECURE_BASE hex "Secure address for PSCI image" - depends on ARMV8_PSCI + depends on ARMV8_PSCI_RELOCATE + default 0x18000000 if ARCH_LS1028A help Address for placing the PSCI text, data and stack sections. - If not defined, the PSCI sections are placed together with the u-boot - but platform can choose to place PSCI code image separately in other - places such as some secure RAM built-in SOC etc.
-endif + +config ARMV8_EA_EL3_FIRST + bool "External aborts and SError interrupt exception are taken in EL3" + help + Exception handling at all exception levels for External Abort and + SError interrupt exception are taken in EL3.
endif diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 14ef07e74f..8b1728862d 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -53,6 +53,7 @@ config ARCH_LS1028A select SYS_FSL_ERRATUM_A011334 select SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND select RESV_RAM if GIC_V3_ITS + select SYS_HAS_ARMV8_SECURE_BASE imply PANIC_HANG
config ARCH_LS1043A @@ -88,6 +89,7 @@ config ARCH_LS1043A select SYS_I2C_MXC_I2C2 if !DM_I2C select SYS_I2C_MXC_I2C3 if !DM_I2C select SYS_I2C_MXC_I2C4 if !DM_I2C + select SYS_HAS_ARMV8_SECURE_BASE imply CMD_PCI imply ID_EEPROM
diff --git a/board/freescale/ls1043ardb/Kconfig b/board/freescale/ls1043ardb/Kconfig index 778b8d8d5a..d66c7804b1 100644 --- a/board/freescale/ls1043ardb/Kconfig +++ b/board/freescale/ls1043ardb/Kconfig @@ -13,14 +13,6 @@ config SYS_SOC config SYS_CONFIG_NAME default "ls1043ardb"
-config SYS_HAS_ARMV8_SECURE_BASE - bool "Enable secure address for PSCI image" - depends on ARMV8_PSCI - help - PSCI image can be re-located to secure RAM. - If enabled, please also define the value for ARMV8_SECURE_BASE, - for LS1043ARDB, it could be some address in OCRAM. - if FSL_LS_PPA config SYS_LS_PPA_FW_ADDR hex "PPA Firmware Addr"

For now, this only provides reset and poweroff functions.
Signed-off-by: Michael Walle michael@walle.cc --- board/kontron/sl28/Makefile | 2 ++ board/kontron/sl28/psci.c | 42 ++++++++++++++++++++++++++++++++++ configs/kontron_sl28_defconfig | 2 ++ 3 files changed, 46 insertions(+) create mode 100644 board/kontron/sl28/psci.c
diff --git a/board/kontron/sl28/Makefile b/board/kontron/sl28/Makefile index 5d220f0744..084c11da37 100644 --- a/board/kontron/sl28/Makefile +++ b/board/kontron/sl28/Makefile @@ -6,6 +6,8 @@ endif
obj-y += common.o ddr.o
+obj-$(CONFIG_ARMV8_PSCI) += psci.o + ifdef CONFIG_SPL_BUILD obj-y += spl.o obj-$(CONFIG_SPL_ATF) += spl_atf.o diff --git a/board/kontron/sl28/psci.c b/board/kontron/sl28/psci.c new file mode 100644 index 0000000000..19f0ef3b6d --- /dev/null +++ b/board/kontron/sl28/psci.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <asm/secure.h> +#include <asm/psci.h> +#include <asm/types.h> +#include <asm/io.h> +#include <asm/system.h> + +#define GPIO2_GPDIR 0x2310000 +#define GPIO2_GPDAT 0x2310008 +#define RSTCR 0x1e60000 +#define RESET_REQ BIT(1) + +u32 __secure psci_version(void) +{ + return ARM_PSCI_VER_0_2; +} + +void __secure psci_system_reset(void) +{ + writel(RESET_REQ, RSTCR); + + while (1) + wfi(); +} + +void __secure psci_system_off(void) +{ + int i; + + writel(0x02000000, GPIO2_GPDIR); + writel(0, GPIO2_GPDAT); + + /* make sure the management controller has sampled the input */ + for (i = 0; i < (1 << 11); i++) + asm("nop"); + + writel(RESET_REQ, RSTCR); + + while (1) + wfi(); +} diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index 7fb6bdbe82..c9d6767055 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -19,6 +19,8 @@ CONFIG_ENV_OFFSET_REDUND=0x3f0000 CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI=y # CONFIG_PSCI_RESET is not set +CONFIG_ARMV8_PSCI=y +CONFIG_ARMV8_PSCI_RELOCATE=y CONFIG_AHCI=y CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_LOAD_ADDR=0x82000000
participants (2)
-
Michael Walle
-
Priyanka Jain