diff options
Diffstat (limited to 'arch/arm/common/gic.c')
| -rw-r--r-- | arch/arm/common/gic.c | 25 | 
1 files changed, 23 insertions, 2 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 36ae03a3f5d..87dfa9026c5 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -351,6 +351,25 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)  	irq_set_chained_handler(irq, gic_handle_cascade_irq);  } +static u8 gic_get_cpumask(struct gic_chip_data *gic) +{ +	void __iomem *base = gic_data_dist_base(gic); +	u32 mask, i; + +	for (i = mask = 0; i < 32; i += 4) { +		mask = readl_relaxed(base + GIC_DIST_TARGET + i); +		mask |= mask >> 16; +		mask |= mask >> 8; +		if (mask) +			break; +	} + +	if (!mask) +		pr_crit("GIC CPU mask not found - kernel will fail to boot.\n"); + +	return mask; +} +  static void __init gic_dist_init(struct gic_chip_data *gic)  {  	unsigned int i; @@ -369,7 +388,9 @@ static void __init gic_dist_init(struct gic_chip_data *gic)  	/*  	 * Set all global interrupts to this CPU only.  	 */ -	cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0); +	cpumask = gic_get_cpumask(gic); +	cpumask |= cpumask << 8; +	cpumask |= cpumask << 16;  	for (i = 32; i < gic_irqs; i += 4)  		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); @@ -400,7 +421,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)  	 * Get what the GIC says our CPU mask is.  	 */  	BUG_ON(cpu >= NR_GIC_CPU_IF); -	cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0); +	cpu_mask = gic_get_cpumask(gic);  	gic_cpu_map[cpu] = cpu_mask;  	/*  |