static void tbase_triggerSgiDump(void) { uint64_t mpidr = read_mpidr(); uint32_t linear_id = platform_get_core_pos(mpidr); uint32_t SGITargets; /* Configure SGI */ gicd_clr_igroupr(get_plat_config()->gicd_base, FIQ_SMP_CALL_SGI); gicd_set_ipriorityr(get_plat_config()->gicd_base, FIQ_SMP_CALL_SGI, GIC_HIGHEST_SEC_PRIORITY); /* Enable SGI */ gicd_set_isenabler(get_plat_config()->gicd_base, FIQ_SMP_CALL_SGI); /* Send SGIs to all cores except the current one (current will directly branch to the dump handler) */ SGITargets = 0xFF; SGITargets &= ~(1 << linear_id); /* Trigger SGI */ irq_raise_softirq(SGITargets, FIQ_SMP_CALL_SGI); /* Current core directly branches to dump handler */ plat_tbase_dump(); }
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; static int is_first_boot = 1; printk(KERN_CRIT "Boot slave CPU\n"); /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); HOTPLUG_INFO("boot_secondary, cpu: %d\n", cpu); /* * The secondary processor is waiting to be released from * the holding pen - release it, then wait for it to flag * that it has been released by resetting pen_release. * * Note that "pen_release" is the hardware CPU ID, whereas * "cpu" is Linux's internal ID. */ pen_release = cpu; __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); if (is_first_boot) { mt65xx_reg_sync_writel(SLAVE_MAGIC_NUM, SLAVE_MAGIC_REG); is_first_boot = 0; } else { mt65xx_reg_sync_writel(virt_to_phys(mt_secondary_startup), BOOTROM_BOOT_ADDR); } power_on_cpu1(); irq_raise_softirq(cpumask_of(cpu), IPI_CPU_START); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { smp_rmb(); if (pen_release == -1) break; udelay(10); } /* * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; }