aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip/irq-brcmstb-l2.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 11:38:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 11:38:57 -0500
commitecb50f0afd35a51ef487e8a54b976052eb03d729 (patch)
tree27457f87d3dc2ce6c81e16d795f953e66c2fff45 /drivers/irqchip/irq-brcmstb-l2.c
parenta157508c9790ccd1c8b5c6a828d6ba85bbe95aaa (diff)
parent1655b0530d9502e69686220491ffb15ba0738c58 (diff)
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq core updates from Thomas Gleixner: "This is the first (boring) part of irq updates: - support for big endian I/O accessors in the generic irq chip - cleanup of brcmstb/bcm7120 drivers so they can be reused for non ARM SoCs - the usual pile of fixes and updates for the various ARM irq chips" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits) irqchip: dw-apb-ictl: Add PM support irqchip: dw-apb-ictl: Enable IRQ_GC_MASK_CACHE_PER_TYPE irqchip: dw-apb-ictl: Always use use {readl|writel}_relaxed ARM: orion: convert the irq_reg_{readl,writel} calls to the new API irqchip: atmel-aic: Add missing entry for rm9200 irq fixups irqchip: atmel-aic: Rename at91sam9_aic_irq_fixup for naming consistency irqchip: atmel-aic: Add specific irq fixup function for sam9g45 and sam9rl irqchip: atmel-aic: Add irq fixups for at91sam926x SoCs irqchip: atmel-aic: Add irq fixup for RTT block irqchip: brcmstb-l2: Convert driver to use irq_reg_{readl,writel} irqchip: bcm7120-l2: Convert driver to use irq_reg_{readl,writel} irqchip: bcm7120-l2: Decouple driver from brcmstb-l2 irqchip: bcm7120-l2: Extend driver to support 64+ bit controllers irqchip: bcm7120-l2: Use gc->mask_cache to simplify suspend/resume functions irqchip: bcm7120-l2: Fix missing nibble in gc->unused mask irqchip: bcm7120-l2: Make sure all register accesses use base+offset irqchip: bcm7120-l2, brcmstb-l2: Remove ARM Kconfig dependency irqchip: bcm7120-l2: Eliminate bad IRQ check irqchip: brcmstb-l2: Eliminate dependency on ARM code genirq: Generic chip: Add big endian I/O accessors ...
Diffstat (limited to 'drivers/irqchip/irq-brcmstb-l2.c')
-rw-r--r--drivers/irqchip/irq-brcmstb-l2.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c
index 14691a4cb84c..313c2c64498a 100644
--- a/drivers/irqchip/irq-brcmstb-l2.c
+++ b/drivers/irqchip/irq-brcmstb-l2.c
@@ -18,7 +18,9 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/kconfig.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/spinlock.h>
22#include <linux/of.h> 24#include <linux/of.h>
23#include <linux/of_irq.h> 25#include <linux/of_irq.h>
24#include <linux/of_address.h> 26#include <linux/of_address.h>
@@ -30,8 +32,6 @@
30#include <linux/irqchip.h> 32#include <linux/irqchip.h>
31#include <linux/irqchip/chained_irq.h> 33#include <linux/irqchip/chained_irq.h>
32 34
33#include <asm/mach/irq.h>
34
35#include "irqchip.h" 35#include "irqchip.h"
36 36
37/* Register offsets in the L2 interrupt controller */ 37/* Register offsets in the L2 interrupt controller */
@@ -54,23 +54,26 @@ struct brcmstb_l2_intc_data {
54static void brcmstb_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) 54static void brcmstb_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
55{ 55{
56 struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc); 56 struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc);
57 struct irq_chip_generic *gc = irq_get_domain_generic_chip(b->domain, 0);
57 struct irq_chip *chip = irq_desc_get_chip(desc); 58 struct irq_chip *chip = irq_desc_get_chip(desc);
58 u32 status; 59 u32 status;
59 60
60 chained_irq_enter(chip, desc); 61 chained_irq_enter(chip, desc);
61 62
62 status = __raw_readl(b->base + CPU_STATUS) & 63 status = irq_reg_readl(gc, CPU_STATUS) &
63 ~(__raw_readl(b->base + CPU_MASK_STATUS)); 64 ~(irq_reg_readl(gc, CPU_MASK_STATUS));
64 65
65 if (status == 0) { 66 if (status == 0) {
66 do_bad_IRQ(irq, desc); 67 raw_spin_lock(&desc->lock);
68 handle_bad_irq(irq, desc);
69 raw_spin_unlock(&desc->lock);
67 goto out; 70 goto out;
68 } 71 }
69 72
70 do { 73 do {
71 irq = ffs(status) - 1; 74 irq = ffs(status) - 1;
72 /* ack at our level */ 75 /* ack at our level */
73 __raw_writel(1 << irq, b->base + CPU_CLEAR); 76 irq_reg_writel(gc, 1 << irq, CPU_CLEAR);
74 status &= ~(1 << irq); 77 status &= ~(1 << irq);
75 generic_handle_irq(irq_find_mapping(b->domain, irq)); 78 generic_handle_irq(irq_find_mapping(b->domain, irq));
76 } while (status); 79 } while (status);
@@ -85,12 +88,12 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d)
85 88
86 irq_gc_lock(gc); 89 irq_gc_lock(gc);
87 /* Save the current mask */ 90 /* Save the current mask */
88 b->saved_mask = __raw_readl(b->base + CPU_MASK_STATUS); 91 b->saved_mask = irq_reg_readl(gc, CPU_MASK_STATUS);
89 92
90 if (b->can_wake) { 93 if (b->can_wake) {
91 /* Program the wakeup mask */ 94 /* Program the wakeup mask */
92 __raw_writel(~gc->wake_active, b->base + CPU_MASK_SET); 95 irq_reg_writel(gc, ~gc->wake_active, CPU_MASK_SET);
93 __raw_writel(gc->wake_active, b->base + CPU_MASK_CLEAR); 96 irq_reg_writel(gc, gc->wake_active, CPU_MASK_CLEAR);
94 } 97 }
95 irq_gc_unlock(gc); 98 irq_gc_unlock(gc);
96} 99}
@@ -102,11 +105,11 @@ static void brcmstb_l2_intc_resume(struct irq_data *d)
102 105
103 irq_gc_lock(gc); 106 irq_gc_lock(gc);
104 /* Clear unmasked non-wakeup interrupts */ 107 /* Clear unmasked non-wakeup interrupts */
105 __raw_writel(~b->saved_mask & ~gc->wake_active, b->base + CPU_CLEAR); 108 irq_reg_writel(gc, ~b->saved_mask & ~gc->wake_active, CPU_CLEAR);
106 109
107 /* Restore the saved mask */ 110 /* Restore the saved mask */
108 __raw_writel(b->saved_mask, b->base + CPU_MASK_SET); 111 irq_reg_writel(gc, b->saved_mask, CPU_MASK_SET);
109 __raw_writel(~b->saved_mask, b->base + CPU_MASK_CLEAR); 112 irq_reg_writel(gc, ~b->saved_mask, CPU_MASK_CLEAR);
110 irq_gc_unlock(gc); 113 irq_gc_unlock(gc);
111} 114}
112 115
@@ -118,6 +121,7 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np,
118 struct irq_chip_generic *gc; 121 struct irq_chip_generic *gc;
119 struct irq_chip_type *ct; 122 struct irq_chip_type *ct;
120 int ret; 123 int ret;
124 unsigned int flags;
121 125
122 data = kzalloc(sizeof(*data), GFP_KERNEL); 126 data = kzalloc(sizeof(*data), GFP_KERNEL);
123 if (!data) 127 if (!data)
@@ -131,8 +135,8 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np,
131 } 135 }
132 136
133 /* Disable all interrupts by default */ 137 /* Disable all interrupts by default */
134 __raw_writel(0xffffffff, data->base + CPU_MASK_SET); 138 writel(0xffffffff, data->base + CPU_MASK_SET);
135 __raw_writel(0xffffffff, data->base + CPU_CLEAR); 139 writel(0xffffffff, data->base + CPU_CLEAR);
136 140
137 data->parent_irq = irq_of_parse_and_map(np, 0); 141 data->parent_irq = irq_of_parse_and_map(np, 0);
138 if (!data->parent_irq) { 142 if (!data->parent_irq) {
@@ -148,9 +152,16 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np,
148 goto out_unmap; 152 goto out_unmap;
149 } 153 }
150 154
155 /* MIPS chips strapped for BE will automagically configure the
156 * peripheral registers for CPU-native byte order.
157 */
158 flags = 0;
159 if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
160 flags |= IRQ_GC_BE_IO;
161
151 /* Allocate a single Generic IRQ chip for this node */ 162 /* Allocate a single Generic IRQ chip for this node */
152 ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, 163 ret = irq_alloc_domain_generic_chips(data->domain, 32, 1,
153 np->full_name, handle_edge_irq, clr, 0, 0); 164 np->full_name, handle_edge_irq, clr, 0, flags);
154 if (ret) { 165 if (ret) {
155 pr_err("failed to allocate generic irq chip\n"); 166 pr_err("failed to allocate generic irq chip\n");
156 goto out_free_domain; 167 goto out_free_domain;