irqchip mvebu changes for v3.15
- armada-370-xp - add MSI helper - MPIC chained handler -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTCECPAAoJEP45WPkGe8ZnyNEP/0nBSeYcCzxs5ZR0DHwsOmyg C7XQefAj0YJL+lsv/Y18NKtYG9B+1j1QoFXqDeF8ZE2K9vShVmLEevHGpxeHr4Fv kAMO7i8uHNU27BPNxTS23d0UbJT5Nt0KA3AJJ9Dj28lBEjRNjAc5Pc87jcbZUd+g c4KKFuggzzwdbj8d1bR1ST8v2xbbg4p9+jmUWKNC2WLnTdZhAZJSPngGgrL8HtFo sAWXwcEPBshh/oRm9dmjPz+sQvEMXfI7V9jC6UTW9WlNTa4x7y5ngom0iQ40k62K wT7PtG6OxzJBI0wuRMjCLt8TInmTJ8Fl51s6VoZ6K08hke8bNdKNxGV0+gLCIPU1 My916yuLIcdgdr4rP+QwzqGEwTCzOKFrnS5JkDMzC36Cva38mfsXAp99mE2FFrO7 dCzDdVwYB4xs6WIApzAXYK88S/RM6PXujblP27hWJTqoa4eUvQQ8TFVaNbhRSCUo fzLEySeJJck/raDzBxEVloTGdb5uvOS/7YYM3+WO8vLnz5h4+bRHadR0l83XAk7d zhipwWwlAW0PuMYYMWmE0G9IQxbJDgm4uChqX7E3dviDWeYTwZYhM9nHIEcbh7o8 3wNrI9jZL+1y4dotX1Z4Mtd1FzBL47oLrDyx7gdvigyzxTAwAkAFr7rUYvHzuh1J NeL0qnmxxRMspRQvXmJ2 =1qJv -----END PGP SIGNATURE----- Merge tag 'irqchip-mvebu-3.15' of git://git.infradead.org/linux-mvebu into irq/core irqchip mvebu changes for v3.15 - armada-370-xp - add MSI helper - MPIC chained handler Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
commit
d0e3a9719f
@ -1,4 +1,4 @@
|
|||||||
Marvell Armada 370 and Armada XP Interrupt Controller
|
Marvell Armada 370, 375, 38x, XP Interrupt Controller
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
@ -16,7 +16,13 @@ Required properties:
|
|||||||
automatically map to the interrupt controller registers of the
|
automatically map to the interrupt controller registers of the
|
||||||
current CPU)
|
current CPU)
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
- interrupts: If defined, then it indicates that this MPIC is
|
||||||
|
connected as a slave to another interrupt controller. This is
|
||||||
|
typically the case on Armada 375 and Armada 38x, where the MPIC is
|
||||||
|
connected as a slave to the Cortex-A9 GIC. The provided interrupt
|
||||||
|
indicate to which GIC interrupt the MPIC output is connected.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/irqchip/chained_irq.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
@ -42,6 +43,7 @@
|
|||||||
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
|
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
|
||||||
|
|
||||||
#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
|
#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
|
||||||
|
#define ARMADA_375_PPI_CAUSE (0x10)
|
||||||
|
|
||||||
#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
|
#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
|
||||||
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
|
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
|
||||||
@ -352,6 +354,62 @@ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
|
|||||||
.xlate = irq_domain_xlate_onecell,
|
.xlate = irq_domain_xlate_onecell,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI_MSI
|
||||||
|
static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
|
||||||
|
{
|
||||||
|
u32 msimask, msinr;
|
||||||
|
|
||||||
|
msimask = readl_relaxed(per_cpu_int_base +
|
||||||
|
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
|
||||||
|
& PCI_MSI_DOORBELL_MASK;
|
||||||
|
|
||||||
|
writel(~msimask, per_cpu_int_base +
|
||||||
|
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
|
||||||
|
|
||||||
|
for (msinr = PCI_MSI_DOORBELL_START;
|
||||||
|
msinr < PCI_MSI_DOORBELL_END; msinr++) {
|
||||||
|
int irq;
|
||||||
|
|
||||||
|
if (!(msimask & BIT(msinr)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
irq = irq_find_mapping(armada_370_xp_msi_domain,
|
||||||
|
msinr - 16);
|
||||||
|
|
||||||
|
if (is_chained)
|
||||||
|
generic_handle_irq(irq);
|
||||||
|
else
|
||||||
|
handle_IRQ(irq, regs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
|
||||||
|
struct irq_desc *desc)
|
||||||
|
{
|
||||||
|
struct irq_chip *chip = irq_get_chip(irq);
|
||||||
|
unsigned long irqmap, irqn;
|
||||||
|
unsigned int cascade_irq;
|
||||||
|
|
||||||
|
chained_irq_enter(chip, desc);
|
||||||
|
|
||||||
|
irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);
|
||||||
|
|
||||||
|
if (irqmap & BIT(0)) {
|
||||||
|
armada_370_xp_handle_msi_irq(NULL, true);
|
||||||
|
irqmap &= ~BIT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
|
||||||
|
cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
|
||||||
|
generic_handle_irq(cascade_irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
chained_irq_exit(chip, desc);
|
||||||
|
}
|
||||||
|
|
||||||
static asmlinkage void __exception_irq_entry
|
static asmlinkage void __exception_irq_entry
|
||||||
armada_370_xp_handle_irq(struct pt_regs *regs)
|
armada_370_xp_handle_irq(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
@ -372,31 +430,9 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_MSI
|
|
||||||
/* MSI handling */
|
/* MSI handling */
|
||||||
if (irqnr == 1) {
|
if (irqnr == 1)
|
||||||
u32 msimask, msinr;
|
armada_370_xp_handle_msi_irq(regs, false);
|
||||||
|
|
||||||
msimask = readl_relaxed(per_cpu_int_base +
|
|
||||||
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
|
|
||||||
& PCI_MSI_DOORBELL_MASK;
|
|
||||||
|
|
||||||
writel(~msimask, per_cpu_int_base +
|
|
||||||
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
|
|
||||||
|
|
||||||
for (msinr = PCI_MSI_DOORBELL_START;
|
|
||||||
msinr < PCI_MSI_DOORBELL_END; msinr++) {
|
|
||||||
int irq;
|
|
||||||
|
|
||||||
if (!(msimask & BIT(msinr)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
irq = irq_find_mapping(armada_370_xp_msi_domain,
|
|
||||||
msinr - 16);
|
|
||||||
handle_IRQ(irq, regs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* IPI Handling */
|
/* IPI Handling */
|
||||||
@ -427,6 +463,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
|
|||||||
struct device_node *parent)
|
struct device_node *parent)
|
||||||
{
|
{
|
||||||
struct resource main_int_res, per_cpu_int_res;
|
struct resource main_int_res, per_cpu_int_res;
|
||||||
|
int parent_irq;
|
||||||
u32 control;
|
u32 control;
|
||||||
|
|
||||||
BUG_ON(of_address_to_resource(node, 0, &main_int_res));
|
BUG_ON(of_address_to_resource(node, 0, &main_int_res));
|
||||||
@ -455,8 +492,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
|
|||||||
|
|
||||||
BUG_ON(!armada_370_xp_mpic_domain);
|
BUG_ON(!armada_370_xp_mpic_domain);
|
||||||
|
|
||||||
irq_set_default_host(armada_370_xp_mpic_domain);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
armada_xp_mpic_smp_cpu_init();
|
armada_xp_mpic_smp_cpu_init();
|
||||||
|
|
||||||
@ -472,7 +507,14 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
|
|||||||
|
|
||||||
armada_370_xp_msi_init(node, main_int_res.start);
|
armada_370_xp_msi_init(node, main_int_res.start);
|
||||||
|
|
||||||
|
parent_irq = irq_of_parse_and_map(node, 0);
|
||||||
|
if (parent_irq <= 0) {
|
||||||
|
irq_set_default_host(armada_370_xp_mpic_domain);
|
||||||
set_handle_irq(armada_370_xp_handle_irq);
|
set_handle_irq(armada_370_xp_handle_irq);
|
||||||
|
} else {
|
||||||
|
irq_set_chained_handler(parent_irq,
|
||||||
|
armada_370_xp_mpic_handle_cascade_irq);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user