4bab4c962bbc25a3f8ec22c339452f075049308f
[openwrt/openwrt.git] / target / linux / ipq806x / patches / 0009-ARM-qcom-Re-organize-platsmp-to-make-it-extensible.patch
1 From 391848e75f8b0ba14816da1ac8f2d838fd0d5744 Mon Sep 17 00:00:00 2001
2 From: Rohit Vaswani <rvaswani@codeaurora.org>
3 Date: Tue, 21 May 2013 19:13:29 -0700
4 Subject: [PATCH 009/182] ARM: qcom: Re-organize platsmp to make it extensible
5
6 This makes it easy to add SMP support for new devices by keying
7 on a device node for the release sequence. We add the
8 enable-method property for the cpus property to specify that we
9 want to use the gcc-msm8660 release sequence (which is going to
10 look for the global clock controller device node to map some
11 Scorpion specific power and control registers). We also remove
12 the nr_cpus detection code as that is done generically in the DT
13 CPU detection code.
14
15 Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
16 [sboyd: Port to CPU_METHOD_OF_DECLARE]
17 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
18 Signed-off-by: Kumar Gala <galak@codeaurora.org>
19 ---
20 arch/arm/mach-msm/common.h | 2 -
21 arch/arm/mach-qcom/board.c | 14 -----
22 arch/arm/mach-qcom/platsmp.c | 118 +++++++++++++++++++++++-------------------
23 3 files changed, 65 insertions(+), 69 deletions(-)
24
25 --- a/arch/arm/mach-msm/common.h
26 +++ b/arch/arm/mach-msm/common.h
27 @@ -23,8 +23,6 @@ extern void msm_map_qsd8x50_io(void);
28 extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
29 unsigned int mtype, void *caller);
30
31 -extern struct smp_operations msm_smp_ops;
32 -
33 struct msm_mmc_platform_data;
34
35 extern void msm_add_devices(void);
36 --- a/arch/arm/mach-qcom/board.c
37 +++ b/arch/arm/mach-qcom/board.c
38 @@ -11,30 +11,16 @@
39 */
40
41 #include <linux/init.h>
42 -#include <linux/of.h>
43 -#include <linux/of_platform.h>
44
45 #include <asm/mach/arch.h>
46 -#include <asm/mach/map.h>
47 -
48 -extern struct smp_operations qcom_smp_ops;
49
50 static const char * const qcom_dt_match[] __initconst = {
51 "qcom,msm8660-surf",
52 "qcom,msm8960-cdp",
53 - NULL
54 -};
55 -
56 -static const char * const apq8074_dt_match[] __initconst = {
57 "qcom,apq8074-dragonboard",
58 NULL
59 };
60
61 DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
62 - .smp = smp_ops(qcom_smp_ops),
63 .dt_compat = qcom_dt_match,
64 MACHINE_END
65 -
66 -DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)")
67 - .dt_compat = apq8074_dt_match,
68 -MACHINE_END
69 --- a/arch/arm/mach-qcom/platsmp.c
70 +++ b/arch/arm/mach-qcom/platsmp.c
71 @@ -13,17 +13,18 @@
72 #include <linux/errno.h>
73 #include <linux/delay.h>
74 #include <linux/device.h>
75 +#include <linux/of.h>
76 +#include <linux/of_address.h>
77 #include <linux/smp.h>
78 #include <linux/io.h>
79
80 -#include <asm/cputype.h>
81 #include <asm/smp_plat.h>
82
83 #include "scm-boot.h"
84
85 -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
86 -#define SCSS_CPU1CORE_RESET 0xD80
87 -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
88 +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0
89 +#define SCSS_CPU1CORE_RESET 0x2d80
90 +#define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64
91
92 extern void secondary_startup(void);
93
94 @@ -36,12 +37,6 @@ static void __ref qcom_cpu_die(unsigned
95 }
96 #endif
97
98 -static inline int get_core_count(void)
99 -{
100 - /* 1 + the PART[1:0] field of MIDR */
101 - return ((read_cpuid_id() >> 4) & 3) + 1;
102 -}
103 -
104 static void qcom_secondary_init(unsigned int cpu)
105 {
106 /*
107 @@ -51,33 +46,41 @@ static void qcom_secondary_init(unsigned
108 spin_unlock(&boot_lock);
109 }
110
111 -static void prepare_cold_cpu(unsigned int cpu)
112 +static int scss_release_secondary(unsigned int cpu)
113 {
114 - int ret;
115 - ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
116 - SCM_FLAG_COLDBOOT_CPU1);
117 - if (ret == 0) {
118 - void __iomem *sc1_base_ptr;
119 - sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
120 - if (sc1_base_ptr) {
121 - writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
122 - writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
123 - writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
124 - iounmap(sc1_base_ptr);
125 - }
126 - } else
127 - printk(KERN_DEBUG "Failed to set secondary core boot "
128 - "address\n");
129 + struct device_node *node;
130 + void __iomem *base;
131 +
132 + node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660");
133 + if (!node) {
134 + pr_err("%s: can't find node\n", __func__);
135 + return -ENXIO;
136 + }
137 +
138 + base = of_iomap(node, 0);
139 + of_node_put(node);
140 + if (!base)
141 + return -ENOMEM;
142 +
143 + writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
144 + writel_relaxed(0, base + SCSS_CPU1CORE_RESET);
145 + writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP);
146 + mb();
147 + iounmap(base);
148 +
149 + return 0;
150 }
151
152 -static int qcom_boot_secondary(unsigned int cpu, struct task_struct *idle)
153 +static DEFINE_PER_CPU(int, cold_boot_done);
154 +
155 +static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
156 {
157 - static int cold_boot_done;
158 + int ret = 0;
159
160 - /* Only need to bring cpu out of reset this way once */
161 - if (cold_boot_done == false) {
162 - prepare_cold_cpu(cpu);
163 - cold_boot_done = true;
164 + if (!per_cpu(cold_boot_done, cpu)) {
165 + ret = func(cpu);
166 + if (!ret)
167 + per_cpu(cold_boot_done, cpu) = true;
168 }
169
170 /*
171 @@ -99,39 +102,48 @@ static int qcom_boot_secondary(unsigned
172 */
173 spin_unlock(&boot_lock);
174
175 - return 0;
176 + return ret;
177 }
178
179 -/*
180 - * Initialise the CPU possible map early - this describes the CPUs
181 - * which may be present or become present in the system. The msm8x60
182 - * does not support the ARM SCU, so just set the possible cpu mask to
183 - * NR_CPUS.
184 - */
185 -static void __init qcom_smp_init_cpus(void)
186 -{
187 - unsigned int i, ncores = get_core_count();
188 -
189 - if (ncores > nr_cpu_ids) {
190 - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
191 - ncores, nr_cpu_ids);
192 - ncores = nr_cpu_ids;
193 - }
194 -
195 - for (i = 0; i < ncores; i++)
196 - set_cpu_possible(i, true);
197 +static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle)
198 +{
199 + return qcom_boot_secondary(cpu, scss_release_secondary);
200 }
201
202 static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
203 {
204 + int cpu, map;
205 + unsigned int flags = 0;
206 + static const int cold_boot_flags[] = {
207 + 0,
208 + SCM_FLAG_COLDBOOT_CPU1,
209 + };
210 +
211 + for_each_present_cpu(cpu) {
212 + map = cpu_logical_map(cpu);
213 + if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) {
214 + set_cpu_present(cpu, false);
215 + continue;
216 + }
217 + flags |= cold_boot_flags[map];
218 + }
219 +
220 + if (scm_set_boot_addr(virt_to_phys(secondary_startup), flags)) {
221 + for_each_present_cpu(cpu) {
222 + if (cpu == smp_processor_id())
223 + continue;
224 + set_cpu_present(cpu, false);
225 + }
226 + pr_warn("Failed to set CPU boot address, disabling SMP\n");
227 + }
228 }
229
230 -struct smp_operations qcom_smp_ops __initdata = {
231 - .smp_init_cpus = qcom_smp_init_cpus,
232 +static struct smp_operations smp_msm8660_ops __initdata = {
233 .smp_prepare_cpus = qcom_smp_prepare_cpus,
234 .smp_secondary_init = qcom_secondary_init,
235 - .smp_boot_secondary = qcom_boot_secondary,
236 + .smp_boot_secondary = msm8660_boot_secondary,
237 #ifdef CONFIG_HOTPLUG_CPU
238 .cpu_die = qcom_cpu_die,
239 #endif
240 };
241 +CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops);