* [PATCH 1/2] ARM: psci: factor out of_psci_fixup() to separate file
2019-05-13 12:14 [PATCH 0/2] Layerscape: Add PPA firmware support Sascha Hauer
@ 2019-05-13 12:14 ` Sascha Hauer
2019-05-13 12:14 ` [PATCH 2/2] ARM: Layerscape: Add PPA firmware support Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2019-05-13 12:14 UTC (permalink / raw)
To: Barebox List
of_psci_fixup() can be used by code which doesn't use the barebox
psci implementation, but provides its own PSCI compatible firmware.
Factor it out to a separate file to compile it independently of the
barebox PSCI implementation.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/Kconfig | 4 +++
arch/arm/cpu/Makefile | 1 +
arch/arm/cpu/psci-of.c | 54 +++++++++++++++++++++++++++++++++++++
arch/arm/cpu/psci.c | 27 +++++--------------
arch/arm/include/asm/psci.h | 2 ++
5 files changed, 67 insertions(+), 21 deletions(-)
create mode 100644 arch/arm/cpu/psci-of.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a683c9c866..480c6f0117 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -428,10 +428,14 @@ config ARM_SECURE_MONITOR
select ARM_SMCCC
bool
+config ARM_PSCI_OF
+ bool
+
config ARM_PSCI
bool "enable Power State Coordination Interface (PSCI) support"
depends on CPU_V7
select ARM_SECURE_MONITOR
+ select ARM_PSCI_OF
help
PSCI is used for controlling secondary CPU cores on some systems. Say
yes here if you have one of these.
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index 8e1af8bf8d..d2f1e7a90b 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_CPU_32v7) += no-mmu.o
endif
obj-$(CONFIG_ARM_PSCI) += psci.o
+obj-$(CONFIG_ARM_PSCI_OF) += psci-of.o
obj-pbl-$(CONFIG_ARM_SMCCC) += smccc-call$(S64).o
AFLAGS_smccc-call$(S64).o :=-Wa,-march=armv$(if $(S64),8,7)-a
AFLAGS_pbl-smccc-call$(S64).o :=-Wa,-march=armv$(if $(S64),8,7)-a
diff --git a/arch/arm/cpu/psci-of.c b/arch/arm/cpu/psci-of.c
new file mode 100644
index 0000000000..ef83b0edee
--- /dev/null
+++ b/arch/arm/cpu/psci-of.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "psci-of: " fmt
+
+#include <common.h>
+#include <of.h>
+#include <asm/psci.h>
+#include <linux/arm-smccc.h>
+
+int of_psci_fixup(struct device_node *root, unsigned long psci_version)
+{
+ struct device_node *psci;
+ int ret;
+ const char *compat;
+ struct device_node *cpus, *cpu;
+
+ psci = of_create_node(root, "/psci");
+ if (!psci)
+ return -EINVAL;
+
+ if (psci_version >= ARM_PSCI_VER_1_0) {
+ compat = "arm,psci-1.0";
+ } else if (psci_version >= ARM_PSCI_VER_0_2) {
+ compat = "arm,psci-0.2";
+ } else {
+ pr_err("Unsupported PSCI version %ld\n", psci_version);
+ return -EINVAL;
+ }
+
+ cpus = of_find_node_by_path_from(root, "/cpus");
+ if (!cpus) {
+ pr_err("Cannot find /cpus node, PSCI fixup aborting\n");
+ return -EINVAL;
+ }
+
+ cpu = cpus;
+ while (1) {
+ cpu = of_find_node_by_type(cpu, "cpu");
+ if (!cpu)
+ break;
+ of_property_write_string(cpu, "enable-method", "psci");
+ pr_debug("Fixed %s\n", cpu->full_name);
+ }
+
+ ret = of_property_write_string(psci, "compatible", compat);
+ if (ret)
+ return ret;
+
+ ret = of_property_write_string(psci, "method", "smc");
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/arch/arm/cpu/psci.c b/arch/arm/cpu/psci.c
index 3a1abd1421..5c662cd0b9 100644
--- a/arch/arm/cpu/psci.c
+++ b/arch/arm/cpu/psci.c
@@ -190,32 +190,17 @@ void psci_entry(u32 r0, u32 r1, u32 r2, u32 r3, u32 r4, u32 r5, u32 r6,
}
}
-static int of_psci_fixup(struct device_node *root, void *unused)
-{
- struct device_node *psci;
- int ret;
+/* Avoid missing prototype warning, called from assembly */
+int psci_cpu_entry_c(void);
+static int of_psci_do_fixup(struct device_node *root, void *unused)
+{
if (bootm_arm_security_state() < ARM_STATE_NONSECURE)
return 0;
- psci = of_create_node(root, "/psci");
- if (!psci)
- return -EINVAL;
-
- ret = of_property_write_string(psci, "compatible", "arm,psci-1.0");
- if (ret)
- return ret;
-
- ret = of_property_write_string(psci, "method", "smc");
- if (ret)
- return ret;
-
- return 0;
+ return of_psci_fixup(root, ARM_PSCI_VER_1_0);
}
-/* Avoid missing prototype warning, called from assembly */
-int psci_cpu_entry_c(void);
-
int psci_cpu_entry_c(void)
{
void (*entry)(u32 context);
@@ -239,7 +224,7 @@ int psci_cpu_entry_c(void)
static int armv7_psci_init(void)
{
- return of_register_fixup(of_psci_fixup, NULL);
+ return of_register_fixup(of_psci_do_fixup, NULL);
}
device_initcall(armv7_psci_init);
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index e0c4525389..f2db967f3a 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -137,4 +137,6 @@ static inline int psci_printf(const char *fmt, ...)
int psci_get_cpu_id(void);
+int of_psci_fixup(struct device_node *root, unsigned long psci_version);
+
#endif /* __ARM_PSCI_H__ */
--
2.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 2/2] ARM: Layerscape: Add PPA firmware support
2019-05-13 12:14 [PATCH 0/2] Layerscape: Add PPA firmware support Sascha Hauer
2019-05-13 12:14 ` [PATCH 1/2] ARM: psci: factor out of_psci_fixup() to separate file Sascha Hauer
@ 2019-05-13 12:14 ` Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2019-05-13 12:14 UTC (permalink / raw)
To: Barebox List
The "Primary Protected Application" (PPA) is a PSCI compliant firmware
distributed by NXP. It is needed to start the secondary cores on
Layerscape SoCs. Without it Linux will be started in EL3 and doesn't
work properly. The precompiled firmware images can be found on
https://github.com/NXP/qoriq-ppa-binary and are not included in
barebox.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/boards/ls1046ardb/board.c | 7 +-
arch/arm/boards/ls1046ardb/lowlevel.c | 2 +-
arch/arm/boards/tqmls1046a/board.c | 6 +
arch/arm/boards/tqmls1046a/lowlevel.c | 2 +-
arch/arm/configs/layerscape_defconfig | 1 +
arch/arm/mach-layerscape/Kconfig | 13 ++
arch/arm/mach-layerscape/Makefile | 1 +
.../mach-layerscape/include/mach/layerscape.h | 10 ++
arch/arm/mach-layerscape/ppa-entry.S | 30 +++++
arch/arm/mach-layerscape/ppa.c | 118 ++++++++++++++++++
firmware/Makefile | 2 +
11 files changed, 189 insertions(+), 3 deletions(-)
create mode 100644 arch/arm/mach-layerscape/ppa-entry.S
create mode 100644 arch/arm/mach-layerscape/ppa.c
diff --git a/arch/arm/boards/ls1046ardb/board.c b/arch/arm/boards/ls1046ardb/board.c
index 483040957e..0846df9fad 100644
--- a/arch/arm/boards/ls1046ardb/board.c
+++ b/arch/arm/boards/ls1046ardb/board.c
@@ -8,16 +8,21 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <asm/system.h>
+#include <mach/layerscape.h>
static int rdb_mem_init(void)
{
+ int ret;
+
if (!of_machine_is_compatible("fsl,ls1046a-rdb"))
return 0;
arm_add_mem_device("ram0", 0x80000000, 0x80000000);
arm_add_mem_device("ram1", 0x880000000, 3ULL * SZ_2G);
- printf("Current EL: %d\n", current_el());
+ ret = ls1046a_ppa_init(0x100000000 - SZ_64M, SZ_64M);
+ if (ret)
+ pr_err("Failed to initialize PPA firmware: %s\n", strerror(-ret));
return 0;
}
diff --git a/arch/arm/boards/ls1046ardb/lowlevel.c b/arch/arm/boards/ls1046ardb/lowlevel.c
index 0c95fbb035..0a30f05aa2 100644
--- a/arch/arm/boards/ls1046ardb/lowlevel.c
+++ b/arch/arm/boards/ls1046ardb/lowlevel.c
@@ -194,7 +194,7 @@ static noinline __noreturn void ls1046ardb_r_entry(unsigned long memsize)
if (memsize + membase >= 0x100000000)
memsize = 0x100000000 - membase;
- barebox_arm_entry(membase, 0x80000000 - SZ_1M * 67,
+ barebox_arm_entry(membase, 0x80000000 - SZ_64M,
__dtb_fsl_ls1046a_rdb_start);
}
diff --git a/arch/arm/boards/tqmls1046a/board.c b/arch/arm/boards/tqmls1046a/board.c
index 8cc4d73de5..028be890e0 100644
--- a/arch/arm/boards/tqmls1046a/board.c
+++ b/arch/arm/boards/tqmls1046a/board.c
@@ -15,11 +15,17 @@
static int tqmls1046a_mem_init(void)
{
+ int ret;
+
if (!of_machine_is_compatible("tqc,tqmls1046a"))
return 0;
arm_add_mem_device("ram0", 0x80000000, SZ_2G);
+ ret = ls1046a_ppa_init(0x100000000 - SZ_64M, SZ_64M);
+ if (ret)
+ pr_err("Failed to initialize PPA firmware: %s\n", strerror(-ret));
+
return 0;
}
mem_initcall(tqmls1046a_mem_init);
diff --git a/arch/arm/boards/tqmls1046a/lowlevel.c b/arch/arm/boards/tqmls1046a/lowlevel.c
index dc0e179694..f79f491ecc 100644
--- a/arch/arm/boards/tqmls1046a/lowlevel.c
+++ b/arch/arm/boards/tqmls1046a/lowlevel.c
@@ -243,7 +243,7 @@ static noinline __noreturn void tqmls1046a_r_entry(void)
unsigned long membase = LS1046A_DDR_SDRAM_BASE;
if (get_pc() >= membase)
- barebox_arm_entry(membase, 0x80000000,
+ barebox_arm_entry(membase, 0x80000000 - SZ_64M,
__dtb_fsl_tqmls1046a_mbls10xxa_start);
arm_cpu_lowlevel_init();
diff --git a/arch/arm/configs/layerscape_defconfig b/arch/arm/configs/layerscape_defconfig
index b81f375415..b36f1944ec 100644
--- a/arch/arm/configs/layerscape_defconfig
+++ b/arch/arm/configs/layerscape_defconfig
@@ -1,4 +1,5 @@
CONFIG_ARCH_LAYERSCAPE=y
+CONFIG_ARCH_LAYERSCAPE_PPA=y
CONFIG_MACH_LS1046ARDB=y
CONFIG_MACH_TQMLS1046A=y
CONFIG_MMU=y
diff --git a/arch/arm/mach-layerscape/Kconfig b/arch/arm/mach-layerscape/Kconfig
index 3a44f3fea1..139c63f66d 100644
--- a/arch/arm/mach-layerscape/Kconfig
+++ b/arch/arm/mach-layerscape/Kconfig
@@ -1,5 +1,18 @@
if ARCH_LAYERSCAPE
+config ARCH_LAYERSCAPE_PPA
+ bool "Include PPA firmware"
+ select ARM_PSCI_OF
+ select ARM_SMCCC
+ select FITIMAGE
+ bool
+ help
+ The "Primary Protected Application" (PPA) is a PSCI compliant firmware
+ distributed by NXP. It is needed to start the secondary cores on
+ Layerscape SoCs. Without it Linux will be started in EL3 and doesn't
+ work properly. The precompiled firmware images can be found here:
+ https://github.com/NXP/qoriq-ppa-binary
+
config ARCH_LS1046
select CPU_V8
select SYS_SUPPORTS_64BIT_KERNEL
diff --git a/arch/arm/mach-layerscape/Makefile b/arch/arm/mach-layerscape/Makefile
index 73cd61a7cf..8a814f9441 100644
--- a/arch/arm/mach-layerscape/Makefile
+++ b/arch/arm/mach-layerscape/Makefile
@@ -4,3 +4,4 @@ lwl-$(CONFIG_ARCH_LS1046) += lowlevel-ls1046a.o
obj-y += icid.o
obj-pbl-y += boot.o
pbl-y += xload-qspi.o xload.o
+obj-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa.o ppa-entry.o
diff --git a/arch/arm/mach-layerscape/include/mach/layerscape.h b/arch/arm/mach-layerscape/include/mach/layerscape.h
index 3366e7f258..1f1da0f66e 100644
--- a/arch/arm/mach-layerscape/include/mach/layerscape.h
+++ b/arch/arm/mach-layerscape/include/mach/layerscape.h
@@ -6,4 +6,14 @@
enum bootsource ls1046_bootsource_get(void);
+#ifdef CONFIG_ARCH_LAYERSCAPE_PPA
+int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size);
+#else
+static inline int ls1046a_ppa_init(resource_size_t ppa_start,
+ resource_size_t ppa_size)
+{
+ return -ENOSYS;
+}
+#endif
+
#endif /* __MACH_LAYERSCAPE_H */
diff --git a/arch/arm/mach-layerscape/ppa-entry.S b/arch/arm/mach-layerscape/ppa-entry.S
new file mode 100644
index 0000000000..18cfa6c37e
--- /dev/null
+++ b/arch/arm/mach-layerscape/ppa-entry.S
@@ -0,0 +1,30 @@
+#include <linux/linkage.h>
+
+.section .text.ppa_entry
+ENTRY(ppa_entry)
+ /*
+ * x0: Secure Firmware entry point
+ * x1: Exception return address Low
+ * x2: Exception return address High
+ */
+
+ /* Save stack pointer for EL2 */
+ mov x3, sp
+ msr sp_el2, x3
+
+ /* Set exception return address hold pointer */
+ adr x4, 1f
+ mov x3, x4
+ rev w3, w3
+ str w3, [x1]
+ lsr x3, x4, #32
+ rev w3, w3
+ str w3, [x2]
+
+ /* Call SEC monitor */
+ br x0
+
+1:
+ mov x0, #0
+ ret
+ENDPROC(ppa_entry)
diff --git a/arch/arm/mach-layerscape/ppa.c b/arch/arm/mach-layerscape/ppa.c
new file mode 100644
index 0000000000..6070451020
--- /dev/null
+++ b/arch/arm/mach-layerscape/ppa.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "ppa: " fmt
+
+#include <common.h>
+#include <init.h>
+#include <firmware.h>
+#include <memory.h>
+#include <linux/sizes.h>
+#include <linux/arm-smccc.h>
+#include <asm/mmu.h>
+#include <soc/fsl/immap_lsch2.h>
+#include <asm/system.h>
+#include <image-fit.h>
+#include <asm/psci.h>
+#include <mach/layerscape.h>
+
+int ppa_entry(const void *, u32 *, u32 *);
+void dma_flush_range(void *ptr, size_t size);
+
+static int of_psci_do_fixup(struct device_node *root, void *unused)
+{
+ unsigned long psci_version;
+ struct arm_smccc_res res = {};
+
+ arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
+ psci_version = res.a0;
+
+ return of_psci_fixup(root, psci_version);
+}
+
+static int ppa_init(void *ppa, size_t ppa_size, void *sec_firmware_addr)
+{
+ int ret;
+ u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
+ struct ccsr_scfg __iomem *scfg = (void *)(LSCH2_SCFG_ADDR);
+ int el = current_el();
+ struct fit_handle *fit;
+ void *conf;
+ const void *buf;
+ unsigned long firmware_size;
+
+ if (el < 3) {
+ printf("EL%d, skip ppa init\n", el);
+ return 0;
+ }
+
+ boot_loc_ptr_l = &scfg->scratchrw[1];
+ boot_loc_ptr_h = &scfg->scratchrw[0];
+
+ fit = fit_open_buf(ppa, ppa_size, false, BOOTM_VERIFY_AVAILABLE);
+ if (IS_ERR(fit)) {
+ pr_err("Cannot open ppa FIT image: %s\n", strerrorp(fit));
+ return PTR_ERR(fit);
+ }
+
+ conf = fit_open_configuration(fit, NULL);
+ if (IS_ERR(conf)) {
+ pr_err("Cannot open default config in ppa FIT image: %s\n",
+ strerrorp(conf));
+ fit_close(fit);
+ return PTR_ERR(fit);
+ }
+
+
+ ret = fit_open_image(fit, conf, "firmware", &buf, &firmware_size);
+ if (ret) {
+ pr_err("Cannot open firmware image in ppa FIT image: %s\n",
+ strerror(-ret));
+ ret = PTR_ERR(fit);
+ goto err;
+ }
+
+ /* Copy the secure firmware to secure memory */
+ memcpy(sec_firmware_addr, buf, firmware_size);
+ dma_flush_range(sec_firmware_addr, ppa_size);
+
+ ret = ppa_entry(sec_firmware_addr, boot_loc_ptr_l, boot_loc_ptr_h);
+ if (ret) {
+ pr_err("Couldn't install PPA firmware: %s\n", strerror(-ret));
+ goto err;
+ }
+
+ pr_info("PPA firmware installed at 0x%p, now in EL%d\n",
+ sec_firmware_addr, current_el());
+
+ of_register_fixup(of_psci_do_fixup, NULL);
+err:
+ fit_close(fit);
+
+ return 0;
+}
+
+int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size)
+{
+ resource_size_t ppa_end = ppa_start + ppa_size - 1;
+ struct resource *res;
+ void *ppa_fw;
+ size_t ppa_fw_size;
+ int ret;
+
+ res = request_sdram_region("ppa", ppa_start, ppa_size);
+ if (!res) {
+ pr_err("Cannot request SDRAM region %pa - %pa\n",
+ &ppa_start, &ppa_end);
+ return -EINVAL;
+ }
+
+ get_builtin_firmware(ppa_ls1046a_bin, &ppa_fw, &ppa_fw_size);
+
+ ret = ppa_init(ppa_fw, ppa_fw_size, (void *)ppa_start);
+ if (ret)
+ return ret;
+
+ of_add_reserve_entry(ppa_start, ppa_end);
+
+ return 0;
+}
diff --git a/firmware/Makefile b/firmware/Makefile
index 306c006e23..9581ee6116 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -13,6 +13,8 @@ firmware-$(CONFIG_FIRMWARE_IMX8MQ_ATF) += imx8mq-bl31.bin
firmware-$(CONFIG_DRIVER_NET_FSL_FMAN) += fsl_fman_ucode_ls1046_r1.0_106_4_18.bin
+firmware-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa-ls1046a.bin
+
# Create $(fwabs) from $(CONFIG_EXTRA_FIRMWARE_DIR) -- if it doesn't have a
# leading /, it's relative to $(srctree).
fwdir := $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE_DIR))
--
2.20.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread