summaryrefslogtreecommitdiff
path: root/arch/arm/mach-versatile/platsmp-vexpress.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2022-04-01 15:35:42 +0300
committerArnd Bergmann <arnd@arndb.de>2022-04-04 11:22:37 +0300
commitd7445676e86900f8dc363825033ff62416c216e0 (patch)
treee7f964467c325f4242e6cea29b5df46bbc889fea /arch/arm/mach-versatile/platsmp-vexpress.c
parent3123109284176b1532874591f7c81f3837bbdc17 (diff)
downloadlinux-d7445676e86900f8dc363825033ff62416c216e0.tar.xz
ARM: versatile: move integrator/realview/vexpress to versatile
These are all fairly small platforms by now, and they are closely related. Just move them all into a single directory. Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Liviu Dudau <liviu.dudau@arm.com> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Tested-by: Sudeep Holla <sudeep.holla@arm.com> Acked-by: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-versatile/platsmp-vexpress.c')
-rw-r--r--arch/arm/mach-versatile/platsmp-vexpress.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/arch/arm/mach-versatile/platsmp-vexpress.c b/arch/arm/mach-versatile/platsmp-vexpress.c
new file mode 100644
index 000000000000..1ee3c45e71c9
--- /dev/null
+++ b/arch/arm/mach-versatile/platsmp-vexpress.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/vexpress.h>
+
+#include <asm/mcpm.h>
+#include <asm/smp_scu.h>
+#include <asm/mach/map.h>
+
+#include "platsmp.h"
+#include "vexpress.h"
+
+bool __init vexpress_smp_init_ops(void)
+{
+#ifdef CONFIG_MCPM
+ int cpu;
+ struct device_node *cpu_node, *cci_node;
+
+ /*
+ * The best way to detect a multi-cluster configuration
+ * is to detect if the kernel can take over CCI ports
+ * control. Loop over possible CPUs and check if CCI
+ * port control is available.
+ * Override the default vexpress_smp_ops if so.
+ */
+ for_each_possible_cpu(cpu) {
+ bool available;
+
+ cpu_node = of_get_cpu_node(cpu, NULL);
+ if (WARN(!cpu_node, "Missing cpu device node!"))
+ return false;
+
+ cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
+ available = cci_node && of_device_is_available(cci_node);
+ of_node_put(cci_node);
+ of_node_put(cpu_node);
+
+ if (!available)
+ return false;
+ }
+
+ mcpm_smp_set_ops();
+ return true;
+#else
+ return false;
+#endif
+}
+
+static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
+ { .compatible = "arm,cortex-a5-scu", },
+ { .compatible = "arm,cortex-a9-scu", },
+ {}
+};
+
+static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *scu = of_find_matching_node(NULL,
+ vexpress_smp_dt_scu_match);
+
+ if (scu)
+ scu_enable(of_iomap(scu, 0));
+
+ /*
+ * Write the address of secondary startup into the
+ * system-wide flags register. The boot monitor waits
+ * until it receives a soft interrupt, and then the
+ * secondary CPU branches to this address.
+ */
+ vexpress_flags_set(__pa_symbol(versatile_secondary_startup));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void vexpress_cpu_die(unsigned int cpu)
+{
+ versatile_immitation_cpu_die(cpu, 0x40);
+}
+#endif
+
+const struct smp_operations vexpress_smp_dt_ops __initconst = {
+ .smp_prepare_cpus = vexpress_smp_dt_prepare_cpus,
+ .smp_secondary_init = versatile_secondary_init,
+ .smp_boot_secondary = versatile_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = vexpress_cpu_die,
+#endif
+};