0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/init.h>
0016 #include <linux/device.h>
0017 #include <linux/smp.h>
0018 #include <linux/io.h>
0019 #include <linux/irqchip/arm-gic.h>
0020
0021 #include <asm/sections.h>
0022 #include <asm/smp_scu.h>
0023 #include <asm/virt.h>
0024
0025 #include "omap-secure.h"
0026 #include "omap-wakeupgen.h"
0027 #include <asm/cputype.h>
0028
0029 #include "soc.h"
0030 #include "iomap.h"
0031 #include "common.h"
0032 #include "clockdomain.h"
0033 #include "pm.h"
0034
0035 #define CPU_MASK 0xff0ffff0
0036 #define CPU_CORTEX_A9 0x410FC090
0037 #define CPU_CORTEX_A15 0x410FC0F0
0038
0039 #define OMAP5_CORE_COUNT 0x2
0040
0041 #define AUX_CORE_BOOT0_GP_RELEASE 0x020
0042 #define AUX_CORE_BOOT0_HS_RELEASE 0x200
0043
0044 struct omap_smp_config {
0045 unsigned long cpu1_rstctrl_pa;
0046 void __iomem *cpu1_rstctrl_va;
0047 void __iomem *scu_base;
0048 void __iomem *wakeupgen_base;
0049 void *startup_addr;
0050 };
0051
0052 static struct omap_smp_config cfg;
0053
0054 static const struct omap_smp_config omap443x_cfg __initconst = {
0055 .cpu1_rstctrl_pa = 0x4824380c,
0056 .startup_addr = omap4_secondary_startup,
0057 };
0058
0059 static const struct omap_smp_config omap446x_cfg __initconst = {
0060 .cpu1_rstctrl_pa = 0x4824380c,
0061 .startup_addr = omap4460_secondary_startup,
0062 };
0063
0064 static const struct omap_smp_config omap5_cfg __initconst = {
0065 .cpu1_rstctrl_pa = 0x48243810,
0066 .startup_addr = omap5_secondary_startup,
0067 };
0068
0069 void __iomem *omap4_get_scu_base(void)
0070 {
0071 return cfg.scu_base;
0072 }
0073
0074 #ifdef CONFIG_OMAP5_ERRATA_801819
0075 static void omap5_erratum_workaround_801819(void)
0076 {
0077 u32 acr, revidr;
0078 u32 acr_mask;
0079
0080
0081 asm volatile ("mrc p15, 0, %0, c0, c0, 6" : "=r" (revidr));
0082 if (revidr & (0x1 << 3))
0083 return;
0084
0085 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
0086
0087
0088
0089
0090
0091
0092 acr_mask = (0x3 << 25) | (0x3 << 27);
0093
0094 if ((acr & acr_mask) == acr_mask)
0095 return;
0096
0097 acr |= acr_mask;
0098 omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
0099
0100 pr_debug("%s: ARM erratum workaround 801819 applied on CPU%d\n",
0101 __func__, smp_processor_id());
0102 }
0103 #else
0104 static inline void omap5_erratum_workaround_801819(void) { }
0105 #endif
0106
0107 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121 static void omap5_secondary_harden_predictor(void)
0122 {
0123 u32 acr, acr_mask;
0124
0125 asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
0126
0127
0128
0129
0130 acr_mask = BIT(0);
0131
0132
0133 if ((acr & acr_mask) == acr_mask)
0134 return;
0135
0136 acr |= acr_mask;
0137 omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
0138
0139 pr_debug("%s: ARM ACR setup for CVE_2017_5715 applied on CPU%d\n",
0140 __func__, smp_processor_id());
0141 }
0142 #else
0143 static inline void omap5_secondary_harden_predictor(void) { }
0144 #endif
0145
0146 static void omap4_secondary_init(unsigned int cpu)
0147 {
0148
0149
0150
0151
0152
0153
0154
0155
0156 if (soc_is_omap443x() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
0157 omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX,
0158 4, 0, 0, 0, 0, 0);
0159
0160 if (soc_is_omap54xx() || soc_is_dra7xx()) {
0161
0162
0163
0164
0165 set_cntfreq();
0166
0167 omap5_erratum_workaround_801819();
0168
0169 omap5_secondary_harden_predictor();
0170 }
0171 }
0172
0173 static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
0174 {
0175 static struct clockdomain *cpu1_clkdm;
0176 static bool booted;
0177 static struct powerdomain *cpu1_pwrdm;
0178
0179
0180
0181
0182
0183
0184
0185 if (omap_secure_apis_support())
0186 omap_modify_auxcoreboot0(AUX_CORE_BOOT0_HS_RELEASE,
0187 0xfffffdff);
0188 else
0189 writel_relaxed(AUX_CORE_BOOT0_GP_RELEASE,
0190 cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
0191
0192 if (!cpu1_clkdm && !cpu1_pwrdm) {
0193 cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
0194 cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm");
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 if (booted && cpu1_pwrdm && cpu1_clkdm) {
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
0225 local_irq_disable();
0226 gic_dist_disable();
0227 }
0228
0229
0230
0231
0232
0233 clkdm_deny_idle_nolock(cpu1_clkdm);
0234 pwrdm_set_next_pwrst(cpu1_pwrdm, PWRDM_POWER_ON);
0235 clkdm_allow_idle_nolock(cpu1_clkdm);
0236
0237 if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
0238 while (gic_dist_disabled()) {
0239 udelay(1);
0240 cpu_relax();
0241 }
0242 gic_timer_retrigger();
0243 local_irq_enable();
0244 }
0245 } else {
0246 dsb_sev();
0247 booted = true;
0248 }
0249
0250 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0251
0252 return 0;
0253 }
0254
0255
0256
0257
0258
0259 static void __init omap4_smp_init_cpus(void)
0260 {
0261 unsigned int i = 0, ncores = 1, cpu_id;
0262
0263
0264 cpu_id = read_cpuid_id() & CPU_MASK;
0265 if (cpu_id == CPU_CORTEX_A9) {
0266
0267
0268
0269
0270 cfg.scu_base = OMAP2_L4_IO_ADDRESS(scu_a9_get_base());
0271 BUG_ON(!cfg.scu_base);
0272 ncores = scu_get_core_count(cfg.scu_base);
0273 } else if (cpu_id == CPU_CORTEX_A15) {
0274 ncores = OMAP5_CORE_COUNT;
0275 }
0276
0277
0278 if (ncores > nr_cpu_ids) {
0279 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
0280 ncores, nr_cpu_ids);
0281 ncores = nr_cpu_ids;
0282 }
0283
0284 for (i = 0; i < ncores; i++)
0285 set_cpu_possible(i, true);
0286 }
0287
0288
0289
0290
0291
0292
0293 static bool __init omap4_smp_cpu1_startup_valid(unsigned long addr)
0294 {
0295 if ((addr >= __pa(PAGE_OFFSET)) && (addr <= __pa(__bss_start)))
0296 return false;
0297
0298 return true;
0299 }
0300
0301
0302
0303
0304
0305
0306
0307 static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
0308 {
0309 unsigned long cpu1_startup_pa, cpu1_ns_pa_addr;
0310 bool needs_reset = false;
0311 u32 released;
0312
0313 if (omap_secure_apis_support())
0314 released = omap_read_auxcoreboot0() & AUX_CORE_BOOT0_HS_RELEASE;
0315 else
0316 released = readl_relaxed(cfg.wakeupgen_base +
0317 OMAP_AUX_CORE_BOOT_0) &
0318 AUX_CORE_BOOT0_GP_RELEASE;
0319 if (released) {
0320 pr_warn("smp: CPU1 not parked?\n");
0321
0322 return;
0323 }
0324
0325 cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base +
0326 OMAP_AUX_CORE_BOOT_1);
0327
0328
0329 if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa))
0330 needs_reset = true;
0331
0332
0333
0334
0335
0336 if ((soc_is_omap44xx() || soc_is_omap54xx())) {
0337 cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
0338 if (!omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
0339 needs_reset = true;
0340 } else {
0341 cpu1_ns_pa_addr = 0;
0342 }
0343
0344 if (!needs_reset || !c->cpu1_rstctrl_va)
0345 return;
0346
0347 pr_info("smp: CPU1 parked within kernel, needs reset (0x%lx 0x%lx)\n",
0348 cpu1_startup_pa, cpu1_ns_pa_addr);
0349
0350 writel_relaxed(1, c->cpu1_rstctrl_va);
0351 readl_relaxed(c->cpu1_rstctrl_va);
0352 writel_relaxed(0, c->cpu1_rstctrl_va);
0353 }
0354
0355 static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
0356 {
0357 const struct omap_smp_config *c = NULL;
0358
0359 if (soc_is_omap443x())
0360 c = &omap443x_cfg;
0361 else if (soc_is_omap446x())
0362 c = &omap446x_cfg;
0363 else if (soc_is_dra74x() || soc_is_omap54xx() || soc_is_dra76x())
0364 c = &omap5_cfg;
0365
0366 if (!c) {
0367 pr_err("%s Unknown SMP SoC?\n", __func__);
0368 return;
0369 }
0370
0371
0372 cfg.cpu1_rstctrl_pa = c->cpu1_rstctrl_pa;
0373 cfg.startup_addr = c->startup_addr;
0374 cfg.wakeupgen_base = omap_get_wakeupgen_base();
0375
0376 if (soc_is_dra74x() || soc_is_omap54xx() || soc_is_dra76x()) {
0377 if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
0378 cfg.startup_addr = omap5_secondary_hyp_startup;
0379 omap5_erratum_workaround_801819();
0380 }
0381
0382 cfg.cpu1_rstctrl_va = ioremap(cfg.cpu1_rstctrl_pa, 4);
0383 if (!cfg.cpu1_rstctrl_va)
0384 return;
0385
0386
0387
0388
0389
0390 if (cfg.scu_base)
0391 scu_enable(cfg.scu_base);
0392
0393 omap4_smp_maybe_reset_cpu1(&cfg);
0394
0395
0396
0397
0398
0399
0400
0401 if (omap_secure_apis_support())
0402 omap_auxcoreboot_addr(__pa_symbol(cfg.startup_addr));
0403 else
0404 writel_relaxed(__pa_symbol(cfg.startup_addr),
0405 cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_1);
0406 }
0407
0408 const struct smp_operations omap4_smp_ops __initconst = {
0409 .smp_init_cpus = omap4_smp_init_cpus,
0410 .smp_prepare_cpus = omap4_smp_prepare_cpus,
0411 .smp_secondary_init = omap4_secondary_init,
0412 .smp_boot_secondary = omap4_boot_secondary,
0413 #ifdef CONFIG_HOTPLUG_CPU
0414 .cpu_die = omap4_cpu_die,
0415 .cpu_kill = omap4_cpu_kill,
0416 #endif
0417 };