aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-vexpress
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2012-07-18 16:41:16 -0400
committerNicolas Pitre <nicolas.pitre@linaro.org>2013-05-29 15:50:35 -0400
commit2f2df895ee3518fbef28dfa6736dfd1e1c04ee1c (patch)
treecca1f6645e733c760da0837e71d323a68be2111e /arch/arm/mach-vexpress
parent13eae144ec754ab64521891d2cffc3156f6f083f (diff)
ARM: vexpress/dcscb: do not hardcode number of CPUs per cluster
If 4 CPUs are assumed, the A15x1-A7x1 model configuration would never shut down the initial cluster as the 0xf reset bit mask will never be observed. Let's construct this mask based on the provided information in the DCSCB config register for the number of CPUs per cluster. Signed-off-by: Nicolas Pitre <nico@linaro.org> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Pawel Moll <pawel.moll@arm.com>
Diffstat (limited to 'arch/arm/mach-vexpress')
-rw-r--r--arch/arm/mach-vexpress/dcscb.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/arm/mach-vexpress/dcscb.c b/arch/arm/mach-vexpress/dcscb.c
index 65dee7818082..44aa7b040e82 100644
--- a/arch/arm/mach-vexpress/dcscb.c
+++ b/arch/arm/mach-vexpress/dcscb.c
@@ -45,10 +45,12 @@ static arch_spinlock_t dcscb_lock = __ARCH_SPIN_LOCK_UNLOCKED;
45 45
46static void __iomem *dcscb_base; 46static void __iomem *dcscb_base;
47static int dcscb_use_count[4][2]; 47static int dcscb_use_count[4][2];
48static int dcscb_allcpus_mask[2];
48 49
49static int dcscb_power_up(unsigned int cpu, unsigned int cluster) 50static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
50{ 51{
51 unsigned int rst_hold, cpumask = (1 << cpu); 52 unsigned int rst_hold, cpumask = (1 << cpu);
53 unsigned int all_mask = dcscb_allcpus_mask[cluster];
52 54
53 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); 55 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
54 if (cpu >= 4 || cluster >= 2) 56 if (cpu >= 4 || cluster >= 2)
@@ -67,7 +69,7 @@ static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
67 if (rst_hold & (1 << 8)) { 69 if (rst_hold & (1 << 8)) {
68 /* remove cluster reset and add individual CPU's reset */ 70 /* remove cluster reset and add individual CPU's reset */
69 rst_hold &= ~(1 << 8); 71 rst_hold &= ~(1 << 8);
70 rst_hold |= 0xf; 72 rst_hold |= all_mask;
71 } 73 }
72 rst_hold &= ~(cpumask | (cpumask << 4)); 74 rst_hold &= ~(cpumask | (cpumask << 4));
73 writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4); 75 writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
@@ -91,13 +93,14 @@ static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
91 93
92static void dcscb_power_down(void) 94static void dcscb_power_down(void)
93{ 95{
94 unsigned int mpidr, cpu, cluster, rst_hold, cpumask; 96 unsigned int mpidr, cpu, cluster, rst_hold, cpumask, all_mask;
95 bool last_man = false, skip_wfi = false; 97 bool last_man = false, skip_wfi = false;
96 98
97 mpidr = read_cpuid_mpidr(); 99 mpidr = read_cpuid_mpidr();
98 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); 100 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
99 cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); 101 cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
100 cpumask = (1 << cpu); 102 cpumask = (1 << cpu);
103 all_mask = dcscb_allcpus_mask[cluster];
101 104
102 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); 105 pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
103 BUG_ON(cpu >= 4 || cluster >= 2); 106 BUG_ON(cpu >= 4 || cluster >= 2);
@@ -107,7 +110,7 @@ static void dcscb_power_down(void)
107 if (dcscb_use_count[cpu][cluster] == 0) { 110 if (dcscb_use_count[cpu][cluster] == 0) {
108 rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4); 111 rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
109 rst_hold |= cpumask; 112 rst_hold |= cpumask;
110 if (((rst_hold | (rst_hold >> 4)) & 0xf) == 0xf) { 113 if (((rst_hold | (rst_hold >> 4)) & all_mask) == all_mask) {
111 rst_hold |= (1 << 8); 114 rst_hold |= (1 << 8);
112 last_man = true; 115 last_man = true;
113 } 116 }
@@ -177,6 +180,7 @@ static void __init dcscb_usage_count_init(void)
177static int __init dcscb_init(void) 180static int __init dcscb_init(void)
178{ 181{
179 struct device_node *node; 182 struct device_node *node;
183 unsigned int cfg;
180 int ret; 184 int ret;
181 185
182 node = of_find_compatible_node(NULL, NULL, "arm,rtsm,dcscb"); 186 node = of_find_compatible_node(NULL, NULL, "arm,rtsm,dcscb");
@@ -185,7 +189,9 @@ static int __init dcscb_init(void)
185 dcscb_base = of_iomap(node, 0); 189 dcscb_base = of_iomap(node, 0);
186 if (!dcscb_base) 190 if (!dcscb_base)
187 return -EADDRNOTAVAIL; 191 return -EADDRNOTAVAIL;
188 192 cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
193 dcscb_allcpus_mask[0] = (1 << (((cfg >> 16) >> (0 << 2)) & 0xf)) - 1;
194 dcscb_allcpus_mask[1] = (1 << (((cfg >> 16) >> (1 << 2)) & 0xf)) - 1;
189 dcscb_usage_count_init(); 195 dcscb_usage_count_init();
190 196
191 ret = mcpm_platform_register(&dcscb_power_ops); 197 ret = mcpm_platform_register(&dcscb_power_ops);