Skip to content

Commit

Permalink
arm: mvebu: Improve the SMP support of the interrupt controller
Browse files Browse the repository at this point in the history
This patch makes the interrupt controller driver more SMP aware for
the Armada XP SoCs. It adds the support for the per-CPU irq. It also
adds the implementation for the set_affinity hook.

Patch initialy wrote by Yehuda Yitschak and reworked by Gregory
CLEMENT.

Signed-off-by: Yehuda Yitschak <yehuday@marvell.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
  • Loading branch information
Gregory CLEMENT authored and Arnd Bergmann committed Feb 28, 2013
1 parent 48be9ac commit 3202bf0
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
2 changes: 1 addition & 1 deletion arch/arm/boot/dts/armada-xp.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
};

mpic: interrupt-controller@d0020000 {
reg = <0xd0020a00 0x1d0>,
reg = <0xd0020a00 0x2d0>,
<0xd0021070 0x58>;
};

Expand Down
72 changes: 72 additions & 0 deletions arch/arm/mach-mvebu/irq-armada-370-xp.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,35 +34,98 @@
#define ARMADA_370_XP_INT_CONTROL (0x00)
#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)

#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)

#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8)

#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)

#define ACTIVE_DOORBELLS (8)

static DEFINE_RAW_SPINLOCK(irq_controller_lock);

static void __iomem *per_cpu_int_base;
static void __iomem *main_int_base;
static struct irq_domain *armada_370_xp_mpic_domain;

/*
* In SMP mode:
* For shared global interrupts, mask/unmask global enable bit
* For CPU interrtups, mask/unmask the calling CPU's bit
*/
static void armada_370_xp_irq_mask(struct irq_data *d)
{
#ifdef CONFIG_SMP
irq_hw_number_t hwirq = irqd_to_hwirq(d);

if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
writel(hwirq, main_int_base +
ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
else
writel(hwirq, per_cpu_int_base +
ARMADA_370_XP_INT_SET_MASK_OFFS);
#else
writel(irqd_to_hwirq(d),
per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
#endif
}

static void armada_370_xp_irq_unmask(struct irq_data *d)
{
#ifdef CONFIG_SMP
irq_hw_number_t hwirq = irqd_to_hwirq(d);

if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
writel(hwirq, main_int_base +
ARMADA_370_XP_INT_SET_ENABLE_OFFS);
else
writel(hwirq, per_cpu_int_base +
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
#else
writel(irqd_to_hwirq(d),
per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
#endif
}

#ifdef CONFIG_SMP
static int armada_xp_set_affinity(struct irq_data *d,
const struct cpumask *mask_val, bool force)
{
unsigned long reg;
unsigned long new_mask = 0;
unsigned long online_mask = 0;
unsigned long count = 0;
irq_hw_number_t hwirq = irqd_to_hwirq(d);
int cpu;

for_each_cpu(cpu, mask_val) {
new_mask |= 1 << cpu_logical_map(cpu);
count++;
}

/*
* Forbid mutlicore interrupt affinity
* This is required since the MPIC HW doesn't limit
* several CPUs from acknowledging the same interrupt.
*/
if (count > 1)
return -EINVAL;

for_each_cpu(cpu, cpu_online_mask)
online_mask |= 1 << cpu_logical_map(cpu);

raw_spin_lock(&irq_controller_lock);

reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
reg = (reg & (~online_mask)) | new_mask;
writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));

raw_spin_unlock(&irq_controller_lock);

return 0;
}
#endif
Expand Down Expand Up @@ -155,6 +218,15 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,

#ifdef CONFIG_SMP
armada_xp_mpic_smp_cpu_init();

/*
* Set the default affinity from all CPUs to the boot cpu.
* This is required since the MPIC doesn't limit several CPUs
* from acknowledging the same interrupt.
*/
cpumask_clear(irq_default_affinity);
cpumask_set_cpu(smp_processor_id(), irq_default_affinity);

#endif

return 0;
Expand Down

0 comments on commit 3202bf0

Please sign in to comment.