From 899f0e66fff36ebb6dd6a83af9aa631f6cb7e0dc Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Mon, 6 May 2013 14:30:19 +0000 Subject: genirq: Generic chip: Add support for per chip type mask cache Today the same interrupt mask cache (stored within struct irq_chip_generic) is shared between all the irq_chip_type instances. As there are instances where each irq_chip_type uses a distinct mask register (as it is the case for Orion SoCs), sharing a single mask cache may be incorrect. So add a distinct pointer for each irq_chip_type, which for now points to the original mask register within irq_chip_generic. So no functional changes here. [ tglx: Minor cosmetic tweaks ] Reported-by: Joey Oravec Signed-off-by: Simon Guinot Signed-off-by: Holger Brunck Signed-off-by: Gerlando Falauto Cc: Andrew Lunn Cc: Lennert Buytenhek Cc: Russell King - ARM Linux Cc: Jason Gunthorpe Cc: Holger Brunck Cc: Ezequiel Garcia Acked-by: Grant Likely Cc: Sebastian Hesselbarth Cc: Jason Cooper Cc: Arnd Bergmann Cc: devicetree-discuss@lists.ozlabs.org Cc: Rob Herring Cc: Ben Dooks Cc: Gregory Clement Cc: Simon Guinot Cc: linux-arm-kernel@lists.infradead.org Cc: Thomas Petazzoni Cc: Jean-Francois Moine Cc: Nicolas Pitre Cc: Rob Landley Cc: Maxime Ripard Link: http://lkml.kernel.org/r/20130506142539.082226607@linutronix.de Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index bc4e06611958..38709a3ab1c0 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -644,6 +644,8 @@ struct irq_chip_regs { * @regs: Register offsets for this chip * @handler: Flow handler associated with this chip * @type: Chip can handle these flow types + * @mask_cache_priv: Cached mask register private to the chip type + * @mask_cache: Pointer to cached mask register * * A irq_generic_chip can have several instances of irq_chip_type when * it requires different functions and register offsets for different @@ -654,6 +656,8 @@ struct irq_chip_type { struct irq_chip_regs regs; irq_flow_handler_t handler; u32 type; + u32 mask_cache_priv; + u32 *mask_cache; }; /** @@ -662,7 +666,7 @@ struct irq_chip_type { * @reg_base: Register base address (virtual) * @irq_base: Interrupt base nr for this chip * @irq_cnt: Number of interrupts handled by this chip - * @mask_cache: Cached mask register + * @mask_cache: Cached mask register shared between all chip types * @type_cache: Cached type register * @polarity_cache: Cached polarity register * @wake_enabled: Interrupt can wakeup from suspend -- cgit v1.2.3 From af80b0fed67261dcba2ce2406db1d553d07cbe75 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Mon, 6 May 2013 14:30:21 +0000 Subject: genirq: Generic chip: Handle separate mask registers There are cases where all irq_chip_type instances have separate mask registers, making a shared mask register cache unsuitable for the purpose. Introduce a new flag IRQ_GC_MASK_CACHE_PER_TYPE. If set, point the per chip mask pointer to the per chip private mask cache instead. [ tglx: Simplified code, renamed flag and massaged changelog ] Signed-off-by: Gerlando Falauto Cc: Andrew Lunn Cc: Joey Oravec Cc: Lennert Buytenhek Cc: Russell King - ARM Linux Cc: Jason Gunthorpe Cc: Holger Brunck Cc: Ezequiel Garcia Acked-by: Grant Likely Cc: Sebastian Hesselbarth Cc: Jason Cooper Cc: Arnd Bergmann Cc: devicetree-discuss@lists.ozlabs.org Cc: Rob Herring Cc: Ben Dooks Cc: Gregory Clement Cc: Simon Guinot Cc: linux-arm-kernel@lists.infradead.org Cc: Thomas Petazzoni Cc: Jean-Francois Moine Cc: Nicolas Pitre Cc: Rob Landley Cc: Maxime Ripard Link: http://lkml.kernel.org/r/20130506142539.152569748@linutronix.de Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index 38709a3ab1c0..7f1f0157fd00 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -704,10 +704,12 @@ struct irq_chip_generic { * @IRQ_GC_INIT_NESTED_LOCK: Set the lock class of the irqs to nested for * irq chips which need to call irq_set_wake() on * the parent irq. Usually GPIO implementations + * @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private */ enum irq_gc_flags { IRQ_GC_INIT_MASK_CACHE = 1 << 0, IRQ_GC_INIT_NESTED_LOCK = 1 << 1, + IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2, }; /* Generic chip callback functions */ -- cgit v1.2.3 From 966dc736b819999cd2d3a6408d47d33b579f7d56 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 6 May 2013 14:30:22 +0000 Subject: genirq: Generic chip: Cache per irq bit mask Cache the per irq bit mask instead of recalculating it over and over. Signed-off-by: Thomas Gleixner Cc: Thomas Petazzoni Cc: Andrew Lunn Cc: Russell King - ARM Linux Cc: Jason Cooper Cc: Arnd Bergmann Cc: Jean-Francois Moine Cc: devicetree-discuss@lists.ozlabs.org Cc: Rob Herring Cc: Jason Gunthorpe Cc: Gregory Clement Cc: Gerlando Falauto Cc: Rob Landley Acked-by: Grant Likely Cc: Maxime Ripard Cc: Ezequiel Garcia Cc: linux-arm-kernel@lists.infradead.org Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20130506142539.227119865@linutronix.de Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index 7f1f0157fd00..d5fc7f5a49b8 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -119,6 +119,7 @@ struct irq_domain; /** * struct irq_data - per irq and irq chip data passed down to chip functions + * @mask: precomputed bitmask for accessing the chip registers * @irq: interrupt number * @hwirq: hardware interrupt number, local to the interrupt domain * @node: node index useful for balancing @@ -138,6 +139,7 @@ struct irq_domain; * irq_data. */ struct irq_data { + u32 mask; unsigned int irq; unsigned long hwirq; unsigned int node; @@ -705,11 +707,13 @@ struct irq_chip_generic { * irq chips which need to call irq_set_wake() on * the parent irq. Usually GPIO implementations * @IRQ_GC_MASK_CACHE_PER_TYPE: Mask cache is chip type private + * @IRQ_GC_NO_MASK: Do not calculate irq_data->mask */ enum irq_gc_flags { IRQ_GC_INIT_MASK_CACHE = 1 << 0, IRQ_GC_INIT_NESTED_LOCK = 1 << 1, IRQ_GC_MASK_CACHE_PER_TYPE = 1 << 2, + IRQ_GC_NO_MASK = 1 << 3, }; /* Generic chip callback functions */ -- cgit v1.2.3 From d0051816e619f8f082582bec07ffa51bdb4f2104 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 6 May 2013 14:30:24 +0000 Subject: genirq: irqchip: Add a mask calculation function Some chips have weird bit mask access patterns instead of the linear you expect. Allow them to calculate the cached mask themself. Signed-off-by: Thomas Gleixner Cc: Thomas Petazzoni Cc: Andrew Lunn Cc: Russell King - ARM Linux Cc: Jason Cooper Cc: Arnd Bergmann Cc: Jean-Francois Moine Cc: devicetree-discuss@lists.ozlabs.org Cc: Rob Herring Cc: Jason Gunthorpe Cc: Gregory Clement Cc: Gerlando Falauto Cc: Rob Landley Acked-by: Grant Likely Cc: Maxime Ripard Cc: Ezequiel Garcia Cc: linux-arm-kernel@lists.infradead.org Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20130506142539.302898834@linutronix.de Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index d5fc7f5a49b8..ab8169faaa65 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -296,6 +296,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) * @irq_suspend: function called from core code on suspend once per chip * @irq_resume: function called from core code on resume once per chip * @irq_pm_shutdown: function called from core code on shutdown once per chip + * @irq_calc_mask: Optional function to set irq_data.mask for special cases * @irq_print_chip: optional to print special chip info in show_interrupts * @flags: chip specific flags */ @@ -327,6 +328,8 @@ struct irq_chip { void (*irq_resume)(struct irq_data *data); void (*irq_pm_shutdown)(struct irq_data *data); + void (*irq_calc_mask)(struct irq_data *data); + void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); unsigned long flags; -- cgit v1.2.3 From 088f40b7b027dad6519712ff224a5798dd62a204 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 6 May 2013 14:30:27 +0000 Subject: genirq: Generic chip: Add linear irq domain support Provide infrastructure for irq chip implementations which work on linear irq domains. - Interface to allocate multiple generic chips which are associated to the irq domain. - Interface to get the generic chip pointer for a particular hardware interrupt in the domain. - irq domain mapping function to install the chip for a particular interrupt. Note: This lacks a removal function for now. [ Sebastian Hesselbarth: Mask cache and pointer math fixups ] Signed-off-by: Thomas Gleixner Cc: Thomas Petazzoni Cc: Andrew Lunn Cc: Russell King - ARM Linux Cc: Jason Cooper Cc: Arnd Bergmann Cc: Jean-Francois Moine Cc: devicetree-discuss@lists.ozlabs.org Cc: Rob Herring Cc: Jason Gunthorpe Cc: Gregory Clement Cc: Gerlando Falauto Cc: Rob Landley Acked-by: Grant Likely Cc: Maxime Ripard Cc: Ezequiel Garcia Cc: linux-arm-kernel@lists.infradead.org Cc: Sebastian Hesselbarth Link: http://lkml.kernel.org/r/20130506142539.450634298@linutronix.de Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index ab8169faaa65..af7052c6a45c 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -678,6 +678,8 @@ struct irq_chip_type { * @wake_active: Interrupt is marked as an wakeup from suspend source * @num_ct: Number of available irq_chip_type instances (usually 1) * @private: Private data for non generic chip callbacks + * @installed: bitfield to denote installed interrupts + * @domain: irq domain pointer * @list: List head for keeping track of instances * @chip_types: Array of interrupt irq_chip_types * @@ -699,6 +701,8 @@ struct irq_chip_generic { u32 wake_active; unsigned int num_ct; void *private; + unsigned long installed; + struct irq_domain *domain; struct list_head list; struct irq_chip_type chip_types[0]; }; @@ -719,6 +723,24 @@ enum irq_gc_flags { IRQ_GC_NO_MASK = 1 << 3, }; +/* + * struct irq_domain_chip_generic - Generic irq chip data structure for irq domains + * @irqs_per_chip: Number of interrupts per chip + * @num_chips: Number of chips + * @irq_flags_to_set: IRQ* flags to set on irq setup + * @irq_flags_to_clear: IRQ* flags to clear on irq setup + * @gc_flags: Generic chip specific setup flags + * @gc: Array of pointers to generic interrupt chips + */ +struct irq_domain_chip_generic { + unsigned int irqs_per_chip; + unsigned int num_chips; + unsigned int irq_flags_to_clear; + unsigned int irq_flags_to_set; + enum irq_gc_flags gc_flags; + struct irq_chip_generic *gc[0]; +}; + /* Generic chip callback functions */ void irq_gc_noop(struct irq_data *d); void irq_gc_mask_disable_reg(struct irq_data *d); @@ -742,6 +764,14 @@ int irq_setup_alt_chip(struct irq_data *d, unsigned int type); void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, unsigned int clr, unsigned int set); +struct irq_chip_generic *irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq); +int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, + int num_ct, const char *name, + irq_flow_handler_t handler, + unsigned int clr, unsigned int set, + enum irq_gc_flags flags); + + static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d) { return container_of(d->chip, struct irq_chip_type, chip); -- cgit v1.2.3 From e8bd834f73714378ef110a64287db1b77033c8da Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 29 May 2013 03:10:52 +0100 Subject: genirq: irqchip: Add mask to block out invalid irqs Some controllers have irqs that aren't wired up and must never be used. For the generic chip attached to an irq_domain this provides a mask that can be used to block out particular irqs so that they never get mapped. Signed-off-by: Grant Likely Link: http://lkml.kernel.org/r/1369793454-19197-2-git-send-email-grant.likely@linaro.org Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index af7052c6a45c..298a9b9ce675 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -679,6 +679,7 @@ struct irq_chip_type { * @num_ct: Number of available irq_chip_type instances (usually 1) * @private: Private data for non generic chip callbacks * @installed: bitfield to denote installed interrupts + * @unused: bitfield to denote unused interrupts * @domain: irq domain pointer * @list: List head for keeping track of instances * @chip_types: Array of interrupt irq_chip_types @@ -702,6 +703,7 @@ struct irq_chip_generic { unsigned int num_ct; void *private; unsigned long installed; + unsigned long unused; struct irq_domain *domain; struct list_head list; struct irq_chip_type chip_types[0]; -- cgit v1.2.3 From 1f6236bfd7c38d5f9f7648fae7215e65274b9e63 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 14 Jun 2013 18:40:43 +0200 Subject: genirq: Add irq_get_trigger_type() to get IRQ flags Drivers that want to get the trigger edge/level type flags for a given interrupt have to call irq_get_irq_data(irq) to get the struct irq_data and then irqd_get_trigger_type(irq_data) to obtain the IRQ flags. This is not only error prone but also unnecessary exposes the struct irq_data to callers. It's better to have an irq_get_trigger_type() function to obtain the edge/level flags for an IRQ. Signed-off-by: Javier Martinez Canillas Acked-by: Grant Likely Cc: Linus Walleij Cc: Samuel Ortiz Cc: Jason Cooper Cc: Andrew Lunn Cc: Russell King Cc: Ralf Baechle Cc: Benjamin Herrenschmidt Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mips@linux-mips.org Link: http://lkml.kernel.org/r/1371228049-27080-2-git-send-email-javier.martinez@collabora.co.uk Signed-off-by: Thomas Gleixner --- include/linux/irq.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux/irq.h') diff --git a/include/linux/irq.h b/include/linux/irq.h index 298a9b9ce675..f04d3ba335cb 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -584,6 +584,12 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d) return d->msi_desc; } +static inline u32 irq_get_trigger_type(unsigned int irq) +{ + struct irq_data *d = irq_get_irq_data(irq); + return d ? irqd_get_trigger_type(d) : 0; +} + int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, struct module *owner); -- cgit v1.2.3