Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 359912
b: refs/heads/master
c: 3202bf0
h: refs/heads/master
v: v3
  • Loading branch information
Gregory CLEMENT authored and Arnd Bergmann committed Feb 28, 2013
1 parent 3c9460d commit ade8afc
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 48be9ac930086f7605fb4959936f568e865b2cff
refs/heads/master: 3202bf0157ccbf8f1f89051d60ba9ca3aa4d424f
2 changes: 1 addition & 1 deletion trunk/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 trunk/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 ade8afc

Please sign in to comment.