static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) { int ret = 0; if (!per_cpu(cold_boot_done, cpu)) { ret = func(cpu); if (!ret) per_cpu(cold_boot_done, cpu) = true; } /* * set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); /* * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return ret; }
static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, struct task_struct *idle) { int ret, hw_cpu; pr_info("Booting CPU %d\n", cpu); /* * Write the address of secondary startup into the system-wide * flags register. The boot monitor waits until it receives a * soft interrupt, and then the secondary CPU branches to this * address. */ hw_cpu = cpu_logical_map(cpu); if (of_machine_is_compatible("marvell,armada375")) mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup); else mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup); smp_wmb(); /* * Doing this before deasserting the CPUs is needed to wake up CPUs * in the offline state after using CPU hotplug. */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ret = mvebu_cpu_reset_deassert(hw_cpu); if (ret) { pr_err("Could not start the secondary CPU: %d\n", ret); return ret; } return 0; }
static int hi3xxx_boot_secondary(unsigned int cpu, struct task_struct *idle) { hi3xxx_set_cpu(cpu, true); hi3xxx_set_cpu_jump(cpu, secondary_startup); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; }
static int __cpuinit release_from_pen(unsigned int cpu) { unsigned long timeout; preset_lpj = loops_per_jiffy; spin_lock(&boot_lock); write_pen_release(cpu_logical_map(cpu)); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { smp_rmb(); if (pen_release == -1) break; udelay(10); } spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; }
static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; /* * set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * 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. */ write_pen_release(cpu_logical_map(cpu)); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { if (pen_release == -1) break; } /* * 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; }
static int secondary_pen_release(unsigned int cpu) { unsigned long timeout; /* * Set synchronisation state between this boot processor * and the secondary one */ raw_spin_lock(&boot_lock); write_pen_release(cpu_logical_map(cpu)); /* * Wake-up cpu with am IPI */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { if (secondary_holding_pen_release == INVALID_HWID) break; udelay(10); } raw_spin_unlock(&boot_lock); return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0; }
static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) { phys_addr_t jumpaddr; jumpaddr = __pa_symbol(secondary_startup); hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); hix5hd2_set_cpu(cpu, true); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; }
static int __cpuinit msm_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; static int cold_boot_done; /* Only need to bring cpu out of reset this way once */ if (cold_boot_done == false) { prepare_cold_cpu(cpu); cold_boot_done = true; } /* * set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * 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_logical_map(cpu); __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 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; }
static int acpi_parking_protocol_cpu_boot(unsigned int cpu) { struct cpu_mailbox_entry *cpu_entry = &cpu_mailbox_entries[cpu]; struct parking_protocol_mailbox __iomem *mailbox; __le32 cpu_id; /* * Map mailbox memory with attribute device nGnRE (ie ioremap - * this deviates from the parking protocol specifications since * the mailboxes are required to be mapped nGnRnE; the attribute * discrepancy is harmless insofar as the protocol specification * is concerned). * If the mailbox is mistakenly allocated in the linear mapping * by FW ioremap will fail since the mapping will be prevented * by the kernel (it clashes with the linear mapping attributes * specifications). */ mailbox = ioremap(cpu_entry->mailbox_addr, sizeof(*mailbox)); if (!mailbox) return -EIO; cpu_id = readl_relaxed(&mailbox->cpu_id); /* * Check if firmware has set-up the mailbox entry properly * before kickstarting the respective cpu. */ if (cpu_id != ~0U) { iounmap(mailbox); return -ENXIO; } /* * stash the mailbox address mapping to use it for further FW * checks in the postboot method */ cpu_entry->mailbox = mailbox; /* * We write the entry point and cpu id as LE regardless of the * native endianness of the kernel. Therefore, any boot-loaders * that read this address need to convert this address to the * Boot-Loader's endianness before jumping. */ writeq_relaxed(__pa(secondary_entry), &mailbox->entry_point); writel_relaxed(cpu_entry->gic_cpu_id, &mailbox->cpu_id); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; }
static int __cpuinit release_from_pen(unsigned int cpu) { unsigned long timeout; /* Set preset_lpj to avoid subsequent lpj recalculations */ preset_lpj = loops_per_jiffy; /* * set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * 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. */ write_pen_release(cpu_logical_map(cpu)); /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 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; }
static int mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned int pcpu, pcluster, ret; extern void secondary_startup(void); cpu_to_pcpu(cpu, &pcpu, &pcluster); pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n", __func__, cpu, pcpu, pcluster); mcpm_set_entry_vector(pcpu, pcluster, NULL); ret = mcpm_cpu_power_up(pcpu, pcluster); if (ret) return ret; mcpm_set_entry_vector(pcpu, pcluster, secondary_startup); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); dsb_sev(); return 0; }
int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; /* * set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * 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. */ write_pen_release(cpu_logical_map(cpu)); /* * Send the secondary CPU a soft interrupt, thereby causing * it to jump to the secondary entrypoint. */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 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; }
int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * This is really belt and braces; we hold unintended secondary * CPUs in the holding pen until we're ready for them. However, * since we haven't sent them a soft interrupt, they shouldn't * be there. */ write_pen_release(cpu_logical_map(cpu)); /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 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; }
static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned int mpidr, pcpu, pcluster, ret; extern void secondary_startup(void); mpidr = cpu_logical_map(cpu); pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n", __func__, cpu, pcpu, pcluster); mcpm_set_entry_vector(pcpu, pcluster, NULL); ret = mcpm_cpu_power_up(pcpu, pcluster); if (ret) return ret; mcpm_set_entry_vector(pcpu, pcluster, secondary_startup); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); dsb_sev(); return 0; }
static int set_enable_mask(const char *val, const struct kernel_param *kp) { int rv = param_set_uint(val, kp); unsigned long flags; pr_info("%s: val=%s, enable_maks=%d\n", __func__, val, enable_mask); if (rv) return rv; spin_lock_irqsave(&enable_mask_lock, flags); if (!(enable_mask & ENABLE_C2)) { unsigned int cpuid = smp_processor_id(); int i; for_each_online_cpu(i) { if (i == cpuid) continue; arch_send_wakeup_ipi_mask(cpumask_of(i)); } }
static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) { static struct clockdomain *cpu1_clkdm; static bool booted; static struct powerdomain *cpu1_pwrdm; void __iomem *base = omap_get_wakeupgen_base(); /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * Update the AuxCoreBoot0 with boot state for secondary core. * omap4_secondary_startup() routine will hold the secondary core till * the AuxCoreBoot1 register is updated with cpu state * A barrier is added to ensure that write buffer is drained */ if (omap_secure_apis_support()) omap_modify_auxcoreboot0(0x200, 0xfffffdff); else __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0); if (!cpu1_clkdm && !cpu1_pwrdm) { cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm"); } /* * The SGI(Software Generated Interrupts) are not wakeup capable * from low power states. This is known limitation on OMAP4 and * needs to be worked around by using software forced clockdomain * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to * software force wakeup. The clockdomain is then put back to * hardware supervised mode. * More details can be found in OMAP4430 TRM - Version J * Section : * 4.3.4.2 Power States of CPU0 and CPU1 */ if (booted && cpu1_pwrdm && cpu1_clkdm) { /* * GIC distributor control register has changed between * CortexA9 r1pX and r2pX. The Control Register secure * banked version is now composed of 2 bits: * bit 0 == Secure Enable * bit 1 == Non-Secure Enable * The Non-Secure banked register has not changed * Because the ROM Code is based on the r1pX GIC, the CPU1 * GIC restoration will cause a problem to CPU0 Non-Secure SW. * The workaround must be: * 1) Before doing the CPU1 wakeup, CPU0 must disable * the GIC distributor * 2) CPU1 must re-enable the GIC distributor on * it's wakeup path. */ if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { local_irq_disable(); gic_dist_disable(); } /* * Ensure that CPU power state is set to ON to avoid CPU * powerdomain transition on wfi */ clkdm_wakeup(cpu1_clkdm); omap_set_pwrdm_state(cpu1_pwrdm, PWRDM_POWER_ON); clkdm_allow_idle(cpu1_clkdm); if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { while (gic_dist_disabled()) { udelay(1); cpu_relax(); } gic_timer_retrigger(); local_irq_enable(); } } else { dsb_sev(); booted = true; } arch_send_wakeup_ipi_mask(cpumask_of(cpu)); /* * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ spin_unlock(&boot_lock); return 0; }
static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) { arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu))); return 0; }
static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; u32 mpidr = cpu_logical_map(cpu); u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); int ret = -ENOSYS; /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * 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 core ID, whereas * "cpu" is Linux's internal ID. */ write_pen_release(core_id); if (!soc_is_exynos5440() && !exynos_cpu_power_state(core_id)) { exynos_cpu_power_up(core_id); timeout = 10; /* wait max 10 ms until cpu1 is on */ while (exynos_cpu_power_state(core_id) != S5P_CORE_LOCAL_PWR_EN) { if (timeout-- == 0) break; mdelay(1); } if (timeout == 0) { printk(KERN_ERR "cpu1 power enable failed"); spin_unlock(&boot_lock); return -ETIMEDOUT; } } /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { unsigned long boot_addr; smp_rmb(); boot_addr = virt_to_phys(exynos4_secondary_startup); /* * Try to set boot address using firmware first * and fall back to boot register if it fails. */ ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr); if (ret && ret != -ENOSYS) goto fail; if (ret == -ENOSYS) { void __iomem *boot_reg = cpu_boot_reg(core_id); if (IS_ERR(boot_reg)) { ret = PTR_ERR(boot_reg); goto fail; } __raw_writel(boot_addr, cpu_boot_reg(core_id)); } call_firmware_op(cpu_boot, core_id); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 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 */ fail: spin_unlock(&boot_lock); return pen_release != -1 ? ret : 0; }
static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; unsigned long phys_cpu = cpu_logical_map(cpu); /* * Set synchronisation state between this boot processor * and the secondary one */ spin_lock(&boot_lock); /* * 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. */ write_pen_release(phys_cpu); if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { __raw_writel(S5P_CORE_LOCAL_PWR_EN, S5P_ARM_CORE1_CONFIGURATION); timeout = 10; /* wait max 10 ms until cpu1 is on */ while ((__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) { if (timeout-- == 0) break; mdelay(1); } if (timeout == 0) { printk(KERN_ERR "cpu1 power enable failed"); spin_unlock(&boot_lock); return -ETIMEDOUT; } } /* * Send the secondary CPU a soft interrupt, thereby causing * the boot monitor to read the system wide flags register, * and branch to the address found there. */ timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { unsigned long boot_addr; smp_rmb(); boot_addr = virt_to_phys(exynos4_secondary_startup); /* * Try to set boot address using firmware first * and fall back to boot register if it fails. */ if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr)) __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); call_firmware_op(cpu_boot, phys_cpu); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 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; }
static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle) { wakeup_secondary(); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); return 0; }