Skip to content

Commit d6cf30c

Browse files
committed
ARM: pxa: fix pxa interrupts handling in DT
The commit "ARM: pxa: arbitrarily set first interrupt number" changed the first pxa interrupt to 16. As a consequence, device-tree builds got broken, because : - pxa_mask_irq() and pxa_unmask_irq() are using IRQ_BIT() - IRQ_BIT(x) calculates the interrupts as : x - PXA_IRQ(0) Before the commit, the first interrupt shift, PXA_IRQ(0) was 0, therefore IRQ_BIT(x) was x. After the change, it is necessary that the same shift of 16 is applied between the virtual interrupt number and the hardware irq number. This situation comes from the common irq_chip shared between legacy platform builds and device-tree builds. Fix the broken interrupts in DT case by adding this shift in the DT case too. As a consequence of the IRQ_BIT() is removed alltogether from interrupts handling, even in the platform data types of platforms : - a legacy irq domain is used - the irq_chip handles hardware interrupts - the virtual to hardware interrupt conversion is fully handled by irq domain mechanics Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
1 parent 5c0c75d commit d6cf30c

File tree

2 files changed

+49
-63
lines changed

2 files changed

+49
-63
lines changed

arch/arm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ config ARCH_PXA
619619
select GENERIC_CLOCKEVENTS
620620
select GPIO_PXA
621621
select HAVE_IDE
622+
select IRQ_DOMAIN
622623
select MULTI_IRQ_HANDLER
623624
select PLAT_PXA
624625
select SPARSE_IRQ

arch/arm/mach-pxa/irq.c

Lines changed: 48 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* it under the terms of the GNU General Public License version 2 as
1212
* published by the Free Software Foundation.
1313
*/
14+
#include <linux/bitops.h>
1415
#include <linux/init.h>
1516
#include <linux/module.h>
1617
#include <linux/interrupt.h>
@@ -40,7 +41,6 @@
4041
#define ICHP_VAL_IRQ (1 << 31)
4142
#define ICHP_IRQ(i) (((i) >> 16) & 0x7fff)
4243
#define IPR_VALID (1 << 31)
43-
#define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
4444

4545
#define MAX_INTERNAL_IRQS 128
4646

@@ -51,6 +51,7 @@
5151
static void __iomem *pxa_irq_base;
5252
static int pxa_internal_irq_nr;
5353
static bool cpu_has_ipr;
54+
static struct irq_domain *pxa_irq_domain;
5455

5556
static inline void __iomem *irq_base(int i)
5657
{
@@ -66,18 +67,20 @@ static inline void __iomem *irq_base(int i)
6667
void pxa_mask_irq(struct irq_data *d)
6768
{
6869
void __iomem *base = irq_data_get_irq_chip_data(d);
70+
irq_hw_number_t irq = irqd_to_hwirq(d);
6971
uint32_t icmr = __raw_readl(base + ICMR);
7072

71-
icmr &= ~(1 << IRQ_BIT(d->irq));
73+
icmr &= ~BIT(irq & 0x1f);
7274
__raw_writel(icmr, base + ICMR);
7375
}
7476

7577
void pxa_unmask_irq(struct irq_data *d)
7678
{
7779
void __iomem *base = irq_data_get_irq_chip_data(d);
80+
irq_hw_number_t irq = irqd_to_hwirq(d);
7881
uint32_t icmr = __raw_readl(base + ICMR);
7982

80-
icmr |= 1 << IRQ_BIT(d->irq);
83+
icmr |= BIT(irq & 0x1f);
8184
__raw_writel(icmr, base + ICMR);
8285
}
8386

@@ -118,40 +121,63 @@ asmlinkage void __exception_irq_entry ichp_handle_irq(struct pt_regs *regs)
118121
} while (1);
119122
}
120123

121-
void __init pxa_init_irq(int irq_nr, int (*fn)(struct irq_data *, unsigned int))
124+
static int pxa_irq_map(struct irq_domain *h, unsigned int virq,
125+
irq_hw_number_t hw)
122126
{
123-
int irq, i, n;
127+
void __iomem *base = irq_base(hw / 32);
124128

125-
BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
129+
/* initialize interrupt priority */
130+
if (cpu_has_ipr)
131+
__raw_writel(hw | IPR_VALID, pxa_irq_base + IPR(hw));
132+
133+
irq_set_chip_and_handler(virq, &pxa_internal_irq_chip,
134+
handle_level_irq);
135+
irq_set_chip_data(virq, base);
136+
set_irq_flags(virq, IRQF_VALID);
137+
138+
return 0;
139+
}
140+
141+
static struct irq_domain_ops pxa_irq_ops = {
142+
.map = pxa_irq_map,
143+
.xlate = irq_domain_xlate_onecell,
144+
};
145+
146+
static __init void
147+
pxa_init_irq_common(struct device_node *node, int irq_nr,
148+
int (*fn)(struct irq_data *, unsigned int))
149+
{
150+
int n;
126151

127152
pxa_internal_irq_nr = irq_nr;
128-
cpu_has_ipr = !cpu_is_pxa25x();
129-
pxa_irq_base = io_p2v(0x40d00000);
153+
pxa_irq_domain = irq_domain_add_legacy(node, irq_nr,
154+
PXA_IRQ(0), 0,
155+
&pxa_irq_ops, NULL);
156+
if (!pxa_irq_domain)
157+
panic("Unable to add PXA IRQ domain\n");
158+
irq_set_default_host(pxa_irq_domain);
130159

131160
for (n = 0; n < irq_nr; n += 32) {
132161
void __iomem *base = irq_base(n >> 5);
133162

134163
__raw_writel(0, base + ICMR); /* disable all IRQs */
135164
__raw_writel(0, base + ICLR); /* all IRQs are IRQ, not FIQ */
136-
for (i = n; (i < (n + 32)) && (i < irq_nr); i++) {
137-
/* initialize interrupt priority */
138-
if (cpu_has_ipr)
139-
__raw_writel(i | IPR_VALID, pxa_irq_base + IPR(i));
140-
141-
irq = PXA_IRQ(i);
142-
irq_set_chip_and_handler(irq, &pxa_internal_irq_chip,
143-
handle_level_irq);
144-
irq_set_chip_data(irq, base);
145-
set_irq_flags(irq, IRQF_VALID);
146-
}
147165
}
148-
149166
/* only unmasked interrupts kick us out of idle */
150167
__raw_writel(1, irq_base(0) + ICCR);
151168

152169
pxa_internal_irq_chip.irq_set_wake = fn;
153170
}
154171

172+
void __init pxa_init_irq(int irq_nr, int (*fn)(struct irq_data *, unsigned int))
173+
{
174+
BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
175+
176+
pxa_irq_base = io_p2v(0x40d00000);
177+
cpu_has_ipr = !cpu_is_pxa25x();
178+
pxa_init_irq_common(NULL, irq_nr, fn);
179+
}
180+
155181
#ifdef CONFIG_PM
156182
static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32];
157183
static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
@@ -203,30 +229,6 @@ struct syscore_ops pxa_irq_syscore_ops = {
203229
};
204230

205231
#ifdef CONFIG_OF
206-
static struct irq_domain *pxa_irq_domain;
207-
208-
static int pxa_irq_map(struct irq_domain *h, unsigned int virq,
209-
irq_hw_number_t hw)
210-
{
211-
void __iomem *base = irq_base(hw / 32);
212-
213-
/* initialize interrupt priority */
214-
if (cpu_has_ipr)
215-
__raw_writel(hw | IPR_VALID, pxa_irq_base + IPR(hw));
216-
217-
irq_set_chip_and_handler(hw, &pxa_internal_irq_chip,
218-
handle_level_irq);
219-
irq_set_chip_data(hw, base);
220-
set_irq_flags(hw, IRQF_VALID);
221-
222-
return 0;
223-
}
224-
225-
static struct irq_domain_ops pxa_irq_ops = {
226-
.map = pxa_irq_map,
227-
.xlate = irq_domain_xlate_onecell,
228-
};
229-
230232
static const struct of_device_id intc_ids[] __initconst = {
231233
{ .compatible = "marvell,pxa-intc", },
232234
{}
@@ -236,7 +238,7 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
236238
{
237239
struct device_node *node;
238240
struct resource res;
239-
int n, ret;
241+
int ret;
240242

241243
node = of_find_matching_node(NULL, intc_ids);
242244
if (!node) {
@@ -267,23 +269,6 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
267269
return;
268270
}
269271

270-
pxa_irq_domain = irq_domain_add_legacy(node, pxa_internal_irq_nr, 0, 0,
271-
&pxa_irq_ops, NULL);
272-
if (!pxa_irq_domain)
273-
panic("Unable to add PXA IRQ domain\n");
274-
275-
irq_set_default_host(pxa_irq_domain);
276-
277-
for (n = 0; n < pxa_internal_irq_nr; n += 32) {
278-
void __iomem *base = irq_base(n >> 5);
279-
280-
__raw_writel(0, base + ICMR); /* disable all IRQs */
281-
__raw_writel(0, base + ICLR); /* all IRQs are IRQ, not FIQ */
282-
}
283-
284-
/* only unmasked interrupts kick us out of idle */
285-
__raw_writel(1, irq_base(0) + ICCR);
286-
287-
pxa_internal_irq_chip.irq_set_wake = fn;
272+
pxa_init_irq_common(node, pxa_internal_irq_nr, fn);
288273
}
289274
#endif /* CONFIG_OF */

0 commit comments

Comments
 (0)