aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-06-19 17:34:43 -0400
committerJason Cooper <jason@lakedaemon.net>2014-06-24 08:38:35 -0400
commitf07e42f96f06dca3f9f897b956d83aec165ee693 (patch)
tree60c37edb4983083d92dc0bf2d002813755272af1 /drivers/irqchip
parentfe64ac89cf8f5067cf7f6757b6cd9fd77c527bdf (diff)
irqchip: spear_shirq: Use proper irq chips for the different SoCs
Only spear300 has an actual mask register for the RAS interrupts. Add an irq chip pointer to the shirq struct and initialize spear300 with the actual implementation and the others with dummy_irq_chip. The disabled RAS3 block has no irq chip assigned, so we can check for this and remove the disabled member. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20140619212713.831341023@linutronix.de Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/spear-shirq.c97
1 files changed, 45 insertions, 52 deletions
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 8765aa7f7a15..169ef9a385d0 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -49,7 +49,8 @@ struct shirq_regs {
49 * virq_base: Base virtual interrupt number 49 * virq_base: Base virtual interrupt number
50 * nr_irqs: Number of interrupts handled by this block 50 * nr_irqs: Number of interrupts handled by this block
51 * offset: Bit offset of the first interrupt 51 * offset: Bit offset of the first interrupt
52 * disabled: Group is disabled, but accounted 52 * irq_chip: Interrupt controller chip used for this instance,
53 * if NULL group is disabled, but accounted
53 */ 54 */
54struct spear_shirq { 55struct spear_shirq {
55 void __iomem *base; 56 void __iomem *base;
@@ -58,19 +59,50 @@ struct spear_shirq {
58 u32 virq_base; 59 u32 virq_base;
59 u32 nr_irqs; 60 u32 nr_irqs;
60 u32 offset; 61 u32 offset;
61 bool disabled; 62 struct irq_chip *irq_chip;
62}; 63};
63 64
64static DEFINE_SPINLOCK(lock);
65
66/* spear300 shared irq registers offsets and masks */ 65/* spear300 shared irq registers offsets and masks */
67#define SPEAR300_INT_ENB_MASK_REG 0x54 66#define SPEAR300_INT_ENB_MASK_REG 0x54
68#define SPEAR300_INT_STS_MASK_REG 0x58 67#define SPEAR300_INT_STS_MASK_REG 0x58
69 68
69static DEFINE_RAW_SPINLOCK(shirq_lock);
70
71static void shirq_irq_mask(struct irq_data *d)
72{
73 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
74 u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
75 u32 __iomem *reg = shirq->base + shirq->regs.enb_reg;
76
77 raw_spin_lock(&shirq_lock);
78 val = readl(reg) & ~(0x1 << shift);
79 writel(val, reg);
80 raw_spin_unlock(&shirq_lock);
81}
82
83static void shirq_irq_unmask(struct irq_data *d)
84{
85 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
86 u32 val, shift = d->irq - shirq->virq_base + shirq->offset;
87 u32 __iomem *reg = shirq->base + shirq->regs.enb_reg;
88
89 raw_spin_lock(&shirq_lock);
90 val = readl(reg) | (0x1 << shift);
91 writel(val, reg);
92 raw_spin_unlock(&shirq_lock);
93}
94
95static struct irq_chip shirq_chip = {
96 .name = "spear-shirq",
97 .irq_mask = shirq_irq_mask,
98 .irq_unmask = shirq_irq_unmask,
99};
100
70static struct spear_shirq spear300_shirq_ras1 = { 101static struct spear_shirq spear300_shirq_ras1 = {
71 .offset = 0, 102 .offset = 0,
72 .nr_irqs = 9, 103 .nr_irqs = 9,
73 .mask = ((0x1 << 9) - 1) << 0, 104 .mask = ((0x1 << 9) - 1) << 0,
105 .irq_chip = &shirq_chip,
74 .regs = { 106 .regs = {
75 .enb_reg = SPEAR300_INT_ENB_MASK_REG, 107 .enb_reg = SPEAR300_INT_ENB_MASK_REG,
76 .status_reg = SPEAR300_INT_STS_MASK_REG, 108 .status_reg = SPEAR300_INT_STS_MASK_REG,
@@ -88,8 +120,8 @@ static struct spear_shirq spear310_shirq_ras1 = {
88 .offset = 0, 120 .offset = 0,
89 .nr_irqs = 8, 121 .nr_irqs = 8,
90 .mask = ((0x1 << 8) - 1) << 0, 122 .mask = ((0x1 << 8) - 1) << 0,
123 .irq_chip = &dummy_irq_chip,
91 .regs = { 124 .regs = {
92 .enb_reg = -1,
93 .status_reg = SPEAR310_INT_STS_MASK_REG, 125 .status_reg = SPEAR310_INT_STS_MASK_REG,
94 }, 126 },
95}; 127};
@@ -98,6 +130,7 @@ static struct spear_shirq spear310_shirq_ras2 = {
98 .offset = 8, 130 .offset = 8,
99 .nr_irqs = 5, 131 .nr_irqs = 5,
100 .mask = ((0x1 << 5) - 1) << 8, 132 .mask = ((0x1 << 5) - 1) << 8,
133 .irq_chip = &dummy_irq_chip,
101 .regs = { 134 .regs = {
102 .enb_reg = -1, 135 .enb_reg = -1,
103 .status_reg = SPEAR310_INT_STS_MASK_REG, 136 .status_reg = SPEAR310_INT_STS_MASK_REG,
@@ -108,8 +141,8 @@ static struct spear_shirq spear310_shirq_ras3 = {
108 .offset = 13, 141 .offset = 13,
109 .nr_irqs = 1, 142 .nr_irqs = 1,
110 .mask = ((0x1 << 1) - 1) << 13, 143 .mask = ((0x1 << 1) - 1) << 13,
144 .irq_chip = &dummy_irq_chip,
111 .regs = { 145 .regs = {
112 .enb_reg = -1,
113 .status_reg = SPEAR310_INT_STS_MASK_REG, 146 .status_reg = SPEAR310_INT_STS_MASK_REG,
114 }, 147 },
115}; 148};
@@ -118,8 +151,8 @@ static struct spear_shirq spear310_shirq_intrcomm_ras = {
118 .offset = 14, 151 .offset = 14,
119 .nr_irqs = 3, 152 .nr_irqs = 3,
120 .mask = ((0x1 << 3) - 1) << 14, 153 .mask = ((0x1 << 3) - 1) << 14,
154 .irq_chip = &dummy_irq_chip,
121 .regs = { 155 .regs = {
122 .enb_reg = -1,
123 .status_reg = SPEAR310_INT_STS_MASK_REG, 156 .status_reg = SPEAR310_INT_STS_MASK_REG,
124 }, 157 },
125}; 158};
@@ -140,15 +173,14 @@ static struct spear_shirq spear320_shirq_ras3 = {
140 .offset = 0, 173 .offset = 0,
141 .nr_irqs = 7, 174 .nr_irqs = 7,
142 .mask = ((0x1 << 7) - 1) << 0, 175 .mask = ((0x1 << 7) - 1) << 0,
143 .disabled = 1,
144}; 176};
145 177
146static struct spear_shirq spear320_shirq_ras1 = { 178static struct spear_shirq spear320_shirq_ras1 = {
147 .offset = 7, 179 .offset = 7,
148 .nr_irqs = 3, 180 .nr_irqs = 3,
149 .mask = ((0x1 << 3) - 1) << 7, 181 .mask = ((0x1 << 3) - 1) << 7,
182 .irq_chip = &dummy_irq_chip,
150 .regs = { 183 .regs = {
151 .enb_reg = -1,
152 .status_reg = SPEAR320_INT_STS_MASK_REG, 184 .status_reg = SPEAR320_INT_STS_MASK_REG,
153 }, 185 },
154}; 186};
@@ -157,8 +189,8 @@ static struct spear_shirq spear320_shirq_ras2 = {
157 .offset = 10, 189 .offset = 10,
158 .nr_irqs = 1, 190 .nr_irqs = 1,
159 .mask = ((0x1 << 1) - 1) << 10, 191 .mask = ((0x1 << 1) - 1) << 10,
192 .irq_chip = &dummy_irq_chip,
160 .regs = { 193 .regs = {
161 .enb_reg = -1,
162 .status_reg = SPEAR320_INT_STS_MASK_REG, 194 .status_reg = SPEAR320_INT_STS_MASK_REG,
163 }, 195 },
164}; 196};
@@ -167,8 +199,8 @@ static struct spear_shirq spear320_shirq_intrcomm_ras = {
167 .offset = 11, 199 .offset = 11,
168 .nr_irqs = 11, 200 .nr_irqs = 11,
169 .mask = ((0x1 << 11) - 1) << 11, 201 .mask = ((0x1 << 11) - 1) << 11,
202 .irq_chip = &dummy_irq_chip,
170 .regs = { 203 .regs = {
171 .enb_reg = -1,
172 .status_reg = SPEAR320_INT_STS_MASK_REG, 204 .status_reg = SPEAR320_INT_STS_MASK_REG,
173 }, 205 },
174}; 206};
@@ -180,45 +212,6 @@ static struct spear_shirq *spear320_shirq_blocks[] = {
180 &spear320_shirq_intrcomm_ras, 212 &spear320_shirq_intrcomm_ras,
181}; 213};
182 214
183static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
184{
185 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
186 u32 val, offset = d->irq - shirq->virq_base;
187 unsigned long flags;
188
189 if (shirq->regs.enb_reg == -1)
190 return;
191
192 spin_lock_irqsave(&lock, flags);
193 val = readl(shirq->base + shirq->regs.enb_reg);
194
195 if (mask ^ shirq->regs.reset_to_enb)
196 val &= ~(0x1 << shirq->offset << offset);
197 else
198 val |= 0x1 << shirq->offset << offset;
199
200 writel(val, shirq->base + shirq->regs.enb_reg);
201 spin_unlock_irqrestore(&lock, flags);
202
203}
204
205static void shirq_irq_mask(struct irq_data *d)
206{
207 shirq_irq_mask_unmask(d, 1);
208}
209
210static void shirq_irq_unmask(struct irq_data *d)
211{
212 shirq_irq_mask_unmask(d, 0);
213}
214
215static struct irq_chip shirq_chip = {
216 .name = "spear-shirq",
217 .irq_ack = shirq_irq_mask,
218 .irq_mask = shirq_irq_mask,
219 .irq_unmask = shirq_irq_unmask,
220};
221
222static void shirq_handler(unsigned irq, struct irq_desc *desc) 215static void shirq_handler(unsigned irq, struct irq_desc *desc)
223{ 216{
224 struct spear_shirq *shirq = irq_get_handler_data(irq); 217 struct spear_shirq *shirq = irq_get_handler_data(irq);
@@ -240,7 +233,7 @@ static void __init spear_shirq_register(struct spear_shirq *shirq,
240{ 233{
241 int i; 234 int i;
242 235
243 if (shirq->disabled) 236 if (!shirq->irq_chip)
244 return; 237 return;
245 238
246 irq_set_chained_handler(parent_irq, shirq_handler); 239 irq_set_chained_handler(parent_irq, shirq_handler);
@@ -248,7 +241,7 @@ static void __init spear_shirq_register(struct spear_shirq *shirq,
248 241
249 for (i = 0; i < shirq->nr_irqs; i++) { 242 for (i = 0; i < shirq->nr_irqs; i++) {
250 irq_set_chip_and_handler(shirq->virq_base + i, 243 irq_set_chip_and_handler(shirq->virq_base + i,
251 &shirq_chip, handle_simple_irq); 244 shirq->irq_chip, handle_simple_irq);
252 set_irq_flags(shirq->virq_base + i, IRQF_VALID); 245 set_irq_flags(shirq->virq_base + i, IRQF_VALID);
253 irq_set_chip_data(shirq->virq_base + i, shirq); 246 irq_set_chip_data(shirq->virq_base + i, shirq);
254 } 247 }