Skip to contentSkip to conversation

ARM: shmobile: r8a7790 SMP prototype v3

PATCH New Magnus Damm 2 participants 3 messages Jul 1, 2013 – Jul 8, 2013

Subsystems (5)
lore
Share & tools
lore

Magnus Damm

author maintainer
#0 lore raw

PATCH 1/1 ARM: shmobile: r8a7790 SMP prototype v3

From: Magnus Damm <[email protected]>

Add SMP prototype support for r8a7790 by enabling one cluster of either 4 x Cortex-A7 or 4 x Cortex-A15.

This patch only adds support for booting, at this point no CPU Hotplug is included. Both the big and the LITTLE cluster are working at this point, but in case of LITTLE broadcast timer and CMT are known to work while CA7 arch timer support needs more work.

On r8a7790 the MD6 pin control boot processor, and on the Lager board SW8.7 can be used to select big or LITTLE.

In big boot mode the CPU cores will be configured as:
- CPU0, CPU1, CPU2, CPU3: enabled (CA15)
- CPU4, CPU5, CPU6, CPU7: disabled (CA7)

In LITTLE boot mode the CPU cores will be configured as:
- CPU0, CPU5, CPU6, CPU7: enabled (CA7)
- CPU1, CPU2, CPU3, CPU4: disabled (CA15)

In case of LITTLE boot mode make sure to disable arch timer support in the kernel config with CONFIG_HAVE_ARM_ARCH_TIMER=n.

---
Written against renesas.git renesas-next-20130701 and [PATCH v2 00/07] ARM: shmobile: Remove unused auxdata and callbacks [PATCH 00/04] ARM: shmobile: Use default ->init_irq()

 arch/arm/boot/dts/r8a7790.dtsi                |   49 ++++++
 arch/arm/mach-shmobile/Makefile               |    1 
 arch/arm/mach-shmobile/board-lager.c          |    1 
 arch/arm/mach-shmobile/include/mach/common.h  |    1 
 arch/arm/mach-shmobile/include/mach/r8a7790.h |    1 
 arch/arm/mach-shmobile/setup-r8a7790.c        |    1 
 arch/arm/mach-shmobile/smp-r8a7790.c          |  187 +++++++++++++++++++++++++
 7 files changed, 241 insertions(+)
arch/arm/boot/dts/r8a7790.dtsi +49 -0
@@ -24,6 +24,55 @@
 			reg = <0>;
 			clock-frequency = <1300000000>;
 		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu4: cpu at 4 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+			clock-frequency = <780000000>;
+		};
+
+		cpu5: cpu at 5 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+			clock-frequency = <780000000>;
+		};
+
+		cpu6: cpu at 6 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x102>;
+			clock-frequency = <780000000>;
+		};
+
+		cpu7: cpu at 7 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x103>;
+			clock-frequency = <780000000>;
+		};
 	};
 
 	gic: interrupt-controller at f1001000 {
arch/arm/mach-shmobile/Makefile +1 -0
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.
 smp-y				:= platsmp.o headsmp.o
 smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-scu.o
 smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o headsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7790)	+= smp-r8a7790.o
 smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o headsmp-scu.o
 
 # IRQ objects
arch/arm/mach-shmobile/board-lager.c +1 -0
@@ -102,6 +102,7 @@ static const char *lager_boards_compat_d
 };
 
 DT_MACHINE_START(LAGER_DT, "lager")
+	.smp		= smp_ops(r8a7790_smp_ops),
 	.init_early	= r8a7790_init_delay,
 	.init_time	= r8a7790_timer_init,
 	.init_machine	= lager_add_standard_devices,
arch/arm/mach-shmobile/include/mach/common.h +1 -0
@@ -11,6 +11,7 @@ extern void shmobile_boot_vector(void);
 extern unsigned long shmobile_boot_fn;
 extern unsigned long shmobile_boot_arg;
 extern void shmobile_boot_scu(void);
+extern void shmobile_invalidate_start(void);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
arch/arm/mach-shmobile/include/mach/r8a7790.h +1 -0
@@ -6,5 +6,6 @@ void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
 void r8a7790_init_delay(void);
 void r8a7790_timer_init(void);
+extern struct smp_operations r8a7790_smp_ops;
 
 #endif /* __ASM_R8A7790_H__ */
arch/arm/mach-shmobile/setup-r8a7790.c +1 -0
@@ -223,6 +223,7 @@ static const char *r8a7790_boards_compat
 };
 
 DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
+	.smp		= smp_ops(r8a7790_smp_ops),
 	.init_early	= r8a7790_init_delay,
 	.init_time	= r8a7790_timer_init,
 	.dt_compat	= r8a7790_boards_compat_dt,
arch/arm/mach-shmobile/smp-r8a7790.c new file +187 -0

