// SPDX-License-Identifier: GPL-2.0-only /* * Created by: Nicolas Pitre, October 2012 * Copyright: (C) 2012-2013 Linaro Limited * * Some portions of this file were originally written by Achin Gupta * Copyright: (C) 2012 ARM Limited
*/
staticvoid tc2_pm_cpu_powerdown_prepare(unsignedint cpu, unsignedint cluster)
{
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
ve_spc_cpu_wakeup_irq(cluster, cpu, true); /* * If the CPU is committed to power down, make sure * the power controller will be in charge of waking it * up upon IRQ, ie IRQ lines are cut from GIC CPU IF * to the CPU by disabling the GIC CPU IF to prevent wfi * from completing execution behind power controller back
*/
gic_cpu_if_down(0);
}
/* * We need the CPU to reach WFI, but the power * controller may put the cluster in reset and * power it off as soon as that happens, before * we have a chance to see STANDBYWFI. * * So we need to check for both conditions:
*/ if (tc2_core_in_reset(cpu, cluster) ||
ve_spc_cpu_in_wfi(cpu, cluster)) return 0; /* success: the CPU is halted */
/* Otherwise, wait and retry: */
msleep(POLL_MSEC);
}
/* * The power management-related features are hidden behind * SCC registers. We need to extract runtime information like * cluster ids and number of CPUs really available in clusters.
*/
np = of_find_compatible_node(NULL, NULL, "arm,vexpress-scc,v2p-ca15_a7");
scc = of_iomap(np, 0); if (!scc) return -ENODEV;
/* * A subset of the SCC registers is also used to communicate * with the SPC (power controller). We need to be able to * drive it very early in the boot process to power up * processors, so we initialize the SPC driver here.
*/
ret = ve_spc_init(scc + SPC_BASE, a15_cluster_id, irq); if (ret) return ret;
if (!cci_probed()) return -ENODEV;
mpidr = read_cpuid_mpidr();
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) {
pr_err("%s: boot CPU is out of bound!\n", __func__); return -EINVAL;
}
ret = mcpm_platform_register(&tc2_pm_power_ops); if (!ret) {
mcpm_sync_init(tc2_pm_power_up_setup); /* test if we can (re)enable the CCI on our own */
BUG_ON(mcpm_loopback(tc2_pm_cluster_cache_disable) != 0);
pr_info("TC2 power management initialized\n");
} 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.