aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorBastian Hecht <hechtb@gmail.com>2013-01-09 14:41:51 -0500
committerSimon Horman <horms+renesas@verge.net.au>2013-01-24 22:43:47 -0500
commit33419a69a56436dda8e9187cf09ff0bde74d8a01 (patch)
treea904655e54b25073cf90be39374713cb1132d14e /arch/arm/mach-shmobile
parent895d3b53fd910f78c52cba89243107fb132538f3 (diff)
ARM: SH-Mobile: sh73a0: Secondary CPUs handle own SCU flags
When booting secondary CPUs we have used the main CPU to set up the Snoop Control Unit flags of these CPUs. It is a cleaner approach if every CPU takes care of its own flags. We avoid the need for locking and the program logic is more concise. With this patch the file headsmp-sh73a0.S is added that contains a startup vector for secondary CPUs that sets up its own SCU flags. Further in sh73a0_smp_prepare_cpus() we can rely on the generic ARM helper scu_power_mode(). This is possible as we don't cross borders anymore (every CPU handles its own flags) and need no locking. So we can throw out the needless function modify_scu_cpu_psr(). Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Makefile2
-rw-r--r--arch/arm/mach-shmobile/headsmp-sh73a0.S50
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h1
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c30
4 files changed, 56 insertions, 27 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index f6aba6d61d89..700e6623aa86 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
15# SMP objects 15# SMP objects
16smp-y := platsmp.o headsmp.o 16smp-y := platsmp.o headsmp.o
17smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o 17smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
18smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o 18smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o
19smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o 19smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
20smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o 20smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
21 21
diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
new file mode 100644
index 000000000000..bec4c0d9b713
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
@@ -0,0 +1,50 @@
1/*
2 * SMP support for SoC sh73a0
3 *
4 * Copyright (C) 2012 Bastian Hecht
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 */
21
22#include <linux/linkage.h>
23#include <linux/init.h>
24#include <asm/memory.h>
25
26 __CPUINIT
27/*
28 * Reset vector for secondary CPUs.
29 *
30 * First we turn on L1 cache coherency for our CPU. Then we jump to
31 * shmobile_invalidate_start that invalidates the cache and hands over control
32 * to the common ARM startup code.
33 * This function will be mapped to address 0 by the SBAR register.
34 * A normal branch is out of range here so we need a long jump. We jump to
35 * the physical address as the MMU is still turned off.
36 */
37 .align 12
38ENTRY(sh73a0_secondary_vector)
39 mrc p15, 0, r0, c0, c0, 5 @ read MIPDR
40 and r0, r0, #3 @ mask out cpu ID
41 lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits
42 mov r1, #0xf0000000 @ SCU base address
43 ldr r2, [r1, #8] @ SCU Power Status Register
44 mov r3, #3
45 bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode)
46 str r2, [r1, #8] @ write back
47
48 ldr pc, 1f
491: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
50ENDPROC(sh73a0_secondary_vector)
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index c0ab595bc18f..4b1af936fae9 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -41,6 +41,7 @@ extern void sh73a0_add_standard_devices(void);
41extern void sh73a0_clock_init(void); 41extern void sh73a0_clock_init(void);
42extern void sh73a0_pinmux_init(void); 42extern void sh73a0_pinmux_init(void);
43extern void sh73a0_pm_init(void); 43extern void sh73a0_pm_init(void);
44extern void sh73a0_secondary_vector(void);
44extern struct clk sh73a0_extal1_clk; 45extern struct clk sh73a0_extal1_clk;
45extern struct clk sh73a0_extal2_clk; 46extern struct clk sh73a0_extal2_clk;
46extern struct clk sh73a0_extcki_clk; 47extern struct clk sh73a0_extcki_clk;
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 5c5bcb595350..430b44ea85f2 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -41,9 +41,6 @@ static void __iomem *scu_base_addr(void)
41 return (void __iomem *)0xf0000000; 41 return (void __iomem *)0xf0000000;
42} 42}
43 43
44static DEFINE_SPINLOCK(scu_lock);
45static unsigned long tmp;
46
47#ifdef CONFIG_HAVE_ARM_TWD 44#ifdef CONFIG_HAVE_ARM_TWD
48static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); 45static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
49void __init sh73a0_register_twd(void) 46void __init sh73a0_register_twd(void)
@@ -52,20 +49,6 @@ void __init sh73a0_register_twd(void)
52} 49}
53#endif 50#endif
54 51
55static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
56{
57 void __iomem *scu_base = scu_base_addr();
58
59 spin_lock(&scu_lock);
60 tmp = __raw_readl(scu_base + 8);
61 tmp &= ~clr;
62 tmp |= set;
63 spin_unlock(&scu_lock);
64
65 /* disable cache coherency after releasing the lock */
66 __raw_writel(tmp, scu_base + 8);
67}
68
69static unsigned int __init sh73a0_get_core_count(void) 52static unsigned int __init sh73a0_get_core_count(void)
70{ 53{
71 void __iomem *scu_base = scu_base_addr(); 54 void __iomem *scu_base = scu_base_addr();
@@ -82,9 +65,6 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
82{ 65{
83 cpu = cpu_logical_map(cpu); 66 cpu = cpu_logical_map(cpu);
84 67
85 /* enable cache coherency */
86 modify_scu_cpu_psr(0, 3 << (cpu * 8));
87
88 if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3) 68 if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
89 __raw_writel(1 << cpu, WUPCR); /* wake up */ 69 __raw_writel(1 << cpu, WUPCR); /* wake up */
90 else 70 else
@@ -95,16 +75,14 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
95 75
96static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) 76static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
97{ 77{
98 int cpu = cpu_logical_map(0);
99
100 scu_enable(scu_base_addr()); 78 scu_enable(scu_base_addr());
101 79
102 /* Map the reset vector (in headsmp.S) */ 80 /* Map the reset vector (in headsmp-sh73a0.S) */
103 __raw_writel(0, APARMBAREA); /* 4k */ 81 __raw_writel(0, APARMBAREA); /* 4k */
104 __raw_writel(__pa(shmobile_secondary_vector), SBAR); 82 __raw_writel(__pa(sh73a0_secondary_vector), SBAR);
105 83
106 /* enable cache coherency on CPU0 */ 84 /* enable cache coherency on booting CPU */
107 modify_scu_cpu_psr(0, 3 << (cpu * 8)); 85 scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
108} 86}
109 87
110static void __init sh73a0_smp_init_cpus(void) 88static void __init sh73a0_smp_init_cpus(void)