1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2015 Carlo Caione <carlo@endlessm.com> 4 * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 5 */ 6 7 #include <linux/delay.h> 8 #include <linux/init.h> 9 #include <linux/io.h> 10 #include <linux/of.h> 11 #include <linux/of_address.h> 12 #include <linux/regmap.h> 13 #include <linux/reset.h> 14 #include <linux/smp.h> 15 #include <linux/mfd/syscon.h> 16 17 #include <asm/cacheflush.h> 18 #include <asm/cp15.h> 19 #include <asm/smp_scu.h> 20 #include <asm/smp_plat.h> 21 22 #define MESON_SMP_SRAM_CPU_CTRL_REG (0x00) 23 #define MESON_SMP_SRAM_CPU_CTRL_ADDR_REG(c) (0x04 + ((c - 1) << 2)) 24 25 #define MESON_CPU_AO_RTI_PWR_A9_CNTL0 (0x00) 26 #define MESON_CPU_AO_RTI_PWR_A9_CNTL1 (0x04) 27 #define MESON_CPU_AO_RTI_PWR_A9_MEM_PD0 (0x14) 28 29 #define MESON_CPU_PWR_A9_CNTL0_M(c) (0x03 << ((c * 2) + 16)) 30 #define MESON_CPU_PWR_A9_CNTL1_M(c) (0x03 << ((c + 1) << 1)) 31 #define MESON_CPU_PWR_A9_MEM_PD0_M(c) (0x0f << (32 - (c * 4))) 32 #define MESON_CPU_PWR_A9_CNTL1_ST(c) (0x01 << (c + 16)) 33 34 static void __iomem *sram_base; 35 static void __iomem *scu_base; 36 static struct regmap *pmu; 37 38 static struct reset_control *meson_smp_get_core_reset(int cpu) 39 { 40 struct device_node *np = of_get_cpu_node(cpu, 0); 41 42 return of_reset_control_get_exclusive(np, NULL); 43 } 44 45 static void meson_smp_set_cpu_ctrl(int cpu, bool on_off) 46 { 47 u32 val = readl(sram_base + MESON_SMP_SRAM_CPU_CTRL_REG); 48 49 if (on_off) 50 val |= BIT(cpu); 51 else 52 val &= ~BIT(cpu); 53 54 /* keep bit 0 always enabled */ 55 val |= BIT(0); 56 57 writel(val, sram_base + MESON_SMP_SRAM_CPU_CTRL_REG); 58 } 59 60 static void __init meson_smp_prepare_cpus(const char *scu_compatible, 61 const char *pmu_compatible, 62 const char *sram_compatible) 63 { 64 static struct device_node *node; 65 66 /* SMP SRAM */ 67 node = of_find_compatible_node(NULL, NULL, sram_compatible); 68 if (!node) { 69 pr_err("Missing SRAM node\n"); 70 return; 71 } 72 73 sram_base = of_iomap(node, 0); 74 of_node_put(node); 75 if (!sram_base) { 76 pr_err("Couldn't map SRAM registers\n"); 77 return; 78 } 79 80 /* PMU */ 81 pmu = syscon_regmap_lookup_by_compatible(pmu_compatible); 82 if (IS_ERR(pmu)) { 83 pr_err("Couldn't map PMU registers\n"); 84 return; 85 } 86 87 /* SCU */ 88 node = of_find_compatible_node(NULL, NULL, scu_compatible); 89 if (!node) { 90 pr_err("Missing SCU node\n"); 91 return; 92 } 93 94 scu_base = of_iomap(node, 0); 95 of_node_put(node); 96 if (!scu_base) { 97 pr_err("Couldn't map SCU registers\n"); 98 return; 99 } 100 101 scu_enable(scu_base); 102 } 103 104 static void __init meson8b_smp_prepare_cpus(unsigned int max_cpus) 105 { 106 meson_smp_prepare_cpus("arm,cortex-a5-scu", "amlogic,meson8b-pmu", 107 "amlogic,meson8b-smp-sram"); 108 } 109 110 static void __init meson8_smp_prepare_cpus(unsigned int max_cpus) 111 { 112 meson_smp_prepare_cpus("arm,cortex-a9-scu", "amlogic,meson8-pmu", 113 "amlogic,meson8-smp-sram"); 114 } 115 116 static void meson_smp_begin_secondary_boot(unsigned int cpu) 117 { 118 /* 119 * Set the entry point before powering on the CPU through the SCU. This 120 * is needed if the CPU is in "warm" state (= after rebooting the 121 * system without power-cycling, or when taking the CPU offline and 122 * then taking it online again. 123 */ 124 writel(__pa_symbol(secondary_startup), 125 sram_base + MESON_SMP_SRAM_CPU_CTRL_ADDR_REG(cpu)); 126 127 /* 128 * SCU Power on CPU (needs to be done before starting the CPU, 129 * otherwise the secondary CPU will not start). 130 */ 131 scu_cpu_power_enable(scu_base, cpu); 132 } 133 134 static int meson_smp_finalize_secondary_boot(unsigned int cpu) 135 { 136 unsigned long timeout; 137 138 timeout = jiffies + (10 * HZ); 139 while (readl(sram_base + MESON_SMP_SRAM_CPU_CTRL_ADDR_REG(cpu))) { 140 if (!time_before(jiffies, timeout)) { 141 pr_err("Timeout while waiting for CPU%d status\n", 142 cpu); 143 return -ETIMEDOUT; 144 } 145 } 146 147 writel(__pa_symbol(secondary_startup), 148 sram_base + MESON_SMP_SRAM_CPU_CTRL_ADDR_REG(cpu)); 149 150 meson_smp_set_cpu_ctrl(cpu, true); 151 152 return 0; 153 } 154 155 static int meson8_smp_boot_secondary(unsigned int cpu, 156 struct task_struct *idle) 157 { 158 struct reset_control *rstc; 159 int ret; 160 161 rstc = meson_smp_get_core_reset(cpu); 162 if (IS_ERR(rstc)) { 163 pr_err("Couldn't get the reset controller for CPU%d\n", cpu); 164 return PTR_ERR(rstc); 165 } 166 167 meson_smp_begin_secondary_boot(cpu); 168 169 /* Reset enable */ 170 ret = reset_control_assert(rstc); 171 if (ret) { 172 pr_err("Failed to assert CPU%d reset\n", cpu); 173 goto out; 174 } 175 176 /* CPU power ON */ 177 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1, 178 MESON_CPU_PWR_A9_CNTL1_M(cpu), 0); 179 if (ret < 0) { 180 pr_err("Couldn't wake up CPU%d\n", cpu); 181 goto out; 182 } 183 184 udelay(10); 185 186 /* Isolation disable */ 187 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu), 188 0); 189 if (ret < 0) { 190 pr_err("Error when disabling isolation of CPU%d\n", cpu); 191 goto out; 192 } 193 194 /* Reset disable */ 195 ret = reset_control_deassert(rstc); 196 if (ret) { 197 pr_err("Failed to de-assert CPU%d reset\n", cpu); 198 goto out; 199 } 200 201 ret = meson_smp_finalize_secondary_boot(cpu); 202 if (ret) 203 goto out; 204 205 out: 206 reset_control_put(rstc); 207 208 return 0; 209 } 210 211 static int meson8b_smp_boot_secondary(unsigned int cpu, 212 struct task_struct *idle) 213 { 214 struct reset_control *rstc; 215 int ret; 216 u32 val; 217 218 rstc = meson_smp_get_core_reset(cpu); 219 if (IS_ERR(rstc)) { 220 pr_err("Couldn't get the reset controller for CPU%d\n", cpu); 221 return PTR_ERR(rstc); 222 } 223 224 meson_smp_begin_secondary_boot(cpu); 225 226 /* CPU power UP */ 227 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, 228 MESON_CPU_PWR_A9_CNTL0_M(cpu), 0); 229 if (ret < 0) { 230 pr_err("Couldn't power up CPU%d\n", cpu); 231 goto out; 232 } 233 234 udelay(5); 235 236 /* Reset enable */ 237 ret = reset_control_assert(rstc); 238 if (ret) { 239 pr_err("Failed to assert CPU%d reset\n", cpu); 240 goto out; 241 } 242 243 /* Memory power UP */ 244 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_MEM_PD0, 245 MESON_CPU_PWR_A9_MEM_PD0_M(cpu), 0); 246 if (ret < 0) { 247 pr_err("Couldn't power up the memory for CPU%d\n", cpu); 248 goto out; 249 } 250 251 /* Wake up CPU */ 252 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1, 253 MESON_CPU_PWR_A9_CNTL1_M(cpu), 0); 254 if (ret < 0) { 255 pr_err("Couldn't wake up CPU%d\n", cpu); 256 goto out; 257 } 258 259 udelay(10); 260 261 ret = regmap_read_poll_timeout(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1, val, 262 val & MESON_CPU_PWR_A9_CNTL1_ST(cpu), 263 10, 10000); 264 if (ret) { 265 pr_err("Timeout while polling PMU for CPU%d status\n", cpu); 266 goto out; 267 } 268 269 /* Isolation disable */ 270 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu), 271 0); 272 if (ret < 0) { 273 pr_err("Error when disabling isolation of CPU%d\n", cpu); 274 goto out; 275 } 276 277 /* Reset disable */ 278 ret = reset_control_deassert(rstc); 279 if (ret) { 280 pr_err("Failed to de-assert CPU%d reset\n", cpu); 281 goto out; 282 } 283 284 ret = meson_smp_finalize_secondary_boot(cpu); 285 if (ret) 286 goto out; 287 288 out: 289 reset_control_put(rstc); 290 291 return 0; 292 } 293 294 #ifdef CONFIG_HOTPLUG_CPU 295 static void meson8_smp_cpu_die(unsigned int cpu) 296 { 297 meson_smp_set_cpu_ctrl(cpu, false); 298 299 v7_exit_coherency_flush(louis); 300 301 scu_power_mode(scu_base, SCU_PM_POWEROFF); 302 303 dsb(); 304 wfi(); 305 306 /* we should never get here */ 307 WARN_ON(1); 308 } 309 310 static int meson8_smp_cpu_kill(unsigned int cpu) 311 { 312 int ret, power_mode; 313 unsigned long timeout; 314 315 timeout = jiffies + (50 * HZ); 316 do { 317 power_mode = scu_get_cpu_power_mode(scu_base, cpu); 318 319 if (power_mode == SCU_PM_POWEROFF) 320 break; 321 322 usleep_range(10000, 15000); 323 } while (time_before(jiffies, timeout)); 324 325 if (power_mode != SCU_PM_POWEROFF) { 326 pr_err("Error while waiting for SCU power-off on CPU%d\n", 327 cpu); 328 return -ETIMEDOUT; 329 } 330 331 msleep(30); 332 333 /* Isolation enable */ 334 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu), 335 0x3); 336 if (ret < 0) { 337 pr_err("Error when enabling isolation for CPU%d\n", cpu); 338 return ret; 339 } 340 341 udelay(10); 342 343 /* CPU power OFF */ 344 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1, 345 MESON_CPU_PWR_A9_CNTL1_M(cpu), 0x3); 346 if (ret < 0) { 347 pr_err("Couldn't change sleep status of CPU%d\n", cpu); 348 return ret; 349 } 350 351 return 1; 352 } 353 354 static int meson8b_smp_cpu_kill(unsigned int cpu) 355 { 356 int ret, power_mode, count = 5000; 357 358 do { 359 power_mode = scu_get_cpu_power_mode(scu_base, cpu); 360 361 if (power_mode == SCU_PM_POWEROFF) 362 break; 363 364 udelay(10); 365 } while (++count); 366 367 if (power_mode != SCU_PM_POWEROFF) { 368 pr_err("Error while waiting for SCU power-off on CPU%d\n", 369 cpu); 370 return -ETIMEDOUT; 371 } 372 373 udelay(10); 374 375 /* CPU power DOWN */ 376 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, 377 MESON_CPU_PWR_A9_CNTL0_M(cpu), 0x3); 378 if (ret < 0) { 379 pr_err("Couldn't power down CPU%d\n", cpu); 380 return ret; 381 } 382 383 /* Isolation enable */ 384 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu), 385 0x3); 386 if (ret < 0) { 387 pr_err("Error when enabling isolation for CPU%d\n", cpu); 388 return ret; 389 } 390 391 udelay(10); 392 393 /* Sleep status */ 394 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1, 395 MESON_CPU_PWR_A9_CNTL1_M(cpu), 0x3); 396 if (ret < 0) { 397 pr_err("Couldn't change sleep status of CPU%d\n", cpu); 398 return ret; 399 } 400 401 /* Memory power DOWN */ 402 ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_MEM_PD0, 403 MESON_CPU_PWR_A9_MEM_PD0_M(cpu), 0xf); 404 if (ret < 0) { 405 pr_err("Couldn't power down the memory of CPU%d\n", cpu); 406 return ret; 407 } 408 409 return 1; 410 } 411 #endif 412 413 static struct smp_operations meson8_smp_ops __initdata = { 414 .smp_prepare_cpus = meson8_smp_prepare_cpus, 415 .smp_boot_secondary = meson8_smp_boot_secondary, 416 #ifdef CONFIG_HOTPLUG_CPU 417 .cpu_die = meson8_smp_cpu_die, 418 .cpu_kill = meson8_smp_cpu_kill, 419 #endif 420 }; 421 422 static struct smp_operations meson8b_smp_ops __initdata = { 423 .smp_prepare_cpus = meson8b_smp_prepare_cpus, 424 .smp_boot_secondary = meson8b_smp_boot_secondary, 425 #ifdef CONFIG_HOTPLUG_CPU 426 .cpu_die = meson8_smp_cpu_die, 427 .cpu_kill = meson8b_smp_cpu_kill, 428 #endif 429 }; 430 431 CPU_METHOD_OF_DECLARE(meson8_smp, "amlogic,meson8-smp", &meson8_smp_ops); 432 CPU_METHOD_OF_DECLARE(meson8b_smp, "amlogic,meson8b-smp", &meson8b_smp_ops); 433