Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * OMAP4 SMP source file. It contains platform specific functions
0004  * needed for the linux smp kernel.
0005  *
0006  * Copyright (C) 2009 Texas Instruments, Inc.
0007  *
0008  * Author:
0009  *      Santosh Shilimkar <santosh.shilimkar@ti.com>
0010  *
0011  * Platform file needed for the OMAP4 SMP. This file is based on arm
0012  * realview smp platform.
0013  * * Copyright (c) 2002 ARM Limited.
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     /* REVIDR[3] indicates erratum fix available on silicon */
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      * BIT(27) - Disables streaming. All write-allocate lines allocate in
0088      * the L1 or L2 cache.
0089      * BIT(25) - Disables streaming. All write-allocate lines allocate in
0090      * the L1 cache.
0091      */
0092     acr_mask = (0x3 << 25) | (0x3 << 27);
0093     /* do we already have it done.. if yes, skip expensive smc */
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  * Configure ACR and enable ACTLR[0] (Enable invalidates of BTB with
0110  * ICIALLU) to activate the workaround for secondary Core.
0111  * NOTE: it is assumed that the primary core's configuration is done
0112  * by the boot loader (kernel will detect a misconfiguration and complain
0113  * if this is not done).
0114  *
0115  * In General Purpose(GP) devices, ACR bit settings can only be done
0116  * by ROM code in "secure world" using the smc call and there is no
0117  * option to update the "firmware" on such devices. This also works for
0118  * High security(HS) devices, as a backup option in case the
0119  * "update" is not done in the "security firmware".
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      * ACTLR[0] (Enable invalidates of BTB with ICIALLU)
0129      */
0130     acr_mask = BIT(0);
0131 
0132     /* Do we already have it done.. if yes, skip expensive smc */
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      * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
0150      * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
0151      * init and for CPU1, a secure PPA API provided. CPU0 must be ON
0152      * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
0153      * OMAP443X GP devices- SMP bit isn't accessible.
0154      * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
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          * Configure the CNTFRQ register for the secondary cpu's which
0163          * indicates the frequency of the cpu local timers.
0164          */
0165         set_cntfreq();
0166         /* Configure ACR to disable streaming WA for 801819 */
0167         omap5_erratum_workaround_801819();
0168         /* Enable ACR to allow for ICUALLU workaround */
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      * Update the AuxCoreBoot0 with boot state for secondary core.
0181      * omap4_secondary_startup() routine will hold the secondary core till
0182      * the AuxCoreBoot1 register is updated with cpu state
0183      * A barrier is added to ensure that write buffer is drained
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      * The SGI(Software Generated Interrupts) are not wakeup capable
0199      * from low power states. This is known limitation on OMAP4 and
0200      * needs to be worked around by using software forced clockdomain
0201      * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
0202      * software force wakeup. The clockdomain is then put back to
0203      * hardware supervised mode.
0204      * More details can be found in OMAP4430 TRM - Version J
0205      * Section :
0206      *  4.3.4.2 Power States of CPU0 and CPU1
0207      */
0208     if (booted && cpu1_pwrdm && cpu1_clkdm) {
0209         /*
0210          * GIC distributor control register has changed between
0211          * CortexA9 r1pX and r2pX. The Control Register secure
0212          * banked version is now composed of 2 bits:
0213          * bit 0 == Secure Enable
0214          * bit 1 == Non-Secure Enable
0215          * The Non-Secure banked register has not changed
0216          * Because the ROM Code is based on the r1pX GIC, the CPU1
0217          * GIC restoration will cause a problem to CPU0 Non-Secure SW.
0218          * The workaround must be:
0219          * 1) Before doing the CPU1 wakeup, CPU0 must disable
0220          * the GIC distributor
0221          * 2) CPU1 must re-enable the GIC distributor on
0222          * it's wakeup path.
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          * Ensure that CPU power state is set to ON to avoid CPU
0231          * powerdomain transition on wfi
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  * Initialise the CPU possible map early - this describes the CPUs
0257  * which may be present or become present in the system.
0258  */
0259 static void __init omap4_smp_init_cpus(void)
0260 {
0261     unsigned int i = 0, ncores = 1, cpu_id;
0262 
0263     /* Use ARM cpuid check here, as SoC detection will not work so early */
0264     cpu_id = read_cpuid_id() & CPU_MASK;
0265     if (cpu_id == CPU_CORTEX_A9) {
0266         /*
0267          * Currently we can't call ioremap here because
0268          * SoC detection won't work until after init_early.
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     /* sanity check */
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  * For now, just make sure the start-up address is not within the booting
0290  * kernel space as that means we just overwrote whatever secondary_startup()
0291  * code there was.
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  * We may need to reset CPU1 before configuring, otherwise kexec boot can end
0303  * up trying to use old kernel startup address or suspend-resume will
0304  * occasionally fail to bring up CPU1 on 4430 if CPU1 fails to enter deeper
0305  * idle states.
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     /* Did the configured secondary_startup() get overwritten? */
0329     if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa))
0330         needs_reset = true;
0331 
0332     /*
0333      * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a
0334      * deeper idle state in WFI and will wake to an invalid address.
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     /* Must preserve cfg.scu_base set earlier */
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      * Initialise the SCU and wake up the secondary core using
0388      * wakeup_secondary().
0389      */
0390     if (cfg.scu_base)
0391         scu_enable(cfg.scu_base);
0392 
0393     omap4_smp_maybe_reset_cpu1(&cfg);
0394 
0395     /*
0396      * Write the address of secondary startup routine into the
0397      * AuxCoreBoot1 where ROM code will jump and start executing
0398      * on secondary core once out of WFE
0399      * A barrier is added to ensure that write buffer is drained
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 };