187 lines not on this page · raw message

#1 lore raw

PATCH 1/1 ARM: shmobile: r8a7790 SMP prototype v3

Magnus,

Thanks for the patch, see my comments below.

arch/arm/mach-shmobile/smp-r8a7790.c line 37

Quoted 9 lines · Magnus Damm
arch/arm/mach-shmobile/smp-r8a7790.c new file +5 -0
@@ -0,0 +1,187 @@
 
+#define SYSC	0xe6180000
+#define SYSCSR  0x0000
+
+#define RST	0xe6160000
+#define CA15BAR	0x6020

CA15BAR and CA15BAR2 addresses in the datasheet v0.5 are simply wrong; they should be 0x0020 and 0x0024, respectively.

You could confirm it in the documentation errata for v0.5 or in the latest datasheet v0.6 release.

I believe that this is not related to an uncertain arch_timer issue you mentioned in the commit log, but we should use proper addresses at least.

arch/arm/mach-shmobile/smp-r8a7790.c line 39

Quoted 2 lines
arch/arm/mach-shmobile/smp-r8a7790.c new file +2 -0
+#define CA15RESCNT 0x0040
+#define CA7BAR	0x4030

The same applies for CA7BAR and CA7BAR2 as well.

Quoted 33 lines
arch/arm/mach-shmobile/smp-r8a7790.c new file +33 -0
+#define CA7RESCNT 0x0044
+#define RESCNT	0x0050
+
+#define APMU	0xe6150000
+#define CA15WUPCR 0x2010
+#define CA7WUPCR 0x1010
+
+#define MERAM	0xe8080000
+
+enum { R8A7790_CLST_CA15, R8A7790_CLST_CA7, R8A7790_CLST_NR };
+
+static struct {
+	unsigned int cabar;
+	unsigned int carescnt;
+	unsigned int carescnt_magic;
+	unsigned int rescnt_bit;
+	unsigned int use_count;
+} r8a7790_clst[R8A7790_CLST_NR] = {
+	[R8A7790_CLST_CA15] = {
+		.cabar = CA15BAR,
+		.carescnt = CA15RESCNT,
+		.carescnt_magic = 0xa5a50000,
+		.rescnt_bit = 1,
+	},
+	[R8A7790_CLST_CA7] = {
+		.cabar = CA7BAR,
+		.carescnt = CA7RESCNT,
+		.carescnt_magic = 0x5a5a0000,
+		.rescnt_bit = 0,
+	},
+};
+
+#define r8a7790_clst_id(cpu) (cpu_logical_map((cpu)) >> 8)

arch/arm/mach-shmobile/smp-r8a7790.c line 82

