diff options
author | Rohit Vaswani <rvaswani@codeaurora.org> | 2013-05-21 22:13:50 -0400 |
---|---|---|
committer | Kumar Gala <galak@codeaurora.org> | 2014-02-11 16:00:39 -0500 |
commit | 6267809f1660cdd72fbb1032ab566facb12a3193 (patch) | |
tree | f00415007b6a045aec07d6f352ef4805a00e76d1 | |
parent | 4c6ede21cd0d4df0c68d4203fa63bb17e29d2e93 (diff) |
ARM: qcom: Add SMP support for KPSSv1
Implement support for the Krait CPU release sequence when the
CPUs are part of the first version of the krait processor
subsystem.
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
-rw-r--r-- | arch/arm/mach-qcom/platsmp.c | 106 | ||||
-rw-r--r-- | arch/arm/mach-qcom/scm-boot.h | 8 |
2 files changed, 111 insertions, 3 deletions
diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c index ec8604d6dfb5..cb0783f3ed75 100644 --- a/arch/arm/mach-qcom/platsmp.c +++ b/arch/arm/mach-qcom/platsmp.c | |||
@@ -26,6 +26,16 @@ | |||
26 | #define SCSS_CPU1CORE_RESET 0x2d80 | 26 | #define SCSS_CPU1CORE_RESET 0x2d80 |
27 | #define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64 | 27 | #define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64 |
28 | 28 | ||
29 | #define APCS_CPU_PWR_CTL 0x04 | ||
30 | #define PLL_CLAMP BIT(8) | ||
31 | #define CORE_PWRD_UP BIT(7) | ||
32 | #define COREPOR_RST BIT(5) | ||
33 | #define CORE_RST BIT(4) | ||
34 | #define L2DT_SLP BIT(3) | ||
35 | #define CLAMP BIT(0) | ||
36 | |||
37 | #define APCS_SAW2_VCTL 0x14 | ||
38 | |||
29 | extern void secondary_startup(void); | 39 | extern void secondary_startup(void); |
30 | 40 | ||
31 | static DEFINE_SPINLOCK(boot_lock); | 41 | static DEFINE_SPINLOCK(boot_lock); |
@@ -71,6 +81,85 @@ static int scss_release_secondary(unsigned int cpu) | |||
71 | return 0; | 81 | return 0; |
72 | } | 82 | } |
73 | 83 | ||
84 | static int kpssv1_release_secondary(unsigned int cpu) | ||
85 | { | ||
86 | int ret = 0; | ||
87 | void __iomem *reg, *saw_reg; | ||
88 | struct device_node *cpu_node, *acc_node, *saw_node; | ||
89 | u32 val; | ||
90 | |||
91 | cpu_node = of_get_cpu_node(cpu, NULL); | ||
92 | if (!cpu_node) | ||
93 | return -ENODEV; | ||
94 | |||
95 | acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); | ||
96 | if (!acc_node) { | ||
97 | ret = -ENODEV; | ||
98 | goto out_acc; | ||
99 | } | ||
100 | |||
101 | saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); | ||
102 | if (!saw_node) { | ||
103 | ret = -ENODEV; | ||
104 | goto out_saw; | ||
105 | } | ||
106 | |||
107 | reg = of_iomap(acc_node, 0); | ||
108 | if (!reg) { | ||
109 | ret = -ENOMEM; | ||
110 | goto out_acc_map; | ||
111 | } | ||
112 | |||
113 | saw_reg = of_iomap(saw_node, 0); | ||
114 | if (!saw_reg) { | ||
115 | ret = -ENOMEM; | ||
116 | goto out_saw_map; | ||
117 | } | ||
118 | |||
119 | /* Turn on CPU rail */ | ||
120 | writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL); | ||
121 | mb(); | ||
122 | udelay(512); | ||
123 | |||
124 | /* Krait bring-up sequence */ | ||
125 | val = PLL_CLAMP | L2DT_SLP | CLAMP; | ||
126 | writel_relaxed(val, reg + APCS_CPU_PWR_CTL); | ||
127 | val &= ~L2DT_SLP; | ||
128 | writel_relaxed(val, reg + APCS_CPU_PWR_CTL); | ||
129 | mb(); | ||
130 | ndelay(300); | ||
131 | |||
132 | val |= COREPOR_RST; | ||
133 | writel_relaxed(val, reg + APCS_CPU_PWR_CTL); | ||
134 | mb(); | ||
135 | udelay(2); | ||
136 | |||
137 | val &= ~CLAMP; | ||
138 | writel_relaxed(val, reg + APCS_CPU_PWR_CTL); | ||
139 | mb(); | ||
140 | udelay(2); | ||
141 | |||
142 | val &= ~COREPOR_RST; | ||
143 | writel_relaxed(val, reg + APCS_CPU_PWR_CTL); | ||
144 | mb(); | ||
145 | udelay(100); | ||
146 | |||
147 | val |= CORE_PWRD_UP; | ||
148 | writel_relaxed(val, reg + APCS_CPU_PWR_CTL); | ||
149 | mb(); | ||
150 | |||
151 | iounmap(saw_reg); | ||
152 | out_saw_map: | ||
153 | iounmap(reg); | ||
154 | out_acc_map: | ||
155 | of_node_put(saw_node); | ||
156 | out_saw: | ||
157 | of_node_put(acc_node); | ||
158 | out_acc: | ||
159 | of_node_put(cpu_node); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
74 | static DEFINE_PER_CPU(int, cold_boot_done); | 163 | static DEFINE_PER_CPU(int, cold_boot_done); |
75 | 164 | ||
76 | static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) | 165 | static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) |
@@ -110,6 +199,11 @@ static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
110 | return qcom_boot_secondary(cpu, scss_release_secondary); | 199 | return qcom_boot_secondary(cpu, scss_release_secondary); |
111 | } | 200 | } |
112 | 201 | ||
202 | static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
203 | { | ||
204 | return qcom_boot_secondary(cpu, kpssv1_release_secondary); | ||
205 | } | ||
206 | |||
113 | static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) | 207 | static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) |
114 | { | 208 | { |
115 | int cpu, map; | 209 | int cpu, map; |
@@ -117,6 +211,8 @@ static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) | |||
117 | static const int cold_boot_flags[] = { | 211 | static const int cold_boot_flags[] = { |
118 | 0, | 212 | 0, |
119 | SCM_FLAG_COLDBOOT_CPU1, | 213 | SCM_FLAG_COLDBOOT_CPU1, |
214 | SCM_FLAG_COLDBOOT_CPU2, | ||
215 | SCM_FLAG_COLDBOOT_CPU3, | ||
120 | }; | 216 | }; |
121 | 217 | ||
122 | for_each_present_cpu(cpu) { | 218 | for_each_present_cpu(cpu) { |
@@ -147,3 +243,13 @@ static struct smp_operations smp_msm8660_ops __initdata = { | |||
147 | #endif | 243 | #endif |
148 | }; | 244 | }; |
149 | CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); | 245 | CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); |
246 | |||
247 | static struct smp_operations qcom_smp_kpssv1_ops __initdata = { | ||
248 | .smp_prepare_cpus = qcom_smp_prepare_cpus, | ||
249 | .smp_secondary_init = qcom_secondary_init, | ||
250 | .smp_boot_secondary = kpssv1_boot_secondary, | ||
251 | #ifdef CONFIG_HOTPLUG_CPU | ||
252 | .cpu_die = qcom_cpu_die, | ||
253 | #endif | ||
254 | }; | ||
255 | CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); | ||
diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h index 7be32ff5d687..6aabb2428176 100644 --- a/arch/arm/mach-qcom/scm-boot.h +++ b/arch/arm/mach-qcom/scm-boot.h | |||
@@ -13,9 +13,11 @@ | |||
13 | #define __MACH_SCM_BOOT_H | 13 | #define __MACH_SCM_BOOT_H |
14 | 14 | ||
15 | #define SCM_BOOT_ADDR 0x1 | 15 | #define SCM_BOOT_ADDR 0x1 |
16 | #define SCM_FLAG_COLDBOOT_CPU1 0x1 | 16 | #define SCM_FLAG_COLDBOOT_CPU1 0x01 |
17 | #define SCM_FLAG_WARMBOOT_CPU1 0x2 | 17 | #define SCM_FLAG_COLDBOOT_CPU2 0x08 |
18 | #define SCM_FLAG_WARMBOOT_CPU0 0x4 | 18 | #define SCM_FLAG_COLDBOOT_CPU3 0x20 |
19 | #define SCM_FLAG_WARMBOOT_CPU0 0x04 | ||
20 | #define SCM_FLAG_WARMBOOT_CPU1 0x02 | ||
19 | 21 | ||
20 | int scm_set_boot_addr(phys_addr_t addr, int flags); | 22 | int scm_set_boot_addr(phys_addr_t addr, int flags); |
21 | 23 | ||