6601ad4e0daff1deccc6c26c4932dda29b5c3fd3
[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 diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h
26 index 0a4899b..572479a 100644
27 --- a/arch/arm/mach-msm/common.h
28 +++ b/arch/arm/mach-msm/common.h
29 @@ -23,8 +23,6 @@ extern void msm_map_qsd8x50_io(void);
30  extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
31                                           unsigned int mtype, void *caller);
32  
33 -extern struct smp_operations msm_smp_ops;
34 -
35  struct msm_mmc_platform_data;
36  
37  extern void msm_add_devices(void);
38 diff --git a/arch/arm/mach-qcom/board.c b/arch/arm/mach-qcom/board.c
39 index 830f69c..bae617e 100644
40 --- a/arch/arm/mach-qcom/board.c
41 +++ b/arch/arm/mach-qcom/board.c
42 @@ -11,30 +11,16 @@
43   */
44  
45  #include <linux/init.h>
46 -#include <linux/of.h>
47 -#include <linux/of_platform.h>
48  
49  #include <asm/mach/arch.h>
50 -#include <asm/mach/map.h>
51 -
52 -extern struct smp_operations qcom_smp_ops;
53  
54  static const char * const qcom_dt_match[] __initconst = {
55         "qcom,msm8660-surf",
56         "qcom,msm8960-cdp",
57 -       NULL
58 -};
59 -
60 -static const char * const apq8074_dt_match[] __initconst = {
61         "qcom,apq8074-dragonboard",
62         NULL
63  };
64  
65  DT_MACHINE_START(QCOM_DT, "Qualcomm (Flattened Device Tree)")
66 -       .smp = smp_ops(qcom_smp_ops),
67         .dt_compat = qcom_dt_match,
68  MACHINE_END
69 -
70 -DT_MACHINE_START(APQ_DT, "Qualcomm (Flattened Device Tree)")
71 -       .dt_compat = apq8074_dt_match,
72 -MACHINE_END
73 diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
74 index 9c53ea7..ec8604d 100644
75 --- a/arch/arm/mach-qcom/platsmp.c
76 +++ b/arch/arm/mach-qcom/platsmp.c
77 @@ -13,17 +13,18 @@
78  #include <linux/errno.h>
79  #include <linux/delay.h>
80  #include <linux/device.h>
81 +#include <linux/of.h>
82 +#include <linux/of_address.h>
83  #include <linux/smp.h>
84  #include <linux/io.h>
85  
86 -#include <asm/cputype.h>
87  #include <asm/smp_plat.h>
88  
89  #include "scm-boot.h"
90  
91 -#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
92 -#define SCSS_CPU1CORE_RESET 0xD80
93 -#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
94 +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL    0x35a0
95 +#define SCSS_CPU1CORE_RESET            0x2d80
96 +#define SCSS_DBG_STATUS_CORE_PWRDUP    0x2e64
97  
98  extern void secondary_startup(void);
99  
100 @@ -36,12 +37,6 @@ static void __ref qcom_cpu_die(unsigned int cpu)
101  }
102  #endif
103  
104 -static inline int get_core_count(void)
105 -{
106 -       /* 1 + the PART[1:0] field of MIDR */
107 -       return ((read_cpuid_id() >> 4) & 3) + 1;
108 -}
109 -
110  static void qcom_secondary_init(unsigned int cpu)
111  {
112         /*
113 @@ -51,33 +46,41 @@ static void qcom_secondary_init(unsigned int cpu)
114         spin_unlock(&boot_lock);
115  }
116  
117 -static void prepare_cold_cpu(unsigned int cpu)
118 +static int scss_release_secondary(unsigned int cpu)
119  {
120 -       int ret;
121 -       ret = scm_set_boot_addr(virt_to_phys(secondary_startup),
122 -                               SCM_FLAG_COLDBOOT_CPU1);
123 -       if (ret == 0) {
124 -               void __iomem *sc1_base_ptr;
125 -               sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
126 -               if (sc1_base_ptr) {
127 -                       writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
128 -                       writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET);
129 -                       writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
130 -                       iounmap(sc1_base_ptr);
131 -               }
132 -       } else
133 -               printk(KERN_DEBUG "Failed to set secondary core boot "
134 -                                 "address\n");
135 +       struct device_node *node;
136 +       void __iomem *base;
137 +
138 +       node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660");
139 +       if (!node) {
140 +               pr_err("%s: can't find node\n", __func__);
141 +               return -ENXIO;
142 +       }
143 +
144 +       base = of_iomap(node, 0);
145 +       of_node_put(node);
146 +       if (!base)
147 +               return -ENOMEM;
148 +
149 +       writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
150 +       writel_relaxed(0, base + SCSS_CPU1CORE_RESET);
151 +       writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP);
152 +       mb();
153 +       iounmap(base);
154 +
155 +       return 0;
156  }
157  
158 -static int qcom_boot_secondary(unsigned int cpu, struct task_struct *idle)
159 +static DEFINE_PER_CPU(int, cold_boot_done);
160 +
161 +static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
162  {
163 -       static int cold_boot_done;
164 +       int ret = 0;
165  
166 -       /* Only need to bring cpu out of reset this way once */
167 -       if (cold_boot_done == false) {
168 -               prepare_cold_cpu(cpu);
169 -               cold_boot_done = true;
170 +       if (!per_cpu(cold_boot_done, cpu)) {
171 +               ret = func(cpu);
172 +               if (!ret)
173 +                       per_cpu(cold_boot_done, cpu) = true;
174         }
175  
176         /*
177 @@ -99,39 +102,48 @@ static int qcom_boot_secondary(unsigned int cpu, struct task_struct *idle)
178          */
179         spin_unlock(&boot_lock);
180  
181 -       return 0;
182 +       return ret;
183  }
184  
185 -/*
186 - * Initialise the CPU possible map early - this describes the CPUs
187 - * which may be present or become present in the system. The msm8x60
188 - * does not support the ARM SCU, so just set the possible cpu mask to
189 - * NR_CPUS.
190 - */
191 -static void __init qcom_smp_init_cpus(void)
192 +static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle)
193  {
194 -       unsigned int i, ncores = get_core_count();
195 -
196 -       if (ncores > nr_cpu_ids) {
197 -               pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
198 -                       ncores, nr_cpu_ids);
199 -               ncores = nr_cpu_ids;
200 -       }
201 -
202 -       for (i = 0; i < ncores; i++)
203 -               set_cpu_possible(i, true);
204 +       return qcom_boot_secondary(cpu, scss_release_secondary);
205  }
206  
207  static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
208  {
209 +       int cpu, map;
210 +       unsigned int flags = 0;
211 +       static const int cold_boot_flags[] = {
212 +               0,
213 +               SCM_FLAG_COLDBOOT_CPU1,
214 +       };
215 +
216 +       for_each_present_cpu(cpu) {
217 +               map = cpu_logical_map(cpu);
218 +               if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) {
219 +                       set_cpu_present(cpu, false);
220 +                       continue;
221 +               }
222 +               flags |= cold_boot_flags[map];
223 +       }
224 +
225 +       if (scm_set_boot_addr(virt_to_phys(secondary_startup), flags)) {
226 +               for_each_present_cpu(cpu) {
227 +                       if (cpu == smp_processor_id())
228 +                               continue;
229 +                       set_cpu_present(cpu, false);
230 +               }
231 +               pr_warn("Failed to set CPU boot address, disabling SMP\n");
232 +       }
233  }
234  
235 -struct smp_operations qcom_smp_ops __initdata = {
236 -       .smp_init_cpus          = qcom_smp_init_cpus,
237 +static struct smp_operations smp_msm8660_ops __initdata = {
238         .smp_prepare_cpus       = qcom_smp_prepare_cpus,
239         .smp_secondary_init     = qcom_secondary_init,
240 -       .smp_boot_secondary     = qcom_boot_secondary,
241 +       .smp_boot_secondary     = msm8660_boot_secondary,
242  #ifdef CONFIG_HOTPLUG_CPU
243         .cpu_die                = qcom_cpu_die,
244  #endif
245  };
246 +CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops);
247 -- 
248 1.7.10.4
249