Consolidate OF IRQ handling code
Subsystems (5)
v2 cover Consolidate OF IRQ handling code
This series merges the common IRQ handling code between Microblaze and Powerpc
Changes in v2:
- The 3 patches to merge of_irq_find_parent(), of_irq_map_raw() and of_irq_map_one() have been merged into a single patch.
- Patch added to move powermac quirk handing into arch/powerpc/platforms/powermac.
- Add endian fixes patch from Rob Herring
Ben, please take a look and let me know if you like this better.
Thanks,
g.
---
Grant Likely (4):
of/irq: Move irq_of_parse_and_map() to common code of/microblaze: strip out of_irq_workarounds code of/powerpc: Move Powermac irq quirk code into powermac pic driver code of/irq: merge irq mapping code
Rob Herring (1):
of/irq: little endian fixes
arch/microblaze/include/asm/irq.h | 13 - arch/microblaze/include/asm/prom.h | 67 ------ arch/microblaze/kernel/irq.c | 14 - arch/microblaze/kernel/prom_parse.c | 331 ------------------------------- arch/powerpc/include/asm/irq.h | 13 - arch/powerpc/include/asm/prom.h | 68 ------ arch/powerpc/kernel/irq.c | 14 - arch/powerpc/kernel/prom_parse.c | 351 --------------------------------- arch/powerpc/platforms/powermac/pic.c | 72 ++++++- arch/sparc/include/asm/prom.h | 1 drivers/of/Kconfig | 4 drivers/of/Makefile | 1 drivers/of/irq.c | 339 ++++++++++++++++++++++++++++++++ drivers/of/of_mdio.c | 1 include/linux/of_irq.h | 70 +++++++ 15 files changed, 487 insertions(+), 872 deletions(-) create mode 100644 drivers/of/irq.c create mode 100644 include/linux/of_irq.h
PATCH v2 1/5 of/irq: Move irq_of_parse_and_map() to common code
Merge common code between PowerPC and Microblaze. SPARC implements irq_of_parse_and_map(), but the implementation is different, so it does not use this code.
--- arch/microblaze/include/asm/irq.h | 13 ----------- arch/microblaze/include/asm/prom.h | 26 +---------------------- arch/microblaze/kernel/irq.c | 14 ++---------- arch/powerpc/include/asm/irq.h | 13 ----------- arch/powerpc/include/asm/prom.h | 27 +----------------------- arch/powerpc/kernel/irq.c | 14 ++---------- arch/sparc/include/asm/prom.h | 1 - drivers/of/Kconfig | 4 ++++ drivers/of/Makefile | 1 + drivers/of/irq.c | 37 ++++++++++++++++++++++++++++++++ drivers/of/of_mdio.c | 1 + include/linux/of_irq.h | 41 ++++++++++++++++++++++++++++++++++++ 12 files changed, 90 insertions(+), 102 deletions(-) create mode 100644 drivers/of/irq.c create mode 100644 include/linux/of_irq.h
arch/microblaze/include/asm/irq.h +0 -13
@@ -62,17 +62,4 @@ struct irq_host;extern unsigned int irq_create_mapping (struct irq_host *host,irq_hw_number_t hwirq); -/** -* irq_create_of_mapping - Map a hardware interrupt into linux virq space -* @controller: Device node of the interrupt controller -* @inspec: Interrupt specifier from the device-tree -* @intsize: Size of the interrupt specifier from the device-tree -* -* This function is identical to irq_create_mapping except that it takes -* as input informations straight from the device-tree (typically the results -* of the of_irq_map_*() functions. -*/ -extern unsigned int irq_create_of_mapping (struct device_node *controller, -u32 *intspec,unsigned int intsize); -#endif /* _ASM_MICROBLAZE_IRQ_H */
arch/microblaze/include/asm/prom.h +1 -25
@@ -20,6 +20,7 @@#ifndef __ASSEMBLY__#include <linux/types.h> +#include <linux/of_irq.h> #include <linux/of_fdt.h> #include <linux/proc_fs.h> #include <linux/platform_device.h>
@@ -92,18 +93,6 @@ extern const void *of_get_mac_address(struct device_node *np);* OF interrupt mapping */ -/* This structure is returned when an interrupt is mapped. The controller -* field needs to be put() after use -*/ - -#define OF_MAX_IRQ_SPEC 4/* We handle specifiers of at most 4 cells */ - -struct of_irq { -struct device_node *controller;/* Interrupt controller node */ -u32 size;/* Specifier size */ -u32 specifier[OF_MAX_IRQ_SPEC ];/* Specifier copy */ -}; -/** * of_irq_map_init - Initialize the irq remapper * @flags: flags defining workarounds to enable
@@ -139,19 +128,6 @@ extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, struct of_irq *out_irq);/** -* of_irq_map_one - Resolve an interrupt for a device -* @device: the device whose interrupt is to be resolved -* @index: index of the interrupt to resolve -* @out_irq: structure of_irq filled by this function -* -* This function resolves an interrupt, walking the tree, for a given -* device-tree node. It's the high level pendant to of_irq_map_raw(). -* It also implements the workarounds for OldWolrd Macs. -*/ -extern int of_irq_map_one (struct device_node *device,int index, -struct of_irq *out_irq); - -/** * of_irq_map_pci - Resolve the interrupt for a PCI device * @pdev: the device whose interrupt is to be resolved * @out_irq: structure of_irq filled by this function
arch/microblaze/kernel/irq.c +2 -12
@@ -17,20 +17,10 @@#include <linux/seq_file.h> #include <linux/kernel_stat.h> #include <linux/irq.h> +#include <linux/of_irq.h> #include <asm/prom.h> -unsigned int irq_of_parse_and_map (struct device_node *dev,int index) -{ -struct of_irq oirq; - -if (of_irq_map_one (dev, index, &oirq)) -return NO_IRQ ; - -return oirq.specifier[0 ]; -} -EXPORT_SYMBOL_GPL (irq_of_parse_and_map); -static u32 concurrent_irq; void __irq_entry do_IRQ(struct pt_regs *regs)
@@ -104,7 +94,7 @@ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)EXPORT_SYMBOL_GPL (irq_create_mapping);unsigned int irq_create_of_mapping (struct device_node *controller, -u32 *intspec,unsigned int intsize) +const u32 *intspec,unsigned int intsize) {return intspec[0 ]; }
arch/powerpc/include/asm/irq.h +0 -13
@@ -304,19 +304,6 @@ extern void irq_free_virt(unsigned int virq, unsigned int count);/* -- OF helpers -- */ /** -* irq_create_of_mapping - Map a hardware interrupt into linux virq space -* @controller: Device node of the interrupt controller -* @inspec: Interrupt specifier from the device-tree -* @intsize: Size of the interrupt specifier from the device-tree -* -* This function is identical to irq_create_mapping except that it takes -* as input informations straight from the device-tree (typically the results -* of the of_irq_map_*() functions. -*/ -extern unsigned int irq_create_of_mapping (struct device_node *controller, -const u32 *intspec,unsigned int intsize); - -/** * irq_of_parse_and_map - Parse and Map an interrupt into linux virq space * @device: Device node of the device whose interrupt is to be mapped * @index: Index of the interrupt to map
arch/powerpc/include/asm/prom.h +1 -26
@@ -18,6 +18,7 @@*/ #include <linux/types.h> #include <linux/of_fdt.h> +#include <linux/of_irq.h> #include <linux/proc_fs.h> #include <linux/platform_device.h> #include <asm/irq.h>
@@ -108,18 +109,6 @@ extern const void *of_get_mac_address(struct device_node *np);* OF interrupt mapping */ -/* This structure is returned when an interrupt is mapped. The controller -* field needs to be put() after use -*/ - -#define OF_MAX_IRQ_SPEC 4/* We handle specifiers of at most 4 cells */ - -struct of_irq { -struct device_node *controller;/* Interrupt controller node */ -u32 size;/* Specifier size */ -u32 specifier[OF_MAX_IRQ_SPEC ];/* Specifier copy */ -}; -/** * of_irq_map_init - Initialize the irq remapper * @flags: flags defining workarounds to enable
@@ -154,20 +143,6 @@ extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, const u32 *addr, struct of_irq *out_irq); - -/** -* of_irq_map_one - Resolve an interrupt for a device -* @device: the device whose interrupt is to be resolved -* @index: index of the interrupt to resolve -* @out_irq: structure of_irq filled by this function -* -* This function resolves an interrupt, walking the tree, for a given -* device-tree node. It's the high level pendant to of_irq_map_raw(). -* It also implements the workarounds for OldWolrd Macs. -*/ -extern int of_irq_map_one (struct device_node *device,int index, -struct of_irq *out_irq); -/** * of_irq_map_pci - Resolve the interrupt for a PCI device * @pdev: the device whose interrupt is to be resolved
arch/powerpc/kernel/irq.c +2 -12
@@ -53,6 +53,8 @@#include <linux/bootmem.h> #include <linux/pci.h> #include <linux/debugfs.h> +#include <linux/of.h> +#include <linux/of_irq.h> #include <asm/uaccess.h> #include <asm/system.h>
@@ -813,18 +815,6 @@ unsigned int irq_create_of_mapping(struct device_node *controller, }EXPORT_SYMBOL_GPL (irq_create_of_mapping); -unsigned int irq_of_parse_and_map (struct device_node *dev,int index) -{ -struct of_irq oirq; - -if (of_irq_map_one (dev, index, &oirq)) -return NO_IRQ ; - -return irq_create_of_mapping (oirq.controller, oirq.specifier, - oirq.size); -} -EXPORT_SYMBOL_GPL (irq_of_parse_and_map); -void irq_dispose_mapping (unsigned int virq) {struct irq_host *host;
arch/sparc/include/asm/prom.h +0 -1
@@ -56,7 +56,6 @@ extern void of_fill_in_cpu_data(void);* register them in the of_device objects, whereas powerpc computes them * on request. */ -extern unsigned int irq_of_parse_and_map (struct device_node *node,int index);static inline void irq_dispose_mapping (unsigned int virq) { }
drivers/of/Kconfig +4 -0
@@ -6,6 +6,10 @@ config OF_DYNAMIC def_bool y depends on OF && PPC_OF +config OF_IRQ + def_bool y + depends on OF && !SPARC + config OF_DEVICE def_bool y depends on OF && (SPARC || PPC_OF || MICROBLAZE)
drivers/of/Makefile +1 -0
@@ -1,5 +1,6 @@ obj-y = base.o obj-$(CONFIG_OF_FLATTREE) += fdt.o +obj-$(CONFIG_OF_IRQ) += irq.o obj-$(CONFIG_OF_DEVICE) += device.o platform.o obj-$(CONFIG_OF_GPIO) += gpio.o obj-$(CONFIG_OF_I2C) += of_i2c.o
drivers/of/irq.c new file +37 -0
@@ -0,0 +1,37 @@ +/* +* Derived from arch/i386/kernel/irq.c +* Copyright (C) 1992 Linus Torvalds +* Adapted from arch/i386 by Gary Thomas +* Copyright (C) 1995-1996 Gary Thomas ([email protected]) +* Updated and modified by Cort Dougan <[email protected]> +* Copyright (C) 1996-2001 Cort Dougan +* Adapted for Power Macintosh by Paul Mackerras +* Copyright (C) 1996 Paul Mackerras ([email protected]) +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version +* 2 of the License, or (at your option) any later version. +* +* This file contains the code used to make IRQ descriptions in the +* device tree to actual irq numbers on an interrupt controller +* driver. +*/ + +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/string.h> + +unsigned int irq_of_parse_and_map (struct device_node *dev,int index) +{ +struct of_irq oirq; + +if (of_irq_map_one (dev, index, &oirq)) +return NO_IRQ ; + +return irq_create_of_mapping (oirq.controller, oirq.specifier, + oirq.size); +} +EXPORT_SYMBOL_GPL (irq_of_parse_and_map);
drivers/of/of_mdio.c +1 -0
@@ -15,6 +15,7 @@#include <linux/err.h> #include <linux/phy.h> #include <linux/of.h> +#include <linux/of_irq.h> #include <linux/of_mdio.h> #include <linux/module.h>
include/linux/of_irq.h new file +41 -0
41 lines not on this page · raw message
PATCH v2 2/5 of/microblaze: strip out of_irq_workarounds code
In reply to Grant LikelyMicroblaze doesn't have any legacy workaround in the device tree irq mapping data. All of the of_irq_workarounds stuff can be dropped
--- arch/microblaze/include/asm/prom.h | 10 --------- arch/microblaze/kernel/prom_parse.c | 41 ----------------------------------- 2 files changed, 0 insertions(+), 51 deletions(-)
arch/microblaze/include/asm/prom.h +0 -10
@@ -93,19 +93,9 @@ extern const void *of_get_mac_address(struct device_node *np);* OF interrupt mapping */ -/** -* of_irq_map_init - Initialize the irq remapper -* @flags: flags defining workarounds to enable -* -* Some machines have bugs in the device-tree which require certain workarounds -* to be applied. Call this before any interrupt mapping attempts to enable -* those workarounds. -*/ #define OF_IMAP_OLDWORLD_MAC 0x00000001#define OF_IMAP_NO_PHANDLE 0x00000002 -extern void of_irq_map_init (unsigned int flags); -/** * of_irq_map_raw - Low level interrupt tree parsing * @parent: the device interrupt parent
arch/microblaze/kernel/prom_parse.c +0 -41
47 lines not on this page · raw message
PATCH v2 3/5 of/powerpc: Move Powermac irq quirk code into powermac pic driver code
In reply to Grant LikelyThe code that figures out what is wrong with the powermac irq device tree data belongs with the rest of the powermac irq code. This patch moves it out of prom_parse.c and into powermac/pic.c so that it is only compiled in when actually needed.
The quirk flags are also conditionally compiled out to discourage their use by other platforms.
--- arch/powerpc/include/asm/prom.h | 24 ++++++--- arch/powerpc/kernel/prom_parse.c | 85 --------------------------------- arch/powerpc/platforms/powermac/pic.c | 72 ++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 100 deletions(-)
arch/powerpc/include/asm/prom.h +15 -9
@@ -109,18 +109,24 @@ extern const void *of_get_mac_address(struct device_node *np);* OF interrupt mapping */ -/** -* of_irq_map_init - Initialize the irq remapper -* @flags: flags defining workarounds to enable -* -* Some machines have bugs in the device-tree which require certain workarounds -* to be applied. Call this before any interrupt mapping attempts to enable -* those workarounds. -*/ #define OF_IMAP_OLDWORLD_MAC 0x00000001#define OF_IMAP_NO_PHANDLE 0x00000002 -extern void of_irq_map_init (unsigned int flags); +#if defined(CONFIG_PPC32 ) && defined(CONFIG_PPC_PMAC ) +/* Workarounds only needed for 32bit powermac machines */ +extern unsigned int of_irq_workarounds; +extern struct device_node *of_irq_dflt_pic; +extern int of_irq_map_oldworld (struct device_node *device,int index, +struct of_irq *out_irq); +#else +#define of_irq_workarounds (0) +#define of_irq_dflt_pic (NULL) +static inline int of_irq_map_oldworld (struct device_node *device,int index, +struct of_irq *out_irq) +{ +return -EINVAL ; +} +#endif /** * of_irq_map_raw - Low level interrupt tree parsing
arch/powerpc/kernel/prom_parse.c +0 -85
103 lines not on this page · raw message
arch/powerpc/platforms/powermac/pic.c +66 -6
97 lines not on this page · raw message
PATCH v2 4/5 of/irq: merge irq mapping code
In reply to Grant LikelyMerge common irq mapping code between PowerPC and Microblaze.
This patch merges of_irq_find_parent(), of_irq_map_raw() and of_irq_map_one(). The functions are dependent on one another, so all three are merged in a single patch. Other than cosmetic difference (ie. DBG() vs. pr_debug()), the implementations are identical.
of_irq_to_resource() is also merged, but in this case the implementations are different. This patch drops the microblaze version and uses the powerpc implementation unchanged. The microblaze version essentially open-coded irq_of_parse_and_map() which it does not need to do. Therefore the powerpc version is safe to adopt.
--- arch/microblaze/include/asm/prom.h | 31 ---- arch/microblaze/kernel/prom_parse.c | 290 ---------------------------------- arch/powerpc/include/asm/prom.h | 47 ----- arch/powerpc/kernel/prom_parse.c | 266 ------------------------------- drivers/of/irq.c | 301 +++++++++++++++++++++++++++++++++++ include/linux/of_irq.h | 29 +++ 6 files changed, 330 insertions(+), 634 deletions(-)
arch/microblaze/include/asm/prom.h +0 -31
@@ -89,34 +89,6 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);/* Get the MAC address */ extern const void *of_get_mac_address (struct device_node *np); -/* -* OF interrupt mapping -*/ - -#define OF_IMAP_OLDWORLD_MAC 0x00000001 -#define OF_IMAP_NO_PHANDLE 0x00000002 - -/** -* of_irq_map_raw - Low level interrupt tree parsing -* @parent: the device interrupt parent -* @intspec: interrupt specifier ("interrupts" property of the device) -* @ointsize: size of the passed in interrupt specifier -* @addr: address specifier (start of "reg" property of the device) -* @out_irq: structure of_irq filled by this function -* -* Returns 0 on success and a negative number on error -* -* This function is a low-level interrupt tree walking function. It -* can be used to do a partial walk with synthetized reg and interrupts -* properties, for example when resolving PCI interrupts when no device -* node exist for the parent. -* -*/ - -extern int of_irq_map_raw (struct device_node *parent,const u32 *intspec, -u32 ointsize,const u32 *addr, -struct of_irq *out_irq); -/** * of_irq_map_pci - Resolve the interrupt for a PCI device * @pdev: the device whose interrupt is to be resolved
@@ -131,9 +103,6 @@ extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec,struct pci_dev ;extern int of_irq_map_pci (struct pci_dev *pdev,struct of_irq *out_irq); -extern int of_irq_to_resource (struct device_node *dev,int index, -struct resource *r); -/** * of_iomap - Maps the memory mapped IO for a given device_node * @device: the device whose io range will be mapped
arch/microblaze/kernel/prom_parse.c +0 -290
302 lines not on this page · raw message
arch/powerpc/include/asm/prom.h +0 -47
59 lines not on this page · raw message
arch/powerpc/kernel/prom_parse.c +0 -266
278 lines not on this page · raw message
drivers/of/irq.c +301 -0
304 lines not on this page · raw message
include/linux/of_irq.h +29 -0
@@ -4,6 +4,8 @@#if defined(CONFIG_OF )struct of_irq ;#include <linux/types.h> +#include <linux/errno.h> +#include <linux/ioport.h> #include <linux/of.h> /*
@@ -30,11 +32,38 @@ struct of_irq {u32 specifier[OF_MAX_IRQ_SPEC ];/* Specifier copy */ }; +/* +* Workarounds only applied to 32bit powermac machines +*/ +#define OF_IMAP_OLDWORLD_MAC 0x00000001 +#define OF_IMAP_NO_PHANDLE 0x00000002 + +#if defined(CONFIG_PPC32 ) && defined(CONFIG_PPC_PMAC ) +extern unsigned int of_irq_workarounds; +extern struct device_node *of_irq_dflt_pic; +extern int of_irq_map_oldworld (struct device_node *device,int index, +struct of_irq *out_irq); +#else /* CONFIG_PPC32 && CONFIG_PPC_PMAC */ +#define of_irq_workarounds (0) +#define of_irq_dflt_pic (NULL) +static inline int of_irq_map_oldworld (struct device_node *device,int index, +struct of_irq *out_irq) +{ +return -EINVAL ; +} +#endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */ + + +extern int of_irq_map_raw (struct device_node *parent,const u32 *intspec, +u32 ointsize,const u32 *addr, +struct of_irq *out_irq);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,const u32 *intspec,unsigned int intsize); +extern int of_irq_to_resource (struct device_node *dev,int index, +struct resource *r);#endif /* CONFIG_OF_IRQ */ #endif /* CONFIG_OF */
PATCH v2 5/5 of/irq: little endian fixes
In reply to Grant LikelyFrom: Rob Herring <[email protected]>
Fix some endian issues in the irq mapping OF code.
--- drivers/of/irq.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-)
drivers/of/irq.c +9 -8
@@ -87,7 +87,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, const u32 *addr, struct of_irq *out_irq) { struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; -const u32 *tmp, *imap, *imask; +const __be32 *tmp, *imap, *imask;u32 intsize =1 , addrsize, newintsize =0 , newaddrsize =0 ;int imaplen, match, i;
@@ -103,7 +103,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, do { tmp = of_get_property(ipar, "#interrupt-cells", NULL); if (tmp != NULL) { - intsize = *tmp; + intsize = be32_to_cpu(*tmp); break; } tnode = ipar;
@@ -132,7 +132,7 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, }while (old && tmp ==NULL );of_node_put (old); old =NULL ; - addrsize = (tmp ==NULL ) ?2 : *tmp; + addrsize = (tmp ==NULL ) ?2 :be32_to_cpu (*tmp);pr_debug (" -> addrsize=%d\n" , addrsize);
@@ -144,8 +144,9 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,if (of_get_property (ipar,"interrupt-controller" ,NULL ) !=NULL ) {pr_debug (" -> got it !\n" ); -memcpy (out_irq->specifier, intspec, - intsize *sizeof (u32)); +for (i =0 ; i < intsize; i++) + out_irq->specifier[i] = +of_read_number (intspec +i,1 ); out_irq->size = intsize; out_irq->controller = ipar;of_node_put (old);
@@ -215,9 +216,9 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,pr_debug (" -> parent lacks #interrupt-cells!\n" ); goto fail; } - newintsize = *tmp; + newintsize =be32_to_cpu (*tmp); tmp =of_get_property (newpar,"#address-cells" ,NULL ); - newaddrsize = (tmp ==NULL ) ?0 : *tmp; + newaddrsize = (tmp ==NULL ) ?0 :be32_to_cpu (*tmp);pr_debug (" -> newintsize=%d, newaddrsize=%d\n" , newintsize, newaddrsize);
@@ -299,7 +300,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq tmp =of_get_property (p,"#interrupt-cells" ,NULL );if (tmp ==NULL ) goto out; - intsize = *tmp; + intsize =be32_to_cpu (*tmp);pr_debug (" intsize=%d intlen=%d\n" , intsize, intlen);