2121#include <linux/io.h>
2222#include <linux/irqchip/arm-gic.h>
2323
24+ #include <asm/sections.h>
2425#include <asm/smp_scu.h>
2526#include <asm/virt.h>
2627
4041
4142#define OMAP5_CORE_COUNT 0x2
4243
44+ #define AUX_CORE_BOOT0_GP_RELEASE 0x020
45+ #define AUX_CORE_BOOT0_HS_RELEASE 0x200
46+
4347struct omap_smp_config {
4448 unsigned long cpu1_rstctrl_pa ;
4549 void __iomem * cpu1_rstctrl_va ;
4650 void __iomem * scu_base ;
51+ void __iomem * wakeupgen_base ;
4752 void * startup_addr ;
4853};
4954
@@ -140,7 +145,6 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
140145 static struct clockdomain * cpu1_clkdm ;
141146 static bool booted ;
142147 static struct powerdomain * cpu1_pwrdm ;
143- void __iomem * base = omap_get_wakeupgen_base ();
144148
145149 /*
146150 * Set synchronisation state between this boot processor
@@ -155,9 +159,11 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
155159 * A barrier is added to ensure that write buffer is drained
156160 */
157161 if (omap_secure_apis_support ())
158- omap_modify_auxcoreboot0 (0x200 , 0xfffffdff );
162+ omap_modify_auxcoreboot0 (AUX_CORE_BOOT0_HS_RELEASE ,
163+ 0xfffffdff );
159164 else
160- writel_relaxed (0x20 , base + OMAP_AUX_CORE_BOOT_0 );
165+ writel_relaxed (AUX_CORE_BOOT0_GP_RELEASE ,
166+ cfg .wakeupgen_base + OMAP_AUX_CORE_BOOT_0 );
161167
162168 if (!cpu1_clkdm && !cpu1_pwrdm ) {
163169 cpu1_clkdm = clkdm_lookup ("mpu1_clkdm" );
@@ -261,9 +267,72 @@ static void __init omap4_smp_init_cpus(void)
261267 set_cpu_possible (i , true);
262268}
263269
270+ /*
271+ * For now, just make sure the start-up address is not within the booting
272+ * kernel space as that means we just overwrote whatever secondary_startup()
273+ * code there was.
274+ */
275+ static bool __init omap4_smp_cpu1_startup_valid (unsigned long addr )
276+ {
277+ if ((addr >= __pa (PAGE_OFFSET )) && (addr <= __pa (__bss_start )))
278+ return false;
279+
280+ return true;
281+ }
282+
283+ /*
284+ * We may need to reset CPU1 before configuring, otherwise kexec boot can end
285+ * up trying to use old kernel startup address or suspend-resume will
286+ * occasionally fail to bring up CPU1 on 4430 if CPU1 fails to enter deeper
287+ * idle states.
288+ */
289+ static void __init omap4_smp_maybe_reset_cpu1 (struct omap_smp_config * c )
290+ {
291+ unsigned long cpu1_startup_pa , cpu1_ns_pa_addr ;
292+ bool needs_reset = false;
293+ u32 released ;
294+
295+ if (omap_secure_apis_support ())
296+ released = omap_read_auxcoreboot0 () & AUX_CORE_BOOT0_HS_RELEASE ;
297+ else
298+ released = readl_relaxed (cfg .wakeupgen_base +
299+ OMAP_AUX_CORE_BOOT_0 ) &
300+ AUX_CORE_BOOT0_GP_RELEASE ;
301+ if (released ) {
302+ pr_warn ("smp: CPU1 not parked?\n" );
303+
304+ return ;
305+ }
306+
307+ cpu1_startup_pa = readl_relaxed (cfg .wakeupgen_base +
308+ OMAP_AUX_CORE_BOOT_1 );
309+ cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr ();
310+
311+ /* Did the configured secondary_startup() get overwritten? */
312+ if (!omap4_smp_cpu1_startup_valid (cpu1_startup_pa ))
313+ needs_reset = true;
314+
315+ /*
316+ * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a
317+ * deeper idle state in WFI and will wake to an invalid address.
318+ */
319+ if ((soc_is_omap44xx () || soc_is_omap54xx ()) &&
320+ !omap4_smp_cpu1_startup_valid (cpu1_ns_pa_addr ))
321+ needs_reset = true;
322+
323+ if (!needs_reset || !c -> cpu1_rstctrl_va )
324+ return ;
325+
326+ pr_info ("smp: CPU1 parked within kernel, needs reset (0x%lx 0x%lx)\n" ,
327+ cpu1_startup_pa , cpu1_ns_pa_addr );
328+
329+ writel_relaxed (1 , c -> cpu1_rstctrl_va );
330+ readl_relaxed (c -> cpu1_rstctrl_va );
331+ writel_relaxed (0 , c -> cpu1_rstctrl_va );
332+ }
333+
264334static void __init omap4_smp_prepare_cpus (unsigned int max_cpus )
265335{
266- void __iomem * base = omap_get_wakeupgen_base ();
267336 const struct omap_smp_config * c = NULL ;
268337
269338 if (soc_is_omap443x ())
@@ -281,6 +350,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
281350 /* Must preserve cfg.scu_base set earlier */
282351 cfg .cpu1_rstctrl_pa = c -> cpu1_rstctrl_pa ;
283352 cfg .startup_addr = c -> startup_addr ;
353+ cfg .wakeupgen_base = omap_get_wakeupgen_base ();
284354
285355 if (soc_is_dra74x () || soc_is_omap54xx ()) {
286356 if ((__boot_cpu_mode & MODE_MASK ) == HYP_MODE )
@@ -299,15 +369,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
299369 if (cfg .scu_base )
300370 scu_enable (cfg .scu_base );
301371
302- /*
303- * Reset CPU1 before configuring, otherwise kexec will
304- * end up trying to use old kernel startup address.
305- */
306- if (cfg .cpu1_rstctrl_va ) {
307- writel_relaxed (1 , cfg .cpu1_rstctrl_va );
308- readl_relaxed (cfg .cpu1_rstctrl_va );
309- writel_relaxed (0 , cfg .cpu1_rstctrl_va );
310- }
372+ omap4_smp_maybe_reset_cpu1 (& cfg );
311373
312374 /*
313375 * Write the address of secondary startup routine into the
@@ -319,7 +381,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
319381 omap_auxcoreboot_addr (__pa_symbol (cfg .startup_addr ));
320382 else
321383 writel_relaxed (__pa_symbol (cfg .startup_addr ),
322- base + OMAP_AUX_CORE_BOOT_1 );
384+ cfg . wakeupgen_base + OMAP_AUX_CORE_BOOT_1 );
323385}
324386
325387const struct smp_operations omap4_smp_ops __initconst = {
0 commit comments