[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1523871304-48517-2-git-send-email-michel.pollet@bp.renesas.com>
Date: Mon, 16 Apr 2018 10:34:56 +0100
From: Michel Pollet <michel.pollet@...renesas.com>
To: linux-renesas-soc@...r.kernel.org,
Simon Horman <horms@...ge.net.au>
Cc: phil.edworthy@...esas.com, buserror+upstream@...il.com,
Michel Pollet <michel.pollet@...renesas.com>,
Rob Herring <robh+dt@...nel.org>,
Mark Rutland <mark.rutland@....com>,
Magnus Damm <magnus.damm@...il.com>,
Russell King <linux@...linux.org.uk>,
Chen-Yu Tsai <wens@...e.org>,
Kevin Hilman <khilman@...libre.com>,
Maxime Ripard <maxime.ripard@...tlin.com>,
Rajendra Nayak <rnayak@...eaurora.org>,
Frank Rowand <frank.rowand@...y.com>,
Florian Fainelli <f.fainelli@...il.com>,
Carlo Caione <carlo@...lessm.com>,
Juri Lelli <juri.lelli@....com>, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org
Subject: [PATCH 1/1] arm: rzn1: Add support for the second CPU.
This enables starting the second CA7 core. Also handles the case the
bootloader has had to change the second CPU parking address to allow
booting in NONSEC/HYP.
Signed-off-by: Michel Pollet <michel.pollet@...renesas.com>
---
arch/arm/mach-shmobile/Makefile | 1 +
arch/arm/mach-shmobile/r9a06g032.h | 7 +++
arch/arm/mach-shmobile/setup-r9a06g032.c | 2 +
arch/arm/mach-shmobile/smp-r9a06g032.c | 88 ++++++++++++++++++++++++++++++++
4 files changed, 98 insertions(+)
create mode 100644 arch/arm/mach-shmobile/r9a06g032.h
create mode 100644 arch/arm/mach-shmobile/smp-r9a06g032.c
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index a63e5c2..e0f8c97 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -36,6 +36,7 @@ smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o
smp-$(CONFIG_ARCH_R8A7791) += smp-r8a7791.o
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_R9A06G032) += smp-r9a06g032.o
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
diff --git a/arch/arm/mach-shmobile/r9a06g032.h b/arch/arm/mach-shmobile/r9a06g032.h
new file mode 100644
index 0000000..3992e97
--- /dev/null
+++ b/arch/arm/mach-shmobile/r9a06g032.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __R9A06G032_H__
+#define __R9A06G032_H__
+
+extern const struct smp_operations rzn1_smp_ops;
+
+#endif /* __R9A06G032_H__ */
diff --git a/arch/arm/mach-shmobile/setup-r9a06g032.c b/arch/arm/mach-shmobile/setup-r9a06g032.c
index 65288e1..7bc6216 100644
--- a/arch/arm/mach-shmobile/setup-r9a06g032.c
+++ b/arch/arm/mach-shmobile/setup-r9a06g032.c
@@ -11,6 +11,7 @@
#include <asm/mach/arch.h>
#include <dt-bindings/soc/renesas,rzn1-map.h>
#include <soc/rzn1/sysctrl.h>
+#include "r9a06g032.h"
static void __iomem *sysctrl_base_addr;
@@ -50,6 +51,7 @@ static const char *rzn1_boards_compat_dt[] __initconst = {
};
DT_MACHINE_START(RZN1_DT, "Renesas RZ/N1 (Device Tree)")
+ .smp = smp_ops(rzn1_smp_ops),
.dt_compat = rzn1_boards_compat_dt,
.restart = rzn1_restart,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/smp-r9a06g032.c b/arch/arm/mach-shmobile/smp-r9a06g032.c
new file mode 100644
index 0000000..e441188
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r9a06g032.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SMP support for Renesas RZ/N1D
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * Michel Pollet <michel.pollet@...renesas.com>, <buserror@...il.com>
+ *
+ * Based on code
+ * Copyright (C) 2012-2013 Allwinner Ltd.
+ *
+ */
+
+#include <linux/of.h>
+#include <soc/rzn1/sysctrl.h>
+#include "r9a06g032.h"
+
+#define BOOTADDR2_CANARY 0x525a4e31
+
+static void __iomem *pen2_base;
+
+static DEFINE_SPINLOCK(cpu_lock);
+
+/*
+ * The alternate boot address for the second core can be overridden in the DT,
+ * typically this will happen if the bootloader decides to park the second
+ * core somewhere else than the fixed ALT_BOOTADDR address.
+ *
+ * This use case is required for NONSEC, as the SYSCTRL BOOTADDR register isn't
+ * available after switching mode, so the bootloader parks the CPU#2 in a pen
+ * is SRAM to await on an alternate address (followed by a canary) then the
+ * bootloader switches mode, and finaly starts the kernel...
+ * The address of that alternate 'register' is passed in /chosen.
+ */
+static void __init rzn1_smp_prepare_cpus(unsigned int max_cpus)
+{
+ u32 bootaddr = 0;
+ struct device_node *np = of_find_node_by_path("/chosen");
+
+ if (np)
+ of_property_read_u32(np, "rzn1,bootaddr", &bootaddr);
+
+ if (bootaddr &&
+ bootaddr != RZN1_SYSCTRL_REG_BOOTADDR &&
+ bootaddr != (RZN1_SYSTEM_CTRL_BASE+RZN1_SYSCTRL_REG_BOOTADDR)) {
+
+ pr_info("RZ/N1 CPU#2 boot address %08x\n", bootaddr);
+ pen2_base = ioremap(bootaddr, 8);
+
+ if (!pen2_base)
+ pr_warn("Couldn't map RZ/N1 CPU#2 PEN2\n");
+ return;
+ }
+ pr_info("RZ/N1 CPU#2 boot address not specified - using SYSCTRL reg\n");
+}
+
+static int __init rzn1_smp_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ u32 t = (u32)virt_to_phys(secondary_startup);
+
+ /* Inform on what is the second CPU boot address */
+ if (pen2_base && (readl(pen2_base + 4) == BOOTADDR2_CANARY))
+ pr_info("RZ/N1 CPU#%d writing %08x to boot address\n", cpu, t);
+ else
+ pr_info("RZ/N1 CPU#%d writing %08x to SYSCTRL reg\n", cpu, t);
+
+ spin_lock(&cpu_lock);
+
+ /* Set CPU boot address */
+ if (pen2_base && (readl(pen2_base + 4) == BOOTADDR2_CANARY))
+ writel(virt_to_phys(secondary_startup), pen2_base);
+ else
+ rzn1_sysctrl_writel(virt_to_phys(secondary_startup),
+ RZN1_SYSCTRL_REG_BOOTADDR);
+
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ spin_unlock(&cpu_lock);
+
+ return 0;
+}
+
+const struct smp_operations rzn1_smp_ops __initconst = {
+ .smp_prepare_cpus = rzn1_smp_prepare_cpus,
+ .smp_boot_secondary = rzn1_smp_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(rzn1_smp, "renesas,r9a06g032", &rzn1_smp_ops);
--
2.7.4
Powered by blists - more mailing lists