staticvoid meson_smp_begin_secondary_boot(unsignedint cpu)
{ /* * Set the entry point before powering on the CPU through the SCU. This * is needed if the CPU is in "warm" state (= after rebooting the * system without power-cycling, or when taking the CPU offline and * then taking it online again.
*/
writel(__pa_symbol(secondary_startup),
sram_base + MESON_SMP_SRAM_CPU_CTRL_ADDR_REG(cpu));
/* * SCU Power on CPU (needs to be done before starting the CPU, * otherwise the secondary CPU will not start).
*/
scu_cpu_power_enable(scu_base, cpu);
}
rstc = meson_smp_get_core_reset(cpu); if (IS_ERR(rstc)) {
pr_err("Couldn't get the reset controller for CPU%d\n", cpu); return PTR_ERR(rstc);
}
meson_smp_begin_secondary_boot(cpu);
/* Reset enable */
ret = reset_control_assert(rstc); if (ret) {
pr_err("Failed to assert CPU%d reset\n", cpu); goto out;
}
/* CPU power ON */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1,
MESON_CPU_PWR_A9_CNTL1_M(cpu), 0); if (ret < 0) {
pr_err("Couldn't wake up CPU%d\n", cpu); goto out;
}
udelay(10);
/* Isolation disable */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu),
0); if (ret < 0) {
pr_err("Error when disabling isolation of CPU%d\n", cpu); goto out;
}
/* Reset disable */
ret = reset_control_deassert(rstc); if (ret) {
pr_err("Failed to de-assert CPU%d reset\n", cpu); goto out;
}
ret = meson_smp_finalize_secondary_boot(cpu); if (ret) goto out;
rstc = meson_smp_get_core_reset(cpu); if (IS_ERR(rstc)) {
pr_err("Couldn't get the reset controller for CPU%d\n", cpu); return PTR_ERR(rstc);
}
meson_smp_begin_secondary_boot(cpu);
/* CPU power UP */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0,
MESON_CPU_PWR_A9_CNTL0_M(cpu), 0); if (ret < 0) {
pr_err("Couldn't power up CPU%d\n", cpu); goto out;
}
udelay(5);
/* Reset enable */
ret = reset_control_assert(rstc); if (ret) {
pr_err("Failed to assert CPU%d reset\n", cpu); goto out;
}
/* Memory power UP */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_MEM_PD0,
MESON_CPU_PWR_A9_MEM_PD0_M(cpu), 0); if (ret < 0) {
pr_err("Couldn't power up the memory for CPU%d\n", cpu); goto out;
}
/* Wake up CPU */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1,
MESON_CPU_PWR_A9_CNTL1_M(cpu), 0); if (ret < 0) {
pr_err("Couldn't wake up CPU%d\n", cpu); goto out;
}
udelay(10);
ret = regmap_read_poll_timeout(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1, val,
val & MESON_CPU_PWR_A9_CNTL1_ST(cpu),
10, 10000); if (ret) {
pr_err("Timeout while polling PMU for CPU%d status\n", cpu); goto out;
}
/* Isolation disable */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu),
0); if (ret < 0) {
pr_err("Error when disabling isolation of CPU%d\n", cpu); goto out;
}
/* Reset disable */
ret = reset_control_deassert(rstc); if (ret) {
pr_err("Failed to de-assert CPU%d reset\n", cpu); goto out;
}
ret = meson_smp_finalize_secondary_boot(cpu); if (ret) goto out;
usleep_range(10000, 15000);
} while (time_before(jiffies, timeout));
if (power_mode != SCU_PM_POWEROFF) {
pr_err("Error while waiting for SCU power-off on CPU%d\n",
cpu); return -ETIMEDOUT;
}
msleep(30);
/* Isolation enable */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu),
0x3); if (ret < 0) {
pr_err("Error when enabling isolation for CPU%d\n", cpu); return ret;
}
udelay(10);
/* CPU power OFF */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1,
MESON_CPU_PWR_A9_CNTL1_M(cpu), 0x3); if (ret < 0) {
pr_err("Couldn't change sleep status of CPU%d\n", cpu); return ret;
}
return 1;
}
staticint meson8b_smp_cpu_kill(unsignedint cpu)
{ int ret, power_mode, count = 5000;
do {
power_mode = scu_get_cpu_power_mode(scu_base, cpu);
if (power_mode == SCU_PM_POWEROFF) break;
udelay(10);
} while (++count);
if (power_mode != SCU_PM_POWEROFF) {
pr_err("Error while waiting for SCU power-off on CPU%d\n",
cpu); return -ETIMEDOUT;
}
udelay(10);
/* CPU power DOWN */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0,
MESON_CPU_PWR_A9_CNTL0_M(cpu), 0x3); if (ret < 0) {
pr_err("Couldn't power down CPU%d\n", cpu); return ret;
}
/* Isolation enable */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL0, BIT(cpu),
0x3); if (ret < 0) {
pr_err("Error when enabling isolation for CPU%d\n", cpu); return ret;
}
udelay(10);
/* Sleep status */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_CNTL1,
MESON_CPU_PWR_A9_CNTL1_M(cpu), 0x3); if (ret < 0) {
pr_err("Couldn't change sleep status of CPU%d\n", cpu); return ret;
}
/* Memory power DOWN */
ret = regmap_update_bits(pmu, MESON_CPU_AO_RTI_PWR_A9_MEM_PD0,
MESON_CPU_PWR_A9_MEM_PD0_M(cpu), 0xf); if (ret < 0) {
pr_err("Couldn't power down the memory of CPU%d\n", cpu); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.