Merge common code between PowerPC and Microblaze. Also create a new arch hook, of_irq_find_parent_by_phandle() to handle arch-specific quirks.
Signed-off-by: Grant Likely <grant.lik...@secretlab.ca> CC: Michal Simek <mon...@monstr.eu> CC: Benjamin Herrenschmidt <b...@kernel.crashing.org> CC: Stephen Rothwell <s...@canb.auug.org.au> CC: microblaze-ucli...@itee.uq.edu.au CC: linuxppc-dev@lists.ozlabs.org CC: devicetree-disc...@lists.ozlabs.org --- arch/microblaze/kernel/prom_parse.c | 22 +++------------------- arch/powerpc/kernel/prom_parse.c | 30 +++++------------------------- drivers/of/irq.c | 28 ++++++++++++++++++++++++++++ include/linux/of_irq.h | 2 ++ 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c index af1b2a7..946f14d 100644 --- a/arch/microblaze/kernel/prom_parse.c +++ b/arch/microblaze/kernel/prom_parse.c @@ -648,25 +648,9 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, * Interrupt remapper */ -static struct device_node *of_irq_find_parent(struct device_node *child) +struct device_node *of_irq_find_parent_by_phandle(phandle p) { - struct device_node *p; - const phandle *parp; - - if (!of_node_get(child)) - return NULL; - - do { - parp = of_get_property(child, "interrupt-parent", NULL); - if (parp == NULL) - p = of_get_parent(child); - else - p = of_find_node_by_phandle(*parp); - of_node_put(child); - child = p; - } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); - - return p; + return of_find_node_by_phandle(p); } int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, @@ -783,7 +767,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); /* Get the interrupt parent */ - newpar = of_find_node_by_phandle((phandle)*imap); + newpar = of_irq_find_parent_by_phandle((phandle)*imap); imap++; --imaplen; diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 8362620..39e977d 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -685,29 +685,12 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, static unsigned int of_irq_workarounds; static struct device_node *of_irq_dflt_pic; -static struct device_node *of_irq_find_parent(struct device_node *child) +struct device_node *of_irq_find_parent_by_phandle(phandle p) { - struct device_node *p; - const phandle *parp; - - if (!of_node_get(child)) - return NULL; - - do { - parp = of_get_property(child, "interrupt-parent", NULL); - if (parp == NULL) - p = of_get_parent(child); - else { - if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) - p = of_node_get(of_irq_dflt_pic); - else - p = of_find_node_by_phandle(*parp); - } - of_node_put(child); - child = p; - } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + return of_node_get(of_irq_dflt_pic); - return p; + return of_find_node_by_phandle(p); } /* This doesn't need to be called if you don't have any special workaround @@ -859,10 +842,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, DBG(" -> match=%d (imaplen=%d)\n", match, imaplen); /* Get the interrupt parent */ - if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) - newpar = of_node_get(of_irq_dflt_pic); - else - newpar = of_find_node_by_phandle((phandle)*imap); + newpar = of_irq_find_parent_by_phandle((phandle)*imap); imap++; --imaplen; diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 56ad1aa..ad569ca 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -24,6 +24,34 @@ #include <linux/of_irq.h> #include <linux/string.h> +/** + * of_irq_find_parent - Given a device node, find its interrupt parent node + * @child: pointer to device node + * + * Returns a pointer to the interrupt parent node, or NULL if the interrupt + * parent could not be determined. + */ +struct device_node *of_irq_find_parent(struct device_node *child) +{ + struct device_node *p; + const phandle *parp; + + if (!of_node_get(child)) + return NULL; + + do { + parp = of_get_property(child, "interrupt-parent", NULL); + if (parp == NULL) + p = of_get_parent(child); + else + p = of_irq_find_parent_by_phandle(*parp); + of_node_put(child); + child = p; + } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); + + return p; +} + unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { struct of_irq oirq; diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index 0e37c05..f98b27b 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -30,6 +30,8 @@ struct of_irq { u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */ }; +extern struct device_node *of_irq_find_parent_by_phandle(phandle p); +extern struct device_node *of_irq_find_parent(struct device_node *child); extern int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq); extern unsigned int irq_create_of_mapping(struct device_node *controller, _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev