
Set the enable-method in the cpu node to psci, create the psci device tree node and also add a reserve section for the psci code that lives in in normal RAM, so that the kernel leaves it alone
Signed-off-by: Arnab Basu arnab.basu@freescale.com Reviewed-by: Bhupesh Sharma bhupesh.sharma@freescale.com Cc: Marc Zyngier marc.zyngier@arm.com --- arch/arm/cpu/armv8/cpu-dt.c | 67 +++++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/system.h | 4 ++ 2 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/arch/arm/cpu/armv8/cpu-dt.c b/arch/arm/cpu/armv8/cpu-dt.c index 9792bc0..c2c8fe7 100644 --- a/arch/arm/cpu/armv8/cpu-dt.c +++ b/arch/arm/cpu/armv8/cpu-dt.c @@ -9,7 +9,69 @@ #include <fdt_support.h>
#ifdef CONFIG_MP +#ifdef CONFIG_ARMV8_PSCI
+static void psci_reserve_mem(void *fdt) +{ +#ifndef CONFIG_ARMV8_SECURE_BASE + /* secure code lives in RAM, keep it alive */ + fdt_add_mem_rsv(fdt, (unsigned long)__secure_start, + __secure_end - __secure_start); +#endif +} + +static int cpu_update_dt_psci(void *fdt) +{ + int nodeoff; + int tmp; + + psci_reserve_mem(fdt); + + nodeoff = fdt_path_offset(fdt, "/cpus"); + if (nodeoff < 0) { + printf("couldn't find /cpus\n"); + return nodeoff; + } + + /* add 'enable-method = "psci"' to each cpu node */ + for (tmp = fdt_first_subnode(fdt, nodeoff); + tmp >= 0; + tmp = fdt_next_subnode(fdt, tmp)) { + const struct fdt_property *prop; + int len; + + prop = fdt_get_property(fdt, tmp, "device_type", &len); + if (!prop) + continue; + if (len < 4) + continue; + if (strcmp(prop->data, "cpu")) + continue; + + fdt_setprop_string(fdt, tmp, "enable-method", "psci"); + } + + nodeoff = fdt_path_offset(fdt, "/psci"); + if (nodeoff < 0) { + nodeoff = fdt_path_offset(fdt, "/"); + if (nodeoff < 0) + return nodeoff; + + nodeoff = fdt_add_subnode(fdt, nodeoff, "psci"); + if (nodeoff < 0) + return nodeoff; + } + + tmp = fdt_setprop_string(fdt, nodeoff, "compatible", "arm,psci-0.2"); + if (tmp) + return tmp; + tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc"); + if (tmp) + return tmp; + + return 0; +} +#else __weak u64 arch_get_release_addr(u64 cpu_id) { return 0; @@ -51,11 +113,16 @@ static void cpu_update_dt_spin_table(void *blob) arch_spin_table_reserve_mem(blob); } #endif +#endif
int cpu_update_dt(void *fdt) { #ifdef CONFIG_MP +#ifdef CONFIG_ARMV8_PSCI + cpu_update_dt_psci(fdt); +#else cpu_update_dt_spin_table(fdt); #endif +#endif return 0; } diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index d51ba66..a1066d4 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -77,6 +77,10 @@ void gic_init(void); void gic_send_sgi(unsigned long sgino); void wait_for_wakeup(void); void smp_kick_all_cpus(void); +#ifdef CONFIG_ARMV8_PSCI +extern char __secure_start[]; +extern char __secure_end[]; +#endif
void flush_l3_cache(void);