diff options
Diffstat (limited to 'drivers/irqchip/irq-brcmstb-l2.c')
-rw-r--r-- | drivers/irqchip/irq-brcmstb-l2.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index c15c840987d2..313c2c64498a 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -18,7 +18,9 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/kconfig.h> #include <linux/platform_device.h> +#include <linux/spinlock.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_address.h> @@ -30,8 +32,6 @@ #include <linux/irqchip.h> #include <linux/irqchip/chained_irq.h> -#include <asm/mach/irq.h> - #include "irqchip.h" /* Register offsets in the L2 interrupt controller */ @@ -54,23 +54,26 @@ struct brcmstb_l2_intc_data { static void brcmstb_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) { struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc); + struct irq_chip_generic *gc = irq_get_domain_generic_chip(b->domain, 0); struct irq_chip *chip = irq_desc_get_chip(desc); u32 status; chained_irq_enter(chip, desc); - status = __raw_readl(b->base + CPU_STATUS) & - ~(__raw_readl(b->base + CPU_MASK_STATUS)); + status = irq_reg_readl(gc, CPU_STATUS) & + ~(irq_reg_readl(gc, CPU_MASK_STATUS)); if (status == 0) { - do_bad_IRQ(irq, desc); + raw_spin_lock(&desc->lock); + handle_bad_irq(irq, desc); + raw_spin_unlock(&desc->lock); goto out; } do { irq = ffs(status) - 1; /* ack at our level */ - __raw_writel(1 << irq, b->base + CPU_CLEAR); + irq_reg_writel(gc, 1 << irq, CPU_CLEAR); status &= ~(1 << irq); generic_handle_irq(irq_find_mapping(b->domain, irq)); } while (status); @@ -85,12 +88,12 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d) irq_gc_lock(gc); /* Save the current mask */ - b->saved_mask = __raw_readl(b->base + CPU_MASK_STATUS); + b->saved_mask = irq_reg_readl(gc, CPU_MASK_STATUS); if (b->can_wake) { /* Program the wakeup mask */ - __raw_writel(~gc->wake_active, b->base + CPU_MASK_SET); - __raw_writel(gc->wake_active, b->base + CPU_MASK_CLEAR); + irq_reg_writel(gc, ~gc->wake_active, CPU_MASK_SET); + irq_reg_writel(gc, gc->wake_active, CPU_MASK_CLEAR); } irq_gc_unlock(gc); } @@ -102,11 +105,11 @@ static void brcmstb_l2_intc_resume(struct irq_data *d) irq_gc_lock(gc); /* Clear unmasked non-wakeup interrupts */ - __raw_writel(~b->saved_mask & ~gc->wake_active, b->base + CPU_CLEAR); + irq_reg_writel(gc, ~b->saved_mask & ~gc->wake_active, CPU_CLEAR); /* Restore the saved mask */ - __raw_writel(b->saved_mask, b->base + CPU_MASK_SET); - __raw_writel(~b->saved_mask, b->base + CPU_MASK_CLEAR); + irq_reg_writel(gc, b->saved_mask, CPU_MASK_SET); + irq_reg_writel(gc, ~b->saved_mask, CPU_MASK_CLEAR); irq_gc_unlock(gc); } @@ -118,6 +121,7 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, struct irq_chip_generic *gc; struct irq_chip_type *ct; int ret; + unsigned int flags; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -131,13 +135,13 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, } /* Disable all interrupts by default */ - __raw_writel(0xffffffff, data->base + CPU_MASK_SET); - __raw_writel(0xffffffff, data->base + CPU_CLEAR); + writel(0xffffffff, data->base + CPU_MASK_SET); + writel(0xffffffff, data->base + CPU_CLEAR); data->parent_irq = irq_of_parse_and_map(np, 0); - if (data->parent_irq < 0) { + if (!data->parent_irq) { pr_err("failed to find parent interrupt\n"); - ret = data->parent_irq; + ret = -EINVAL; goto out_unmap; } @@ -148,9 +152,16 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, goto out_unmap; } + /* MIPS chips strapped for BE will automagically configure the + * peripheral registers for CPU-native byte order. + */ + flags = 0; + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + flags |= IRQ_GC_BE_IO; + /* Allocate a single Generic IRQ chip for this node */ ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, - np->full_name, handle_edge_irq, clr, 0, 0); + np->full_name, handle_edge_irq, clr, 0, flags); if (ret) { pr_err("failed to allocate generic irq chip\n"); goto out_free_domain; |