@@ -42,6 +42,8 @@ extern void z_reinit_idle_thread(int i);
4242 (0x1 << 24 ) | /* "ROM control version" = 1 */ \
4343 (0x2 << 0 )) /* "Core wake version" = 2 */
4444
45+ #define IDC_ALL_CORES (BIT(CONFIG_MP_NUM_CPUS) - 1)
46+
4547struct cpustart_rec {
4648 uint32_t cpu ;
4749 arch_cpustart_t fn ;
@@ -224,8 +226,29 @@ void z_mp_entry(void)
224226 /* Interrupt must be enabled while running on current core */
225227 irq_enable (DT_IRQN (DT_INST (0 , intel_cavs_idc )));
226228
227- #if defined(CONFIG_SMP_BOOT_DELAY ) && defined(CONFIG_IPM_CAVS_IDC )
228- cavs_idc_smp_init (NULL );
229+ #ifdef CONFIG_IPM_CAVS_IDC
230+ if (IS_ENABLED (CONFIG_SMP_BOOT_DELAY )) {
231+ cavs_idc_smp_init (NULL );
232+ }
233+ #else
234+ /* Unfortunately the interrupt controller doesn't understand
235+ * that each CPU has its own mask register (the timer has a
236+ * similar hook). Needed only on hardware with ROMs that
237+ * disable this; cAVS 2.5 starts with an unmasked hardware
238+ * default.
239+ */
240+ if (!IS_ENABLED (CONFIG_SOC_SERIES_INTEL_CAVS_V25 )) {
241+ CAVS_INTCTRL [start_rec .cpu ].l2 .clear = CAVS_L2_IDC ;
242+ }
243+
244+ /* Unmask IDC interrupts from this core to all others. A
245+ * delay is needed following the write on older hardware, or
246+ * else the modification gets lost. Voodoo.
247+ */
248+ if (IS_ENABLED (CONFIG_SOC_SERIES_INTEL_CAVS_V15 )) {
249+ k_busy_wait (10 );
250+ }
251+ IDC [start_rec .cpu ].busy_int = IDC_ALL_CORES ;
229252#endif
230253
231254 cpus_active [start_rec .cpu ] = true;
@@ -323,9 +346,11 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
323346 /* Early DSPs have a ROM that actually receives the startup
324347 * IDC as an interrupt, and we don't want that to be confused
325348 * by IPIs sent by the OS elsewhere. Mask the IDC interrupt
326- * on other core so IPI won't cause them to jump to ISR until
327- * the core is fully initialized.
349+ * on the new core so Zephyr IPIs from existing cores won't
350+ * cause it to jump to ISR until the core is fully
351+ * initialized. Wait for the startup IDC to arrive though.
328352 */
353+ # ifdef CONFIG_IPM_CAVS_IDC
329354 uint32_t idc_reg = idc_read (IPC_IDCCTL , cpu_num );
330355
331356 idc_reg &= ~IPC_IDCCTL_IDCTBIE (0 );
@@ -335,9 +360,13 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
335360
336361 k_busy_wait (100 );
337362
338- #ifdef CONFIG_SMP_BOOT_DELAY
339- cavs_idc_smp_init (NULL );
340- #endif
363+ if (IS_ENABLED (CONFIG_SMP_BOOT_DELAY )) {
364+ cavs_idc_smp_init (NULL );
365+ }
366+ # else
367+ IDC [cpu_num ].busy_int &= ~IDC_ALL_CORES ;
368+ k_busy_wait (100 );
369+ # endif
341370#endif
342371}
343372
@@ -403,16 +432,13 @@ void soc_idc_init(void)
403432 * target core clears the busy bit.
404433 */
405434 for (int core = 0 ; core < CONFIG_MP_NUM_CPUS ; core ++ ) {
406- uint32_t coremask = BIT (CONFIG_MP_NUM_CPUS ) - 1 ;
407-
408- IDC [core ].busy_int |= coremask ;
409- IDC [core ].done_int &= ~coremask ;
435+ IDC [core ].busy_int |= IDC_ALL_CORES ;
436+ IDC [core ].done_int &= ~IDC_ALL_CORES ;
410437
411438 /* Also unmask the IDC interrupt for every core in the
412439 * L2 mask register.
413440 */
414441 CAVS_INTCTRL [core ].l2 .clear = CAVS_L2_IDC ;
415-
416442 }
417443
418444 /* Clear out any existing pending interrupts that might be present */
0 commit comments