@@ -37,6 +37,7 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o
+obj-$(CONFIG_ARCH_R8A73A4) += pm-r8a73a4.o
# Framework support
obj-$(CONFIG_SMP) += $(smp-y)
@@ -21,6 +21,7 @@
#include <asm/suspend.h>
#include "common.h"
#include "rcar-gen2.h"
+#include "r8a73a4.h"
static struct {
void __iomem *iomem;
@@ -194,7 +195,7 @@ static void apmu_init_cpu(struct resource *res, int cpu, int bit)
pr_debug("apmu ioremap %d %d %pr\n", cpu, bit, res);
- /* Setup for debug mode */
+ /* Setup for debug mode */ // FIXME Not documented on APE6?
x = readl(apmu_cpus[cpu].iomem + DBGRCR_OFFS);
x |= DBGCPUREN | DBGCPUNREN(bit) | DBGCPUPREN;
writel(x, apmu_cpus[cpu].iomem + DBGRCR_OFFS);
@@ -253,7 +254,9 @@ static void __init shmobile_smp_apmu_setup_boot(void)
{
/* install boot code shared by all CPUs */
shmobile_boot_fn = __pa_symbol(shmobile_smp_boot);
+#ifdef CONFIG_ARCH_RCAR_GEN2 // FIXME
shmobile_boot_fn_gen2 = shmobile_boot_fn;
+#endif
}
static int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
@@ -269,7 +272,15 @@ static void __init shmobile_smp_apmu_prepare_cpus_dt(unsigned int max_cpus)
{
shmobile_smp_apmu_setup_boot();
apmu_parse_dt(apmu_init_cpu);
- rcar_gen2_pm_init();
+ if (of_machine_is_compatible("renesas,r8a73a4")) { // FIXME
+#ifdef CONFIG_ARCH_R8A73A4
+ r8a73a4_pm_init();
+#endif
+ } else {
+#ifdef CONFIG_ARCH_RCAR_GEN2
+ rcar_gen2_pm_init();
+#endif
+ }
}
static struct smp_operations apmu_smp_ops __initdata = {
new file mode 100644
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R-Mobile APE6 Power management support
+ * Based on R-Car Generation 2 Power management support
+ *
+ * Copyright (C) 2013 - 2015 Renesas Electronics Corporation
+ * Copyright (C) 2011 - 2013 Renesas Solutions Corp.
+ * Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
+ * Copyright (C) 2011 Magnus Damm
+ */
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+#include <asm/cputype.h>
+#include "common.h"
+#include "r8a73a4.h"
+
+/* System Controller */
+#define SYSC 0xe6180000 // FIXME
+
+/* Boot Address Registers */
+#define CA7BAR 0x4020 /* CA7 Boot Address Register */
+#define CA15BAR 0x6020 /* CA15 Boot Address Register */
+#define SBAR_BAREN BIT(4) /* SBAR is valid */
+
+/* Reset Control Register */
+#define RESCNT 0x801c /* Reset Control Register */
+#define RESCNT_MSTPCA15 BIT(10) /* AP-System Core(CA15) Module stop */
+#define RESCNT_MSTPCA7 BIT(9) /* AP-System Core(CA9) Module stop */
+
+/* CCI-400 */
+#define CCI_BASE 0xf0190000 // FIXME
+
+#define CCI_SLAVE3 0x4000 /* S3: CA15 */
+#define CCI_SLAVE4 0x5000 /* S4: CA7 */
+
+#define CCI_PORT_CTRL 0x0000
+
+#define CCI_ENABLE_SNOOP_REQ BIT(0)
+#define CCI_ENABLE_DVM_REQ BIT(1)
+#define CCI_ENABLE_REQ (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
+
+#define CCI_CTRL_STATUS 0x000c
+
+static inline u32 phys_to_sbar(phys_addr_t addr)
+{
+ return (addr >> 8) & 0xfffffc00;
+}
+
+void __init r8a73a4_pm_init(void)
+{
+ void __iomem *p;
+ u32 bar;
+ static int once;
+ struct device_node *np;
+ bool has_a7 = false;
+ bool has_a15 = false;
+ struct resource res;
+ int error;
+
+ if (once++)
+ return;
+
+ for_each_of_cpu_node(np) {
+ if (of_device_is_compatible(np, "arm,cortex-a15"))
+ has_a15 = true;
+ else if (of_device_is_compatible(np, "arm,cortex-a7"))
+ has_a7 = true;
+ }
+
+ np = of_find_compatible_node(NULL, NULL, "renesas,smp-sram");
+ if (!np)
+ return;
+
+ error = of_address_to_resource(np, 0, &res);
+ of_node_put(np);
+ if (error) {
+ pr_err("Failed to get smp-sram address: %d\n", error);
+ return;
+ }
+
+ /* RAM for jump stub, because BAR requires 256KB aligned address */
+ if (res.start & (256 * 1024 - 1) ||
+ resource_size(&res) < shmobile_boot_size) {
+ pr_err("Invalid smp-sram region\n");
+ return;
+ }
+
+ /* install reset vector */
+ p = ioremap(res.start, resource_size(&res));
+ if (!p)
+ return;
+
+ memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ iounmap(p);
+
+ /* setup reset vector and disable reset */
+ p = ioremap(SYSC, 0x9000);
+ bar = phys_to_sbar(res.start);
+ if (has_a15) {
+ writel_relaxed(bar, p + CA15BAR);
+ // FIXME The register write below breaks the CFI FLASH:
+ // -0.flash: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000089 Chip ID 0x0088b1
+ // -Intel/Sharp Extended Query Table at 0x010A
+ // -Intel/Sharp Extended Query Table at 0x010A
+ // -Intel/Sharp Extended Query Table at 0x010A
+ // -Intel/Sharp Extended Query Table at 0x010A
+ // -Intel/Sharp Extended Query Table at 0x010A
+ // -Using buffer write method
+ // -Using auto-unlock on power-up/resume
+ // -cfi_cmdset_0001: Erase suspend on write enabled
+ // -erase region 0: offset=0x0,size=0x40000,blocks=512
+ // -0.flash: program region size/ctrl_valid/ctrl_inval = 1024/16/16
+ // -0.flash: 1 set(s) of 1 interleaved chips --> 8 partitions of 16384 KiB
+ // -3 fixed-partitions partitions found on MTD device 0.flash
+ // -Creating 3 MTD partitions on "0.flash":
+ // -0x000000000000-0x000000040000 : "uboot"
+ // -0x000000040000-0x000000080000 : "uboot-env"
+ // -0x000000080000-0x000008000000 : "flash"
+ // +physmap-flash 0.flash: map_probe failed
+ writel_relaxed(bar | SBAR_BAREN, p + CA15BAR);
+
+ /* de-assert reset for CA15 CPUs */
+ writel_relaxed(readl_relaxed(p + RESCNT) & ~RESCNT_MSTPCA15,
+ p + RESCNT);
+ }
+ if (has_a7) {
+ writel_relaxed(bar, p + CA7BAR);
+ writel_relaxed(bar | SBAR_BAREN, p + CA7BAR);
+
+ /* de-assert reset for CA7 CPUs */
+ writel_relaxed(readl_relaxed(p + RESCNT) & ~RESCNT_MSTPCA7,
+ p + RESCNT);
+ }
+ iounmap(p);
+
+ /* enable snoop and DVM */
+ p = ioremap(CCI_BASE, 0x8000);
+ if (has_a15)
+ writel_relaxed(CCI_ENABLE_REQ, p + CCI_SLAVE3 + CCI_PORT_CTRL);
+ if (has_a7)
+ writel_relaxed(CCI_ENABLE_REQ, p + CCI_SLAVE4 + CCI_PORT_CTRL);
+ while (readl_relaxed(p + CCI_CTRL_STATUS))
+ /* wait for pending bit low */;
+ iounmap(p);
+
+ shmobile_smp_apmu_suspend_init();
+}
new file mode 100644
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_R8A73A4_H__
+#define __ASM_R8A73A4_H__
+
+void r8a73a4_pm_init(void);
+
+#endif /* __ASM_R8A73A4_H__ */
@@ -117,6 +117,7 @@ config ARCH_R8A73A4
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
select HAVE_ARM_ARCH_TIMER
+ select RENESAS_APMU
select RENESAS_IRQC
config ARCH_R7S72100
Hoop up APMU-based secondary CPU support for R-Mobile APE6. This brings up the 3 other Cortex-A15 CPU cores. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> --- arch/arm/mach-shmobile/Makefile | 1 + arch/arm/mach-shmobile/platsmp-apmu.c | 15 ++- arch/arm/mach-shmobile/pm-r8a73a4.c | 152 ++++++++++++++++++++++++++ arch/arm/mach-shmobile/r8a73a4.h | 7 ++ drivers/soc/renesas/Kconfig | 1 + 5 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-shmobile/pm-r8a73a4.c create mode 100644 arch/arm/mach-shmobile/r8a73a4.h