aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2012-07-18 16:41:16 -0400
committerJon Medhurst <tixy@linaro.org>2013-05-03 12:11:41 +0100
commit1cd802a0e99b2d4c8bde85be19748960efa6cacd (patch)
tree4eabd93a2e7d5e6473a0c75f41c783d69a4c8f4d
parent0f80732f5d51be9c981a78cbcbecdc5b72f7a1e6 (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>
-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 946b332ab99..dd9e80566f9 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;
static void __iomem *dcscb_base;
static int dcscb_use_count[4][2];
+static int dcscb_mcpm_cpu_mask[2];
static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
{
unsigned int rst_hold, cpumask = (1 << cpu);
+ unsigned int mcpm_mask = dcscb_mcpm_cpu_mask[cluster];
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
if (cpu >= 4 || cluster >= 2)
@@ -67,7 +69,7 @@ static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
if (rst_hold & (1 << 8)) {
/* remove cluster reset and add individual CPU's reset */
rst_hold &= ~(1 << 8);
- rst_hold |= 0xf;
+ rst_hold |= mcpm_mask;
}
rst_hold &= ~(cpumask | (cpumask << 4));
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)
static void dcscb_power_down(void)
{
- unsigned int mpidr, cpu, cluster, rst_hold, cpumask;
+ unsigned int mpidr, cpu, cluster, rst_hold, cpumask, mcpm_mask;
bool last_man = false, skip_wfi = false;
mpidr = read_cpuid_mpidr();
cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
cpumask = (1 << cpu);
+ mcpm_mask = dcscb_mcpm_cpu_mask[cluster];
pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
BUG_ON(cpu >= 4 || cluster >= 2);
@@ -107,7 +110,7 @@ static void dcscb_power_down(void)
if (dcscb_use_count[cpu][cluster] == 0) {
rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
rst_hold |= cpumask;
- if (((rst_hold | (rst_hold >> 4)) & 0xf) == 0xf) {
+ if (((rst_hold | (rst_hold >> 4)) & mcpm_mask) == mcpm_mask) {
rst_hold |= (1 << 8);
last_man = true;
}
@@ -178,6 +181,7 @@ static void __init dcscb_usage_count_init(void)
static int __init dcscb_init(void)
{
struct device_node *node;
+ unsigned int cfg;
int ret;
node = of_find_compatible_node(NULL, NULL, "arm,rtsm,dcscb");
@@ -186,7 +190,9 @@ static int __init dcscb_init(void)
dcscb_base= of_iomap(node, 0);
if (!dcscb_base)
return -EADDRNOTAVAIL;
-
+ cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
+ dcscb_mcpm_cpu_mask[0] = (1 << (((cfg >> 16) >> (0 << 2)) & 0xf)) - 1;
+ dcscb_mcpm_cpu_mask[1] = (1 << (((cfg >> 16) >> (1 << 2)) & 0xf)) - 1;
dcscb_usage_count_init();
ret = mcpm_platform_register(&dcscb_power_ops);