1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2002 ARM Ltd. 4 * All Rights Reserved 5 * Copyright (c) 2010, Code Aurora Forum. All rights reserved. 6 * Copyright (c) 2014 The Linux Foundation. All rights reserved. 7 */ 8 9 #include <linux/init.h> 10 #include <linux/errno.h> 11 #include <linux/delay.h> 12 #include <linux/device.h> 13 #include <linux/of.h> 14 #include <linux/of_address.h> 15 #include <linux/smp.h> 16 #include <linux/io.h> 17 #include <linux/qcom_scm.h> 18 19 #include <asm/smp_plat.h> 20 21 22 #define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x35a0 23 #define SCSS_CPU1CORE_RESET 0x2d80 24 #define SCSS_DBG_STATUS_CORE_PWRDUP 0x2e64 25 26 #define APCS_CPU_PWR_CTL 0x04 27 #define PLL_CLAMP BIT(8) 28 #define CORE_PWRD_UP BIT(7) 29 #define COREPOR_RST BIT(5) 30 #define CORE_RST BIT(4) 31 #define L2DT_SLP BIT(3) 32 #define CLAMP BIT(0) 33 34 #define APC_PWR_GATE_CTL 0x14 35 #define BHS_CNT_SHIFT 24 36 #define LDO_PWR_DWN_SHIFT 16 37 #define LDO_BYP_SHIFT 8 38 #define BHS_SEG_SHIFT 1 39 #define BHS_EN BIT(0) 40 41 #define APCS_SAW2_VCTL 0x14 42 #define APCS_SAW2_2_VCTL 0x1c 43 44 extern void secondary_startup_arm(void); 45 46 #ifdef CONFIG_HOTPLUG_CPU 47 static void qcom_cpu_die(unsigned int cpu) 48 { 49 wfi(); 50 } 51 #endif 52 53 static int scss_release_secondary(unsigned int cpu) 54 { 55 struct device_node *node; 56 void __iomem *base; 57 58 node = of_find_compatible_node(NULL, NULL, "qcom,gcc-msm8660"); 59 if (!node) { 60 pr_err("%s: can't find node\n", __func__); 61 return -ENXIO; 62 } 63 64 base = of_iomap(node, 0); 65 of_node_put(node); 66 if (!base) 67 return -ENOMEM; 68 69 writel_relaxed(0, base + VDD_SC1_ARRAY_CLAMP_GFS_CTL); 70 writel_relaxed(0, base + SCSS_CPU1CORE_RESET); 71 writel_relaxed(3, base + SCSS_DBG_STATUS_CORE_PWRDUP); 72 mb(); 73 iounmap(base); 74 75 return 0; 76 } 77 78 static int kpssv1_release_secondary(unsigned int cpu) 79 { 80 int ret = 0; 81 void __iomem *reg, *saw_reg; 82 struct device_node *cpu_node, *acc_node, *saw_node; 83 u32 val; 84 85 cpu_node = of_get_cpu_node(cpu, NULL); 86 if (!cpu_node) 87 return -ENODEV; 88 89 acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); 90 if (!acc_node) { 91 ret = -ENODEV; 92 goto out_acc; 93 } 94 95 saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); 96 if (!saw_node) { 97 ret = -ENODEV; 98 goto out_saw; 99 } 100 101 reg = of_iomap(acc_node, 0); 102 if (!reg) { 103 ret = -ENOMEM; 104 goto out_acc_map; 105 } 106 107 saw_reg = of_iomap(saw_node, 0); 108 if (!saw_reg) { 109 ret = -ENOMEM; 110 goto out_saw_map; 111 } 112 113 /* Turn on CPU rail */ 114 writel_relaxed(0xA4, saw_reg + APCS_SAW2_VCTL); 115 mb(); 116 udelay(512); 117 118 /* Krait bring-up sequence */ 119 val = PLL_CLAMP | L2DT_SLP | CLAMP; 120 writel_relaxed(val, reg + APCS_CPU_PWR_CTL); 121 val &= ~L2DT_SLP; 122 writel_relaxed(val, reg + APCS_CPU_PWR_CTL); 123 mb(); 124 ndelay(300); 125 126 val |= COREPOR_RST; 127 writel_relaxed(val, reg + APCS_CPU_PWR_CTL); 128 mb(); 129 udelay(2); 130 131 val &= ~CLAMP; 132 writel_relaxed(val, reg + APCS_CPU_PWR_CTL); 133 mb(); 134 udelay(2); 135 136 val &= ~COREPOR_RST; 137 writel_relaxed(val, reg + APCS_CPU_PWR_CTL); 138 mb(); 139 udelay(100); 140 141 val |= CORE_PWRD_UP; 142 writel_relaxed(val, reg + APCS_CPU_PWR_CTL); 143 mb(); 144 145 iounmap(saw_reg); 146 out_saw_map: 147 iounmap(reg); 148 out_acc_map: 149 of_node_put(saw_node); 150 out_saw: 151 of_node_put(acc_node); 152 out_acc: 153 of_node_put(cpu_node); 154 return ret; 155 } 156 157 static int kpssv2_release_secondary(unsigned int cpu) 158 { 159 void __iomem *reg; 160 struct device_node *cpu_node, *l2_node, *acc_node, *saw_node; 161 void __iomem *l2_saw_base; 162 unsigned reg_val; 163 int ret; 164 165 cpu_node = of_get_cpu_node(cpu, NULL); 166 if (!cpu_node) 167 return -ENODEV; 168 169 acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); 170 if (!acc_node) { 171 ret = -ENODEV; 172 goto out_acc; 173 } 174 175 l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); 176 if (!l2_node) { 177 ret = -ENODEV; 178 goto out_l2; 179 } 180 181 saw_node = of_parse_phandle(l2_node, "qcom,saw", 0); 182 if (!saw_node) { 183 ret = -ENODEV; 184 goto out_saw; 185 } 186 187 reg = of_iomap(acc_node, 0); 188 if (!reg) { 189 ret = -ENOMEM; 190 goto out_map; 191 } 192 193 l2_saw_base = of_iomap(saw_node, 0); 194 if (!l2_saw_base) { 195 ret = -ENOMEM; 196 goto out_saw_map; 197 } 198 199 /* Turn on the BHS, turn off LDO Bypass and power down LDO */ 200 reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN; 201 writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); 202 mb(); 203 /* wait for the BHS to settle */ 204 udelay(1); 205 206 /* Turn on BHS segments */ 207 reg_val |= 0x3f << BHS_SEG_SHIFT; 208 writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); 209 mb(); 210 /* wait for the BHS to settle */ 211 udelay(1); 212 213 /* Finally turn on the bypass so that BHS supplies power */ 214 reg_val |= 0x3f << LDO_BYP_SHIFT; 215 writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); 216 217 /* enable max phases */ 218 writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL); 219 mb(); 220 udelay(50); 221 222 reg_val = COREPOR_RST | CLAMP; 223 writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); 224 mb(); 225 udelay(2); 226 227 reg_val &= ~CLAMP; 228 writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); 229 mb(); 230 udelay(2); 231 232 reg_val &= ~COREPOR_RST; 233 writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); 234 mb(); 235 236 reg_val |= CORE_PWRD_UP; 237 writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); 238 mb(); 239 240 ret = 0; 241 242 iounmap(l2_saw_base); 243 out_saw_map: 244 iounmap(reg); 245 out_map: 246 of_node_put(saw_node); 247 out_saw: 248 of_node_put(l2_node); 249 out_l2: 250 of_node_put(acc_node); 251 out_acc: 252 of_node_put(cpu_node); 253 254 return ret; 255 } 256 257 static DEFINE_PER_CPU(int, cold_boot_done); 258 259 static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) 260 { 261 int ret = 0; 262 263 if (!per_cpu(cold_boot_done, cpu)) { 264 ret = func(cpu); 265 if (!ret) 266 per_cpu(cold_boot_done, cpu) = true; 267 } 268 269 /* 270 * Send the secondary CPU a soft interrupt, thereby causing 271 * the boot monitor to read the system wide flags register, 272 * and branch to the address found there. 273 */ 274 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 275 276 return ret; 277 } 278 279 static int msm8660_boot_secondary(unsigned int cpu, struct task_struct *idle) 280 { 281 return qcom_boot_secondary(cpu, scss_release_secondary); 282 } 283 284 static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) 285 { 286 return qcom_boot_secondary(cpu, kpssv1_release_secondary); 287 } 288 289 static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle) 290 { 291 return qcom_boot_secondary(cpu, kpssv2_release_secondary); 292 } 293 294 static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) 295 { 296 int cpu; 297 298 if (qcom_scm_set_cold_boot_addr(secondary_startup_arm, 299 cpu_present_mask)) { 300 for_each_present_cpu(cpu) { 301 if (cpu == smp_processor_id()) 302 continue; 303 set_cpu_present(cpu, false); 304 } 305 pr_warn("Failed to set CPU boot address, disabling SMP\n"); 306 } 307 } 308 309 static const struct smp_operations smp_msm8660_ops __initconst = { 310 .smp_prepare_cpus = qcom_smp_prepare_cpus, 311 .smp_boot_secondary = msm8660_boot_secondary, 312 #ifdef CONFIG_HOTPLUG_CPU 313 .cpu_die = qcom_cpu_die, 314 #endif 315 }; 316 CPU_METHOD_OF_DECLARE(qcom_smp, "qcom,gcc-msm8660", &smp_msm8660_ops); 317 318 static const struct smp_operations qcom_smp_kpssv1_ops __initconst = { 319 .smp_prepare_cpus = qcom_smp_prepare_cpus, 320 .smp_boot_secondary = kpssv1_boot_secondary, 321 #ifdef CONFIG_HOTPLUG_CPU 322 .cpu_die = qcom_cpu_die, 323 #endif 324 }; 325 CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); 326 327 static const struct smp_operations qcom_smp_kpssv2_ops __initconst = { 328 .smp_prepare_cpus = qcom_smp_prepare_cpus, 329 .smp_boot_secondary = kpssv2_boot_secondary, 330 #ifdef CONFIG_HOTPLUG_CPU 331 .cpu_die = qcom_cpu_die, 332 #endif 333 }; 334 CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops); 335