[PATCH 3/8] ARM: sirf: move irq driver to drivers/irqchip
Barry Song
21cnbao at gmail.com
Mon Mar 25 05:56:41 EDT 2013
2013/3/25, Arnd Bergmann <arnd at arndb.de>:
> On Monday 25 March 2013, Barry Song wrote:
>> 2013/3/20, Arnd Bergmann <arnd at arndb.de>:
>
>> > +static asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct
>> > pt_regs *regs)
>> > +{
>> > + void __iomem *base = sirfsoc_irqdomain->host_data;
>> > + u32 irqstat, irqnr;
>> > +
>> > + irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID);
>> > + irqnr = irq_find_mapping(sirfsoc_irqdomain, irqstat & 0xff);
>> > +
>> > + handle_IRQ(irqnr, regs);
>> > +}
>> > +
>> > +static void __init sirfsoc_irq_init(struct device_node *np, struct
>> > device_node *parent)
>>
>> this function should be changed from void to int.
>
> Right.
>
>> > +{
>> > + void __iomem *base = of_iomap(np, 0);
>> > + if (!base)
>> > + panic("unable to map intc cpu registers\n");
>> > +
>> > + sirfsoc_irqdomain = irq_domain_add_linear(np, SIRFSOC_NUM_IRQS,
>> > + &irq_domain_simple_ops, base);
>>
>> this breaks the hwirq and irq mapping. the hwirq 0 is mapped to
>> no_irqs, then setup_irq will fail in
>> drivers/clocksource/timer-prima2.c.
>
> Hmm, I don't understand yet what is going on there. This should create
> a domain with all dynamically allocated interrupt descriptors,
> and the hwirq number is just local to the controller then.
suppose we think the hardware register flag bit of timer-prima2 is 0,
irq_of_parse_and_map() will return 16 in patch2 for the timer-prima2
which uses the 1st hardware IRQ in the system.
if add nr_irqs=288 in ATLAS6 machine, irq_of_parse_and_map() will
return 288 in patch2. it looks like the first hw irq will always be
mapped to nr_irqs.
>
> Without patch 2 of the series, this would fail, because that interrupt
> is not mapped, but as far as I can tell, we correctly instantiate
> the domain here, so the irq_of_parse_and_map() in sirfsoc_of_timer_map
> should return a valid interrupt number. Can you check what it returns
> instead? Does it work if you revert to a legacy domain here?
actually patch2 can work without patch3 by irq_domain_add legacy. as
you can see, my old timer-marco.c uses irq_of_parse_and_map() instead
of reading interrupts manually.
the irq mapping works with the following changes:
-------------------------------------------------------------------------
-------------------------------------------------------------------------
arch/arm/mach-prima2/common.c:
DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
/* Maintainer: Barry Song <baohua.song at csr.com> */
.map_io = sirfsoc_map_io,
+ .nr_irqs = 288,
.init_irq = irqchip_init,
.init_time = sirfsoc_init_time,
.init_machine = sirfsoc_mach_init,
-------------------------------------------------------------------------
-------------------------------------------------------------------------
drivers/irqchip/irq-sirfsoc.c:
index 9a6a925..271f905 100644
--- a/drivers/irqchip/irq-sirfsoc.c
+++ b/drivers/irqchip/irq-sirfsoc.c
@@ -54,13 +54,13 @@ static asmlinkage void __exception_irq_entry
sirfsoc_handle_irq(struct pt_regs *
handle_IRQ(irqnr, regs);
}
-static void __init sirfsoc_irq_init(struct device_node *np, struct
device_node *parent)
+static int __init sirfsoc_irq_init(struct device_node *np, struct
device_node *parent)
{
void __iomem *base = of_iomap(np, 0);
if (!base)
panic("unable to map intc cpu registers\n");
- sirfsoc_irqdomain = irq_domain_add_linear(np, SIRFSOC_NUM_IRQS,
+ sirfsoc_irqdomain = irq_domain_add_legacy(np, SIRFSOC_NUM_IRQS, 0, 0,
&irq_domain_simple_ops, base);
sirfsoc_alloc_gc(base, 0, 32);
@@ -73,6 +73,8 @@ static void __init sirfsoc_irq_init(struct
device_node *np, struct device_node *
writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK1);
set_handle_irq(sirfsoc_handle_irq);
+
+ return 0;
}
IRQCHIP_DECLARE(sirfsoc_intc, "sirf,prima2-intc", sirfsoc_irq_init);
-------------------------------------------------------------------------
-------------------------------------------------------------------------
drivers/pinctrl/pinctrl-sirf.c:
- bank->domain = irq_domain_add_linear(np,
SIRFSOC_GPIO_BANK_SIZE,
+ bank->domain = irq_domain_add_legacy(np,
SIRFSOC_GPIO_BANK_SIZE,
+ 128 + i * SIRFSOC_GPIO_BANK_SIZE, 0,
&sirfsoc_gpio_irq_simple_ops, bank);
@@ -65,13 +74,14 @@ MACHINE_END
-barry
More information about the linux-arm-kernel
mailing list