diff options
author | Kapil Hali <kapilh@broadcom.com> | 2015-12-01 11:24:06 -0500 |
---|---|---|
committer | Florian Fainelli <f.fainelli@gmail.com> | 2015-12-07 15:30:17 -0500 |
commit | 84320e1a635fcf90cff4185f029ce9e31bf1d4a7 (patch) | |
tree | a42fd368793397dbee9c1c4201ea5429fdecb99b /arch/arm/mach-bcm | |
parent | f4ce7effe2253a325f8ba182903cbdf0d8698593 (diff) |
ARM: BCM: Clean up SMP support for Broadcom Kona
These changes cleans up SMP implementaion for Broadcom's
Kona SoC which are required for handling SMP for iProc
family of SoCs at a single place for BCM NSP and BCM Kona.
Signed-off-by: Kapil Hali <kapilh@broadcom.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Diffstat (limited to 'arch/arm/mach-bcm')
-rw-r--r-- | arch/arm/mach-bcm/kona_smp.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/arch/arm/mach-bcm/kona_smp.c b/arch/arm/mach-bcm/kona_smp.c index 66a0465528a5..15af781228a5 100644 --- a/arch/arm/mach-bcm/kona_smp.c +++ b/arch/arm/mach-bcm/kona_smp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2014 Broadcom Corporation | 2 | * Copyright (C) 2014-2015 Broadcom Corporation |
3 | * Copyright 2014 Linaro Limited | 3 | * Copyright 2014 Linaro Limited |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -30,9 +30,10 @@ | |||
30 | 30 | ||
31 | /* Name of device node property defining secondary boot register location */ | 31 | /* Name of device node property defining secondary boot register location */ |
32 | #define OF_SECONDARY_BOOT "secondary-boot-reg" | 32 | #define OF_SECONDARY_BOOT "secondary-boot-reg" |
33 | #define MPIDR_CPUID_BITMASK 0x3 | ||
33 | 34 | ||
34 | /* I/O address of register used to coordinate secondary core startup */ | 35 | /* I/O address of register used to coordinate secondary core startup */ |
35 | static u32 secondary_boot; | 36 | static u32 secondary_boot_addr; |
36 | 37 | ||
37 | /* | 38 | /* |
38 | * Enable the Cortex A9 Snoop Control Unit | 39 | * Enable the Cortex A9 Snoop Control Unit |
@@ -78,44 +79,68 @@ static int __init scu_a9_enable(void) | |||
78 | static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) | 79 | static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) |
79 | { | 80 | { |
80 | static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; | 81 | static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; |
81 | struct device_node *node; | 82 | struct device_node *cpus_node = NULL; |
83 | struct device_node *cpu_node = NULL; | ||
82 | int ret; | 84 | int ret; |
83 | 85 | ||
84 | BUG_ON(secondary_boot); /* We're called only once */ | ||
85 | |||
86 | /* | 86 | /* |
87 | * This function is only called via smp_ops->smp_prepare_cpu(). | 87 | * This function is only called via smp_ops->smp_prepare_cpu(). |
88 | * That only happens if a "/cpus" device tree node exists | 88 | * That only happens if a "/cpus" device tree node exists |
89 | * and has an "enable-method" property that selects the SMP | 89 | * and has an "enable-method" property that selects the SMP |
90 | * operations defined herein. | 90 | * operations defined herein. |
91 | */ | 91 | */ |
92 | node = of_find_node_by_path("/cpus"); | 92 | cpus_node = of_find_node_by_path("/cpus"); |
93 | BUG_ON(!node); | 93 | if (!cpus_node) |
94 | 94 | return; | |
95 | /* | 95 | |
96 | * Our secondary enable method requires a "secondary-boot-reg" | 96 | for_each_child_of_node(cpus_node, cpu_node) { |
97 | * property to specify a register address used to request the | 97 | u32 cpuid; |
98 | * ROM code boot a secondary code. If we have any trouble | 98 | |
99 | * getting this we fall back to uniprocessor mode. | 99 | if (of_node_cmp(cpu_node->type, "cpu")) |
100 | */ | 100 | continue; |
101 | if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) { | 101 | |
102 | pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n", | 102 | if (of_property_read_u32(cpu_node, "reg", &cpuid)) { |
103 | node->name); | 103 | pr_debug("%s: missing reg property\n", |
104 | ret = -ENOENT; /* Arrange to disable SMP */ | 104 | cpu_node->full_name); |
105 | goto out; | 105 | ret = -ENOENT; |
106 | goto out; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * "secondary-boot-reg" property should be defined only | ||
111 | * for secondary cpu | ||
112 | */ | ||
113 | if ((cpuid & MPIDR_CPUID_BITMASK) == 1) { | ||
114 | /* | ||
115 | * Our secondary enable method requires a | ||
116 | * "secondary-boot-reg" property to specify a register | ||
117 | * address used to request the ROM code boot a secondary | ||
118 | * core. If we have any trouble getting this we fall | ||
119 | * back to uniprocessor mode. | ||
120 | */ | ||
121 | if (of_property_read_u32(cpu_node, | ||
122 | OF_SECONDARY_BOOT, | ||
123 | &secondary_boot_addr)) { | ||
124 | pr_warn("%s: no" OF_SECONDARY_BOOT "property\n", | ||
125 | cpu_node->name); | ||
126 | ret = -ENOENT; | ||
127 | goto out; | ||
128 | } | ||
129 | } | ||
106 | } | 130 | } |
107 | 131 | ||
108 | /* | 132 | /* |
109 | * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is | 133 | * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is |
110 | * returned, the SoC reported a uniprocessor configuration. | 134 | * returned, the SoC reported a uniprocessor configuration. |
111 | * We bail on any other error. | 135 | * We bail on any other error. |
112 | */ | 136 | */ |
113 | ret = scu_a9_enable(); | 137 | ret = scu_a9_enable(); |
114 | out: | 138 | out: |
115 | of_node_put(node); | 139 | of_node_put(cpu_node); |
140 | of_node_put(cpus_node); | ||
141 | |||
116 | if (ret) { | 142 | if (ret) { |
117 | /* Update the CPU present map to reflect uniprocessor mode */ | 143 | /* Update the CPU present map to reflect uniprocessor mode */ |
118 | BUG_ON(ret != -ENOENT); | ||
119 | pr_warn("disabling SMP\n"); | 144 | pr_warn("disabling SMP\n"); |
120 | init_cpu_present(&only_cpu_0); | 145 | init_cpu_present(&only_cpu_0); |
121 | } | 146 | } |
@@ -139,7 +164,7 @@ out: | |||
139 | * - Wait for the secondary boot register to be re-written, which | 164 | * - Wait for the secondary boot register to be re-written, which |
140 | * indicates the secondary core has started. | 165 | * indicates the secondary core has started. |
141 | */ | 166 | */ |
142 | static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) | 167 | static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) |
143 | { | 168 | { |
144 | void __iomem *boot_reg; | 169 | void __iomem *boot_reg; |
145 | phys_addr_t boot_func; | 170 | phys_addr_t boot_func; |
@@ -154,15 +179,16 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
154 | return -EINVAL; | 179 | return -EINVAL; |
155 | } | 180 | } |
156 | 181 | ||
157 | if (!secondary_boot) { | 182 | if (!secondary_boot_addr) { |
158 | pr_err("required secondary boot register not specified\n"); | 183 | pr_err("required secondary boot register not specified\n"); |
159 | return -EINVAL; | 184 | return -EINVAL; |
160 | } | 185 | } |
161 | 186 | ||
162 | boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32)); | 187 | boot_reg = ioremap_nocache( |
188 | (phys_addr_t)secondary_boot_addr, sizeof(u32)); | ||
163 | if (!boot_reg) { | 189 | if (!boot_reg) { |
164 | pr_err("unable to map boot register for cpu %u\n", cpu_id); | 190 | pr_err("unable to map boot register for cpu %u\n", cpu_id); |
165 | return -ENOSYS; | 191 | return -ENOMEM; |
166 | } | 192 | } |
167 | 193 | ||
168 | /* | 194 | /* |
@@ -191,12 +217,12 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
191 | 217 | ||
192 | pr_err("timeout waiting for cpu %u to start\n", cpu_id); | 218 | pr_err("timeout waiting for cpu %u to start\n", cpu_id); |
193 | 219 | ||
194 | return -ENOSYS; | 220 | return -ENXIO; |
195 | } | 221 | } |
196 | 222 | ||
197 | static struct smp_operations bcm_smp_ops __initdata = { | 223 | static struct smp_operations bcm_smp_ops __initdata = { |
198 | .smp_prepare_cpus = bcm_smp_prepare_cpus, | 224 | .smp_prepare_cpus = bcm_smp_prepare_cpus, |
199 | .smp_boot_secondary = bcm_boot_secondary, | 225 | .smp_boot_secondary = kona_boot_secondary, |
200 | }; | 226 | }; |
201 | CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", | 227 | CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", |
202 | &bcm_smp_ops); | 228 | &bcm_smp_ops); |