diff options
Diffstat (limited to 'arch/arm/mach-mvebu/platsmp.c')
-rw-r--r-- | arch/arm/mach-mvebu/platsmp.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c new file mode 100644 index 000000000000..fe16aaf7c19c --- /dev/null +++ b/arch/arm/mach-mvebu/platsmp.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * Symmetric Multi Processing (SMP) support for Armada XP | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell | ||
5 | * | ||
6 | * Lior Amsalem <alior@marvell.com> | ||
7 | * Yehuda Yitschak <yehuday@marvell.com> | ||
8 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | ||
9 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | * | ||
15 | * The Armada XP SoC has 4 ARMv7 PJ4B CPUs running in full HW coherency | ||
16 | * This file implements the routines for preparing the SMP infrastructure | ||
17 | * and waking up the secondary CPUs | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | #include <asm/smp_plat.h> | ||
26 | #include "common.h" | ||
27 | #include "armada-370-xp.h" | ||
28 | #include "pmsu.h" | ||
29 | #include "coherency.h" | ||
30 | |||
31 | void __init set_secondary_cpus_clock(void) | ||
32 | { | ||
33 | int thiscpu; | ||
34 | unsigned long rate; | ||
35 | struct clk *cpu_clk = NULL; | ||
36 | struct device_node *np = NULL; | ||
37 | |||
38 | thiscpu = smp_processor_id(); | ||
39 | for_each_node_by_type(np, "cpu") { | ||
40 | int err; | ||
41 | int cpu; | ||
42 | |||
43 | err = of_property_read_u32(np, "reg", &cpu); | ||
44 | if (WARN_ON(err)) | ||
45 | return; | ||
46 | |||
47 | if (cpu == thiscpu) { | ||
48 | cpu_clk = of_clk_get(np, 0); | ||
49 | break; | ||
50 | } | ||
51 | } | ||
52 | if (WARN_ON(IS_ERR(cpu_clk))) | ||
53 | return; | ||
54 | clk_prepare_enable(cpu_clk); | ||
55 | rate = clk_get_rate(cpu_clk); | ||
56 | |||
57 | /* set all the other CPU clk to the same rate than the boot CPU */ | ||
58 | for_each_node_by_type(np, "cpu") { | ||
59 | int err; | ||
60 | int cpu; | ||
61 | |||
62 | err = of_property_read_u32(np, "reg", &cpu); | ||
63 | if (WARN_ON(err)) | ||
64 | return; | ||
65 | |||
66 | if (cpu != thiscpu) { | ||
67 | cpu_clk = of_clk_get(np, 0); | ||
68 | clk_set_rate(cpu_clk, rate); | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void __cpuinit armada_xp_secondary_init(unsigned int cpu) | ||
74 | { | ||
75 | armada_xp_mpic_smp_cpu_init(); | ||
76 | } | ||
77 | |||
78 | static int __cpuinit armada_xp_boot_secondary(unsigned int cpu, | ||
79 | struct task_struct *idle) | ||
80 | { | ||
81 | pr_info("Booting CPU %d\n", cpu); | ||
82 | |||
83 | armada_xp_boot_cpu(cpu, armada_xp_secondary_startup); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static void __init armada_xp_smp_init_cpus(void) | ||
89 | { | ||
90 | unsigned int i, ncores; | ||
91 | ncores = coherency_get_cpu_count(); | ||
92 | |||
93 | /* Limit possible CPUs to defconfig */ | ||
94 | if (ncores > nr_cpu_ids) { | ||
95 | pr_warn("SMP: %d CPUs physically present. Only %d configured.", | ||
96 | ncores, nr_cpu_ids); | ||
97 | pr_warn("Clipping CPU count to %d\n", nr_cpu_ids); | ||
98 | ncores = nr_cpu_ids; | ||
99 | } | ||
100 | |||
101 | for (i = 0; i < ncores; i++) | ||
102 | set_cpu_possible(i, true); | ||
103 | |||
104 | set_smp_cross_call(armada_mpic_send_doorbell); | ||
105 | } | ||
106 | |||
107 | void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) | ||
108 | { | ||
109 | set_secondary_cpus_clock(); | ||
110 | flush_cache_all(); | ||
111 | set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); | ||
112 | } | ||
113 | |||
114 | struct smp_operations armada_xp_smp_ops __initdata = { | ||
115 | .smp_init_cpus = armada_xp_smp_init_cpus, | ||
116 | .smp_prepare_cpus = armada_xp_smp_prepare_cpus, | ||
117 | .smp_secondary_init = armada_xp_secondary_init, | ||
118 | .smp_boot_secondary = armada_xp_boot_secondary, | ||
119 | #ifdef CONFIG_HOTPLUG_CPU | ||
120 | .cpu_die = armada_xp_cpu_die, | ||
121 | #endif | ||
122 | }; | ||