Quoted 10 lines
arch/arm/mach-shmobile/smp-r8a7790.c new file +10 -0
+#define r8a7790_cpu_id(cpu) (cpu_logical_map((cpu)) & 0xff)
+
+static void r8a7790_deassert_reset(unsigned int cpu)
+{
+	void __iomem *p, *carescnt;
+	u32 bar, mask, magic;
+	unsigned int clst_id = r8a7790_clst_id(cpu);
+
+	/* setup reset vectors */
+	p = ioremap_nocache(RST, 0x7000);

Therefore ioremap size for RST should be updated accordingly.

Quoted 16 lines
arch/arm/mach-shmobile/smp-r8a7790.c new file +16 -0
+	bar = (MERAM >> 8) & 0xfffffc00;
+	__raw_writel(bar, p + r8a7790_clst[clst_id].cabar);
+	__raw_writel(bar | 0x10, p + r8a7790_clst[clst_id].cabar);
+
+	/* enable clocks for cluster */
+	if (r8a7790_clst[clst_id].use_count++ == 0) {
+		mask = 1 << r8a7790_clst[clst_id].rescnt_bit;
+		__raw_writel(__raw_readl(p + RESCNT) & ~mask, p + RESCNT);
+	}
+
+	/* enable per-core clocks */
+	mask = BIT(3 - r8a7790_cpu_id(cpu));
+	magic = r8a7790_clst[clst_id].carescnt_magic;
+	carescnt = p + r8a7790_clst[clst_id].carescnt;
+	__raw_writel((__raw_readl(carescnt) & ~mask) | magic, carescnt);
+

arch/arm/mach-shmobile/smp-r8a7790.c line 108

Quoted 10 lines
arch/arm/mach-shmobile/smp-r8a7790.c new file +10 -0
+	iounmap(p);
+}
+
+static void r8a7790_assert_reset(unsigned int cpu)
+{
+	void __iomem *p, *carescnt;
+	u32 mask, magic;
+	unsigned int clst_id = r8a7790_clst_id(cpu);
+
+	p = ioremap_nocache(RST, 0x7000);

Ditto.
--
Shinya Kuribayashi
Renesas Electronics

author maintainer
#2 lore raw

PATCH 1/1 ARM: shmobile: r8a7790 SMP prototype v3

Hi Kuribayashi-san,

Quoted 18 lines · Shinya Kuribayashi

Magnus,

Thanks for the patch, see my comments below.

arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900

Quoted 9 lines · Magnus Damm
arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900 new file +5 -0
@@ -0,0 +1,187 @@
 
+#define SYSC 0xe6180000
+#define SYSCSR  0x0000
+
+#define RST  0xe6160000
+#define CA15BAR      0x6020

CA15BAR and CA15BAR2 addresses in the datasheet v0.5 are simply wrong; they should be 0x0020 and 0x0024, respectively.

Quoted 5 lines

You could confirm it in the documentation errata for v0.5 or in the latest datasheet v0.6 release.

I believe that this is not related to an uncertain arch_timer issue you mentioned in the commit log, but we should use proper addresses at least.

Thanks for pointing this out. Will fix.

Quoted 4 lines

arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900

Quoted 2 lines
arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900 new file +2 -0
+#define CA15RESCNT 0x0040
+#define CA7BAR       0x4030

The same applies for CA7BAR and CA7BAR2 as well.

Ok, will fix!

Quoted 37 lines
Quoted 37 lines
arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900 new file +37 -0
+#define CA7RESCNT 0x0044
+#define RESCNT       0x0050
+
+#define APMU 0xe6150000
+#define CA15WUPCR 0x2010
+#define CA7WUPCR 0x1010
+
+#define MERAM        0xe8080000
+
+enum { R8A7790_CLST_CA15, R8A7790_CLST_CA7, R8A7790_CLST_NR };
+
+static struct {
+     unsigned int cabar;
+     unsigned int carescnt;
+     unsigned int carescnt_magic;
+     unsigned int rescnt_bit;
+     unsigned int use_count;
+} r8a7790_clst[R8A7790_CLST_NR] = {
+     [R8A7790_CLST_CA15] = {
+             .cabar = CA15BAR,
+             .carescnt = CA15RESCNT,
+             .carescnt_magic = 0xa5a50000,
+             .rescnt_bit = 1,
+     },
+     [R8A7790_CLST_CA7] = {
+             .cabar = CA7BAR,
+             .carescnt = CA7RESCNT,
+             .carescnt_magic = 0x5a5a0000,
+             .rescnt_bit = 0,
+     },
+};
+
+#define r8a7790_clst_id(cpu) (cpu_logical_map((cpu)) >> 8)
+#define r8a7790_cpu_id(cpu) (cpu_logical_map((cpu)) & 0xff)
+
+static void r8a7790_deassert_reset(unsigned int cpu)
+{
Quoted 8 lines

arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900

Quoted 6 lines
arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900 new file +6 -0
+     void __iomem *p, *carescnt;
+     u32 bar, mask, magic;
+     unsigned int clst_id = r8a7790_clst_id(cpu);
+
+     /* setup reset vectors */
+     p = ioremap_nocache(RST, 0x7000);

Therefore ioremap size for RST should be updated accordingly.

Sure, will do.

Quoted 20 lines
Quoted 20 lines
arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900 new file +20 -0
+     bar = (MERAM >> 8) & 0xfffffc00;
+     __raw_writel(bar, p + r8a7790_clst[clst_id].cabar);
+     __raw_writel(bar | 0x10, p + r8a7790_clst[clst_id].cabar);
+
+     /* enable clocks for cluster */
+     if (r8a7790_clst[clst_id].use_count++ == 0) {
+             mask = 1 << r8a7790_clst[clst_id].rescnt_bit;
+             __raw_writel(__raw_readl(p + RESCNT) & ~mask, p + RESCNT);
+     }
+
+     /* enable per-core clocks */
+     mask = BIT(3 - r8a7790_cpu_id(cpu));
+     magic = r8a7790_clst[clst_id].carescnt_magic;
+     carescnt = p + r8a7790_clst[clst_id].carescnt;
+     __raw_writel((__raw_readl(carescnt) & ~mask) | magic, carescnt);
+
+     iounmap(p);
+}
+
+static void r8a7790_assert_reset(unsigned int cpu)
Quoted 8 lines

arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900

Quoted 6 lines
arch/arm/mach-shmobile/smp-r8a7790.c 2013-07-01 13:41:32.000000000 +0900 new file +6 -0
+{
+     void __iomem *p, *carescnt;
+     u32 mask, magic;
+     unsigned int clst_id = r8a7790_clst_id(cpu);
+
+     p = ioremap_nocache(RST, 0x7000);

Ditto.

Sounds good. I will include this together with feedback from Arnd and RMK in next version.

Thanks,

/ magnus