Skip to content

Commit 4648b63

Browse files
Andy Rossnashif
authored andcommitted
soc/intel_adsp: Add support for legacy IDC driver for pre-2.5 hardware
The IDC driver was written for Tiger Lake era devices, but works fine on the earlier hardware too. Make it selectable; if you don't configure IPM_CAVS_IDC, then you get the new driver. Signed-off-by: Andy Ross <[email protected]>
1 parent c6de46c commit 4648b63

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

soc/xtensa/intel_adsp/common/soc_mp.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4547
struct 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

Comments
 (0)