/* Size of mapped Cortex A9 SCU address space */ #define CORTEX_A9_SCU_SIZE 0x58
/* * Enable the Cortex A9 Snoop Control Unit * * By the time this is called we already know there are multiple * cores present. We assume we're running on a Cortex A9 processor, * so any trouble getting the base address register or getting the * SCU base is a problem. * * Return 0 if successful or an error code otherwise.
*/ staticint __init scu_a9_enable(void)
{ unsignedlong config_base; void __iomem *scu_base; unsignedint i, ncores;
if (!scu_a9_has_base()) {
pr_err("no configuration base address register!\n"); return -ENXIO;
}
/* Config base address register value is zero for uniprocessor */
config_base = scu_a9_get_base(); if (!config_base) {
pr_err("hardware reports only one core\n"); return -ENOENT;
}
scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); if (!scu_base) {
pr_err("failed to remap config base (%lu/%u) for SCU\n",
config_base, CORTEX_A9_SCU_SIZE); return -ENOMEM;
}
if (ncores > nr_cpu_ids) {
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
ncores, nr_cpu_ids);
ncores = nr_cpu_ids;
}
/* The BCM63138 SoC has two Cortex-A9 CPUs, CPU0 features a complete * and fully functional VFP unit that can be used, but CPU1 does not. * Since we will not be able to trap kernel-mode NEON to force * migration to CPU0, just do not advertise VFP support at all. * * This will make vfp_init bail out and do not attempt to use VFP at * all, for kernel-mode NEON, we do not want to introduce any * conditionals in hot-paths, so we just restrict the system to UP.
*/ #ifdef CONFIG_VFP if (ncores > 1) {
pr_warn("SMP: secondary CPUs lack VFP unit, disabling VFP\n");
vfp_disable();
staticint bcm63138_smp_boot_secondary(unsignedint cpu, struct task_struct *idle)
{ void __iomem *bootlut_base; struct device_node *dn; int ret = 0;
u32 val;
dn = of_find_matching_node(NULL, bcm63138_bootlut_ids); if (!dn) {
pr_err("SMP: unable to find bcm63138 boot LUT node\n"); return -ENODEV;
}
bootlut_base = of_iomap(dn, 0);
of_node_put(dn);
if (!bootlut_base) {
pr_err("SMP: unable to remap boot LUT base register\n"); return -ENOMEM;
}
/* Locate the secondary CPU node */
dn = of_get_cpu_node(cpu, NULL); if (!dn) {
pr_err("SMP: failed to locate secondary CPU%d node\n", cpu);
ret = -ENODEV; goto out;
}
/* Write the secondary init routine to the BootLUT reset vector */
val = __pa_symbol(secondary_startup);
writel_relaxed(val, bootlut_base + BOOTLUT_RESET_VECT);
/* Power up the core, will jump straight to its reset vector when we * return
*/
ret = bcm63xx_pmb_power_on_cpu(dn);
of_node_put(dn);
out:
iounmap(bootlut_base);
return ret;
}
staticvoid __init bcm63138_smp_prepare_cpus(unsignedint max_cpus)
{ int ret;
ret = scu_a9_enable(); if (ret) {
pr_warn("SMP: Cortex-A9 SCU setup failed\n"); return;
}
}
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.