diff options
author | Bastian Hecht <hechtb@gmail.com> | 2013-01-09 14:41:51 -0500 |
---|---|---|
committer | Simon Horman <horms+renesas@verge.net.au> | 2013-01-24 22:43:47 -0500 |
commit | 33419a69a56436dda8e9187cf09ff0bde74d8a01 (patch) | |
tree | a904655e54b25073cf90be39374713cb1132d14e /arch/arm/mach-shmobile | |
parent | 895d3b53fd910f78c52cba89243107fb132538f3 (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/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/headsmp-sh73a0.S | 50 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/smp-sh73a0.c | 30 |
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 |
16 | smp-y := platsmp.o headsmp.o | 16 | smp-y := platsmp.o headsmp.o |
17 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 17 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
18 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o | 18 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o |
19 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o | 19 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o |
20 | smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o | 20 | smp-$(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 | ||
38 | ENTRY(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 | ||
49 | 1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET | ||
50 | ENDPROC(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); | |||
41 | extern void sh73a0_clock_init(void); | 41 | extern void sh73a0_clock_init(void); |
42 | extern void sh73a0_pinmux_init(void); | 42 | extern void sh73a0_pinmux_init(void); |
43 | extern void sh73a0_pm_init(void); | 43 | extern void sh73a0_pm_init(void); |
44 | extern void sh73a0_secondary_vector(void); | ||
44 | extern struct clk sh73a0_extal1_clk; | 45 | extern struct clk sh73a0_extal1_clk; |
45 | extern struct clk sh73a0_extal2_clk; | 46 | extern struct clk sh73a0_extal2_clk; |
46 | extern struct clk sh73a0_extcki_clk; | 47 | extern 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 | ||
44 | static DEFINE_SPINLOCK(scu_lock); | ||
45 | static unsigned long tmp; | ||
46 | |||
47 | #ifdef CONFIG_HAVE_ARM_TWD | 44 | #ifdef CONFIG_HAVE_ARM_TWD |
48 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); | 45 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); |
49 | void __init sh73a0_register_twd(void) | 46 | void __init sh73a0_register_twd(void) |
@@ -52,20 +49,6 @@ void __init sh73a0_register_twd(void) | |||
52 | } | 49 | } |
53 | #endif | 50 | #endif |
54 | 51 | ||
55 | static 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 | |||
69 | static unsigned int __init sh73a0_get_core_count(void) | 52 | static 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 | ||
96 | static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) | 76 | static 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 | ||
110 | static void __init sh73a0_smp_init_cpus(void) | 88 | static void __init sh73a0_smp_init_cpus(void) |