|
@@ -37,9 +37,6 @@
|
|
#define OF_SECONDARY_BOOT "secondary-boot-reg"
|
|
#define OF_SECONDARY_BOOT "secondary-boot-reg"
|
|
#define MPIDR_CPUID_BITMASK 0x3
|
|
#define MPIDR_CPUID_BITMASK 0x3
|
|
|
|
|
|
-/* I/O address of register used to coordinate secondary core startup */
|
|
|
|
-static u32 secondary_boot_addr;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Enable the Cortex A9 Snoop Control Unit
|
|
* Enable the Cortex A9 Snoop Control Unit
|
|
*
|
|
*
|
|
@@ -81,20 +78,40 @@ static int __init scu_a9_enable(void)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int nsp_write_lut(void)
|
|
|
|
|
|
+static u32 secondary_boot_addr_for(unsigned int cpu)
|
|
|
|
+{
|
|
|
|
+ u32 secondary_boot_addr = 0;
|
|
|
|
+ struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
|
|
|
|
+
|
|
|
|
+ if (!cpu_node) {
|
|
|
|
+ pr_err("Failed to find device tree node for CPU%u\n", cpu);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (of_property_read_u32(cpu_node,
|
|
|
|
+ OF_SECONDARY_BOOT,
|
|
|
|
+ &secondary_boot_addr))
|
|
|
|
+ pr_err("required secondary boot register not specified for CPU%u\n",
|
|
|
|
+ cpu);
|
|
|
|
+
|
|
|
|
+ of_node_put(cpu_node);
|
|
|
|
+
|
|
|
|
+ return secondary_boot_addr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int nsp_write_lut(unsigned int cpu)
|
|
{
|
|
{
|
|
void __iomem *sku_rom_lut;
|
|
void __iomem *sku_rom_lut;
|
|
phys_addr_t secondary_startup_phy;
|
|
phys_addr_t secondary_startup_phy;
|
|
|
|
+ const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
|
|
|
|
|
|
- if (!secondary_boot_addr) {
|
|
|
|
- pr_warn("required secondary boot register not specified\n");
|
|
|
|
|
|
+ if (!secondary_boot_addr)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
- }
|
|
|
|
|
|
|
|
sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr,
|
|
sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr,
|
|
- sizeof(secondary_boot_addr));
|
|
|
|
|
|
+ sizeof(phys_addr_t));
|
|
if (!sku_rom_lut) {
|
|
if (!sku_rom_lut) {
|
|
- pr_warn("unable to ioremap SKU-ROM LUT register\n");
|
|
|
|
|
|
+ pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu);
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -113,70 +130,12 @@ static int nsp_write_lut(void)
|
|
|
|
|
|
static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
|
|
static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
|
|
{
|
|
{
|
|
- static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
|
|
|
|
- struct device_node *cpus_node = NULL;
|
|
|
|
- struct device_node *cpu_node = NULL;
|
|
|
|
- int ret;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * This function is only called via smp_ops->smp_prepare_cpu().
|
|
|
|
- * That only happens if a "/cpus" device tree node exists
|
|
|
|
- * and has an "enable-method" property that selects the SMP
|
|
|
|
- * operations defined herein.
|
|
|
|
- */
|
|
|
|
- cpus_node = of_find_node_by_path("/cpus");
|
|
|
|
- if (!cpus_node)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- for_each_child_of_node(cpus_node, cpu_node) {
|
|
|
|
- u32 cpuid;
|
|
|
|
-
|
|
|
|
- if (of_node_cmp(cpu_node->type, "cpu"))
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
|
|
|
|
- pr_debug("%s: missing reg property\n",
|
|
|
|
- cpu_node->full_name);
|
|
|
|
- ret = -ENOENT;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * "secondary-boot-reg" property should be defined only
|
|
|
|
- * for secondary cpu
|
|
|
|
- */
|
|
|
|
- if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
|
|
|
|
- /*
|
|
|
|
- * Our secondary enable method requires a
|
|
|
|
- * "secondary-boot-reg" property to specify a register
|
|
|
|
- * address used to request the ROM code boot a secondary
|
|
|
|
- * core. If we have any trouble getting this we fall
|
|
|
|
- * back to uniprocessor mode.
|
|
|
|
- */
|
|
|
|
- if (of_property_read_u32(cpu_node,
|
|
|
|
- OF_SECONDARY_BOOT,
|
|
|
|
- &secondary_boot_addr)) {
|
|
|
|
- pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
|
|
|
|
- cpu_node->name);
|
|
|
|
- ret = -ENOENT;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
|
|
|
|
- * returned, the SoC reported a uniprocessor configuration.
|
|
|
|
- * We bail on any other error.
|
|
|
|
- */
|
|
|
|
- ret = scu_a9_enable();
|
|
|
|
-out:
|
|
|
|
- of_node_put(cpu_node);
|
|
|
|
- of_node_put(cpus_node);
|
|
|
|
|
|
+ const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
|
|
|
|
|
|
- if (ret) {
|
|
|
|
|
|
+ /* Enable the SCU on Cortex A9 based SoCs */
|
|
|
|
+ if (scu_a9_enable()) {
|
|
/* Update the CPU present map to reflect uniprocessor mode */
|
|
/* Update the CPU present map to reflect uniprocessor mode */
|
|
- pr_warn("disabling SMP\n");
|
|
|
|
|
|
+ pr_warn("failed to enable A9 SCU - disabling SMP\n");
|
|
init_cpu_present(&only_cpu_0);
|
|
init_cpu_present(&only_cpu_0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -207,6 +166,7 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|
u32 cpu_id;
|
|
u32 cpu_id;
|
|
u32 boot_val;
|
|
u32 boot_val;
|
|
bool timeout = false;
|
|
bool timeout = false;
|
|
|
|
+ const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
|
|
|
|
|
|
cpu_id = cpu_logical_map(cpu);
|
|
cpu_id = cpu_logical_map(cpu);
|
|
if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
|
|
if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
|
|
@@ -214,13 +174,11 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!secondary_boot_addr) {
|
|
|
|
- pr_err("required secondary boot register not specified\n");
|
|
|
|
|
|
+ if (!secondary_boot_addr)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
- }
|
|
|
|
|
|
|
|
- boot_reg = ioremap_nocache(
|
|
|
|
- (phys_addr_t)secondary_boot_addr, sizeof(u32));
|
|
|
|
|
|
+ boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr,
|
|
|
|
+ sizeof(phys_addr_t));
|
|
if (!boot_reg) {
|
|
if (!boot_reg) {
|
|
pr_err("unable to map boot register for cpu %u\n", cpu_id);
|
|
pr_err("unable to map boot register for cpu %u\n", cpu_id);
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
@@ -263,7 +221,7 @@ static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|
* After wake up, secondary core branches to the startup
|
|
* After wake up, secondary core branches to the startup
|
|
* address programmed at SKU ROM LUT location.
|
|
* address programmed at SKU ROM LUT location.
|
|
*/
|
|
*/
|
|
- ret = nsp_write_lut();
|
|
|
|
|
|
+ ret = nsp_write_lut(cpu);
|
|
if (ret) {
|
|
if (ret) {
|
|
pr_err("unable to write startup addr to SKU ROM LUT\n");
|
|
pr_err("unable to write startup addr to SKU ROM LUT\n");
|
|
goto out;
|
|
goto out;
|
|
@@ -276,12 +234,12 @@ out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static const struct smp_operations bcm_smp_ops __initconst = {
|
|
|
|
|
|
+static const struct smp_operations kona_smp_ops __initconst = {
|
|
.smp_prepare_cpus = bcm_smp_prepare_cpus,
|
|
.smp_prepare_cpus = bcm_smp_prepare_cpus,
|
|
.smp_boot_secondary = kona_boot_secondary,
|
|
.smp_boot_secondary = kona_boot_secondary,
|
|
};
|
|
};
|
|
CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
|
|
CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
|
|
- &bcm_smp_ops);
|
|
|
|
|
|
+ &kona_smp_ops);
|
|
|
|
|
|
static const struct smp_operations nsp_smp_ops __initconst = {
|
|
static const struct smp_operations nsp_smp_ops __initconst = {
|
|
.smp_prepare_cpus = bcm_smp_prepare_cpus,
|
|
.smp_prepare_cpus = bcm_smp_prepare_cpus,
|