ARM: HYP/non-sec/PSCI: emit DT nodes
authorMarc Zyngier <marc.zyngier@arm.com>
Sat, 12 Jul 2014 13:24:07 +0000 (14:24 +0100)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Mon, 28 Jul 2014 15:19:52 +0000 (17:19 +0200)
Generate the PSCI node in the device tree.

Also add a reserve section for the "secure" code that lives in
in normal RAM, so that the kernel knows it'd better not trip on
it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Ian Campbell <ijc@hellion.org.uk>
arch/arm/cpu/armv7/Makefile
arch/arm/cpu/armv7/virt-dt.c [new file with mode: 0644]
arch/arm/include/asm/armv7.h
arch/arm/lib/bootm-fdt.c

index 735c4ad37e297dc316018ada487307853213cfcd..703ce8c640aa09c85d53e40dae55371e9bd512ac 100644 (file)
@@ -21,6 +21,7 @@ endif
 ifneq ($(CONFIG_ARMV7_NONSEC)$(CONFIG_ARMV7_VIRT),)
 obj-y  += nonsec_virt.o
 obj-y  += virt-v7.o
+obj-y  += virt-dt.o
 endif
 
 ifneq ($(CONFIG_ARMV7_PSCI),)
diff --git a/arch/arm/cpu/armv7/virt-dt.c b/arch/arm/cpu/armv7/virt-dt.c
new file mode 100644 (file)
index 0000000..0b0d6a7
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <stdio_dev.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <asm/global_data.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/armv7.h>
+#include <asm/psci.h>
+
+static int fdt_psci(void *fdt)
+{
+#ifdef CONFIG_ARMV7_PSCI
+       int nodeoff;
+       int tmp;
+
+       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");
+       if (tmp)
+               return tmp;
+       tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
+       if (tmp)
+               return tmp;
+       tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend", ARM_PSCI_FN_CPU_SUSPEND);
+       if (tmp)
+               return tmp;
+       tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off", ARM_PSCI_FN_CPU_OFF);
+       if (tmp)
+               return tmp;
+       tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on", ARM_PSCI_FN_CPU_ON);
+       if (tmp)
+               return tmp;
+       tmp = fdt_setprop_u32(fdt, nodeoff, "migrate", ARM_PSCI_FN_MIGRATE);
+       if (tmp)
+               return tmp;
+#endif
+       return 0;
+}
+
+int armv7_update_dt(void *fdt)
+{
+#ifndef CONFIG_ARMV7_SECURE_BASE
+       /* secure code lives in RAM, keep it alive */
+       fdt_add_mem_rsv(fdt, (unsigned long)__secure_start,
+                       __secure_end - __secure_start);
+#endif
+
+       return fdt_psci(fdt);
+}
index 11476ddd164af88b2325085d3dfddd3c7cc53070..323f282fb7b953ce854ef434328655861ba76c64 100644 (file)
@@ -79,6 +79,7 @@ void v7_outer_cache_inval_range(u32 start, u32 end);
 #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
 
 int armv7_init_nonsec(void);
+int armv7_update_dt(void *fdt);
 
 /* defined in assembly file */
 unsigned int _nonsec_init(void);
index 8394e15b7e3822d3d3132deb5b13df0a61c407bd..d4f1578e9e96fcdbd1434b5c5e663339844ada83 100644 (file)
 
 #include <common.h>
 #include <fdt_support.h>
+#include <asm/armv7.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 int arch_fixup_fdt(void *blob)
 {
        bd_t *bd = gd->bd;
-       int bank;
+       int bank, ret;
        u64 start[CONFIG_NR_DRAM_BANKS];
        u64 size[CONFIG_NR_DRAM_BANKS];
 
@@ -32,5 +33,12 @@ int arch_fixup_fdt(void *blob)
                size[bank] = bd->bi_dram[bank].size;
        }
 
-       return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+       ret = fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
+       if (ret)
+               return ret;
+
+       ret = armv7_update_dt(blob);
+#endif
+       return ret;
 }