VIC DT binding and MULTI_IRQ_HANDLER
Subsystems (9)
v2 cover VIC DT binding and MULTI_IRQ_HANDLER
This patch series adds a device tree binding for the VIC and support for a generic VIC MULTI_IRQ_HANDLER. The MULTI_IRQ_HANDLER is a step towards a single image kernel, removing the need for mach specific entry handlers for platforms using the VIC as the primary interrupt controller.
This has dependencies on:
- of/irq: introduce of_irq_init http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/066844.html - irq: add declaration of irq_domain_simple_ops to irqdomain.h https://lkml.org/lkml/2011/9/14/189
from Rob Herring, and
- ARM: Make global handler and CONFIG_MULTI_IRQ_HANDLER mutually exclusive http://www.spinics.net/lists/arm-kernel/msg141948.html
from Marc Zyngier.
Tested on picoxcell and build tested for all defconfigs.
Jamie Iles (10):
ARM: vic: device tree binding
ARM: vic: MULTI_IRQ_HANDLER handler
ARM: ep93xx: convert to MULTI_IRQ_HANDLER
ARM: netx: convert to MULTI_IRQ_HANDLER
ARM: nomadik: convert to MULTI_IRQ_HANDLER
ARM: s3c64xx: convert to MULTI_IRQ_HANDLER
ARM: spear: convert to MULTI_IRQ_HANDLER
ARM: u300: convert to MULTI_IRQ_HANDLER
ARM: versatile: convert to MULTI_IRQ_HANDLER
ARM: samsung: convert to MULTI_IRQ_HANDLER
Documentation/devicetree/bindings/arm/vic.txt | 29 ++++ arch/arm/Kconfig | 10 ++ arch/arm/common/Kconfig | 1 + arch/arm/common/vic.c | 135 ++++++++++++++++---- arch/arm/include/asm/hardware/vic.h | 14 ++- arch/arm/mach-ep93xx/adssphere.c | 2 + arch/arm/mach-ep93xx/edb93xx.c | 9 ++ arch/arm/mach-ep93xx/gesbc9312.c | 2 + arch/arm/mach-ep93xx/include/mach/entry-macro.S | 42 ------ arch/arm/mach-ep93xx/micro9.c | 5 + arch/arm/mach-ep93xx/simone.c | 2 + arch/arm/mach-ep93xx/snappercl15.c | 2 + arch/arm/mach-ep93xx/ts72xx.c | 2 + arch/arm/mach-netx/include/mach/entry-macro.S | 13 -- arch/arm/mach-netx/nxdb500.c | 2 + arch/arm/mach-netx/nxdkn.c | 2 + arch/arm/mach-netx/nxeb500hmi.c | 2 + arch/arm/mach-nomadik/board-nhk8815.c | 2 + arch/arm/mach-nomadik/include/mach/entry-macro.S | 30 ----- arch/arm/mach-s3c64xx/include/mach/entry-macro.S | 7 +- arch/arm/mach-s3c64xx/mach-anw6410.c | 2 + arch/arm/mach-s3c64xx/mach-crag6410.c | 2 + arch/arm/mach-s3c64xx/mach-hmt.c | 2 + arch/arm/mach-s3c64xx/mach-mini6410.c | 2 + arch/arm/mach-s3c64xx/mach-ncp.c | 2 + arch/arm/mach-s3c64xx/mach-real6410.c | 2 + arch/arm/mach-s3c64xx/mach-smartq5.c | 2 + arch/arm/mach-s3c64xx/mach-smartq7.c | 2 + arch/arm/mach-s3c64xx/mach-smdk6400.c | 2 + arch/arm/mach-s3c64xx/mach-smdk6410.c | 2 + arch/arm/mach-s5p64x0/include/mach/entry-macro.S | 7 +- arch/arm/mach-s5p64x0/mach-smdk6440.c | 2 + arch/arm/mach-s5p64x0/mach-smdk6450.c | 2 + arch/arm/mach-s5pc100/include/mach/entry-macro.S | 25 ---- arch/arm/mach-s5pc100/mach-smdkc100.c | 2 + arch/arm/mach-s5pv210/include/mach/entry-macro.S | 37 ------ arch/arm/mach-s5pv210/mach-aquila.c | 2 + arch/arm/mach-s5pv210/mach-goni.c | 2 + arch/arm/mach-s5pv210/mach-smdkc110.c | 2 + arch/arm/mach-s5pv210/mach-smdkv210.c | 2 + arch/arm/mach-s5pv210/mach-torbreck.c | 2 + arch/arm/mach-spear3xx/include/mach/entry-macro.S | 27 ---- arch/arm/mach-spear3xx/spear300_evb.c | 2 + arch/arm/mach-spear3xx/spear310_evb.c | 2 + arch/arm/mach-spear3xx/spear320_evb.c | 2 + arch/arm/mach-spear6xx/include/mach/entry-macro.S | 36 ----- arch/arm/mach-spear6xx/spear600_evb.c | 2 + arch/arm/mach-u300/include/mach/entry-macro.S | 24 ---- arch/arm/mach-u300/u300.c | 2 + arch/arm/mach-versatile/include/mach/entry-macro.S | 30 ----- arch/arm/mach-versatile/versatile_ab.c | 2 + arch/arm/mach-versatile/versatile_dt.c | 2 + arch/arm/mach-versatile/versatile_pb.c | 2 + 53 files changed, 252 insertions(+), 299 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/vic.txt
Signature · 1 line
1.7.4.1
PATCH v2 1/10 ARM: vic: device tree binding
This adds a device tree binding for the VIC based on the of_irq_init() support. This adds an irqdomain to the vic and always registers all vics in the static vic array rather than for pm only to keep track of the irq domain. struct irq_data::hwirq is used where appropriate rather than runtime masking.
v2: - use irq_domain_simple_ops
- remove stub implementation of vic_of_init for !CONFIG_OF
- Make VIC select IRQ_DOMAIN
--- Documentation/devicetree/bindings/arm/vic.txt | 29 +++++++ arch/arm/common/Kconfig | 1 + arch/arm/common/vic.c | 106 ++++++++++++++++++------- arch/arm/include/asm/hardware/vic.h | 10 ++- 4 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/vic.txt
Documentation/devicetree/bindings/arm/vic.txt new file +29 -0
@@ -0,0 +1,29 @@ +* ARM Vectored Interrupt Controller + +One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM +system for interrupt routing. For multiple controllers they can either be +nested or have the outputs wire-OR'd together. + +Required properties: + +- compatible : should be one of + "arm,pl190-vic" + "arm,pl192-vic" +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : The number of cells to define the interrupts. Must be 1 as + the VIC has no configuration options for interrupt sources. The cell is a u32 + and defines the interrupt number. +- reg : The register bank for the VIC. + +Optional properties: + +- interrupts : Interrupt source for parent controllers if the VIC is nested. + +Example: + + vic0: interrupt-controller at 60000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x60000 0x1000>; + };
arch/arm/common/Kconfig +1 -0
@@ -2,6 +2,7 @@ config ARM_GIC bool config ARM_VIC + select IRQ_DOMAIN bool config ARM_VIC_NR
arch/arm/common/vic.c +78 -28
190 lines not on this page · raw message
arch/arm/include/asm/hardware/vic.h +9 -1
@@ -41,7 +41,15 @@#define VIC_PL192_VECT_ADDR 0xF00#ifndef __ASSEMBLY__ +#include <linux/compiler.h> +#include <linux/types.h> + +struct device_node ;void vic_init (void __iomem *base,unsigned int irq_start,u32 vic_sources,u32 resume_sources); -#endif +#ifdef CONFIG_OF +int vic_of_init (struct device_node *node,struct device_node *parent); +#endif /* CONFIG_OF */ + +#endif /* __ASSEMBLY__ */ #endif
Signature · 1 line
1.7.4.1
PATCH v2 1/10 ARM: vic: device tree binding
Quoted 9 lines · Jamie Iles
This adds a device tree binding for the VIC based on the
of_irq_init()support. This adds an irqdomain to the vic and always registers all vics in the static vic array rather than for pm only to keep track of the irq domain. structirq_data::hwirqis used where appropriate rather than runtime masking.v2: - use
irq_domain_simple_ops
- remove stub implementation ofvic_of_initfor !CONFIG_OF
- Make VIC selectIRQ_DOMAIN
Looks right to me.
Quoted 286 lines
Cc Rob Herring <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Jamie Iles <[email protected]>--- Documentation/devicetree/bindings/arm/vic.txt | 29 +++++++ arch/arm/common/Kconfig | 1 + arch/arm/common/vic.c | 106 ++++++++++++++++++------- arch/arm/include/asm/hardware/vic.h | 10 ++- 4 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/vic.txtDocumentation/devicetree/bindings/arm/vic.txt new file +29
-0@@ -0,0 +1,29 @@ +* ARM Vectored Interrupt Controller + +One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM +system for interrupt routing. For multiple controllers they can either be +nested or have the outputs wire-OR'd together. + +Required properties: + +- compatible : should be one of + "arm,pl190-vic" + "arm,pl192-vic" +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : The number of cells to define the interrupts. Must be 1 as + the VIC has no configuration options for interrupt sources. The cell is a u32 + and defines the interrupt number. +- reg : The register bank for the VIC. + +Optional properties: + +- interrupts : Interrupt source for parent controllers if the VIC is nested. + +Example: + + vic0: interrupt-controller at 60000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x60000 0x1000>; + };arch/arm/common/Kconfig +1
-0@@ -2,6 +2,7 @@ config ARM_GIC bool config ARM_VIC + select IRQ_DOMAIN bool config ARM_VIC_NRarch/arm/common/vic.c +78
-28@@ -22,6 +22,10 @@#include <linux/init.h> #include <linux/list.h> #include <linux/io.h> +#include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/syscore_ops.h> #include <linux/device.h> #include <linux/amba/bus.h> @@ -29,7 +33,6 @@#include <asm/mach/irq.h> #include <asm/hardware/vic.h> -#ifdef CONFIG_PM /** * struct vic_device - VIC PM device * @irq: The IRQ number for the base of the VIC. @@ -40,6 +43,7 @@* @int_enable: Save for VIC_INT_ENABLE. * @soft_int: Save for VIC_INT_SOFT. * @protect: Save for VIC_PROTECT. +* @domain: The IRQ domain for the VIC. */ struct vic_device {void __iomem *base;@@ -50,13 +54,13 @@ struct vic_device {u32 int_enable;u32 soft_int;u32 protect; +struct irq_domain domain; };/* we cannot allocate memory when VICs are initially registered */ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR ];static int vic_id; -#endif /* CONFIG_PM */ /** * vic_init2 - common initialisation code @@ -156,39 +160,50 @@ static int __init vic_pm_init(void)return 0 ; }late_initcall (vic_pm_init); +#endif /* CONFIG_PM */ /** -* vic_pm_register - Register a VIC for later power management control +* vic_register() - Register a VIC. * @base: The base address of the VIC. * @irq: The base IRQ for the VIC. * @resume_sources: bitmask of interrupts allowed for resume sources. +* @node: The device tree node associated with the VIC. * * Register the VIC with the system device tree so that it can be notified * of suspend and resume requests and ensure that the correct actions are * taken to re-instate the settings on resume. +* +* This also configures the IRQ domain for the VIC. */ -static void __init vic_pm_register (void __iomem *base,unsigned int irq,u32 resume_sources) +static void __init vic_register (void __iomem *base,unsigned int irq, +u32 resume_sources,struct device_node *node) {struct vic_device *v; -if (vic_id >=ARRAY_SIZE (vic_devices)) +if (vic_id >=ARRAY_SIZE (vic_devices)) {printk (KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n" , __func__); -else { - v = &vic_devices[vic_id]; - v->base = base; - v->resume_sources = resume_sources; - v->irq = irq; - vic_id++; +return ; } + + v = &vic_devices[vic_id]; + v->base = base; + v->resume_sources = resume_sources; + v->irq = irq; + vic_id++; + + v->domain.irq_base = irq; + v->domain.nr_irq =32 ; +#ifdef CONFIG_OF_IRQ + v->domain.of_node =of_node_get (node); + v->domain.ops = &irq_domain_simple_ops; +#endif /* CONFIG_OF */ +irq_domain_add (&v->domain); } -#else -static inline void vic_pm_register (void __iomem *base,unsigned int irq,u32 arg1) { } -#endif /* CONFIG_PM */ static void vic_ack_irq (struct irq_data *d) {void __iomem *base =irq_data_get_irq_chip_data (d); -unsigned int irq = d->irq &31 ; +unsigned int irq = d->hwirq;writel (1 << irq, base +VIC_INT_ENABLE_CLEAR );/* moreover, clear the soft-triggered, in case it was the reason */ writel (1 << irq, base +VIC_INT_SOFT_CLEAR );@@ -197,14 +212,14 @@ static void vic_ack_irq(struct irq_data *d)static void vic_mask_irq (struct irq_data *d) {void __iomem *base =irq_data_get_irq_chip_data (d); -unsigned int irq = d->irq &31 ; +unsigned int irq = d->hwirq;writel (1 << irq, base +VIC_INT_ENABLE_CLEAR ); }static void vic_unmask_irq (struct irq_data *d) {void __iomem *base =irq_data_get_irq_chip_data (d); -unsigned int irq = d->irq &31 ; +unsigned int irq = d->hwirq;writel (1 << irq, base +VIC_INT_ENABLE ); }@@ -226,7 +241,7 @@ static struct vic_device *vic_from_irq(unsigned int irq)static int vic_set_wake (struct irq_data *d,unsigned int on) {struct vic_device *v =vic_from_irq (d->irq); -unsigned int off = d->irq &31 ; +unsigned int off = d->hwirq;u32 bit =1 << off;if (!v)@@ -331,15 +346,9 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,vic_set_irq_sources (base, irq_start, vic_sources); } -/** -* vic_init - initialise a vectored interrupt controller -* @base: iomem base address -* @irq_start: starting interrupt number, must be muliple of 32 -* @vic_sources: bitmask of interrupt sources to allow -* @resume_sources: bitmask of interrupt sources to allow for resume -*/ -void __init vic_init (void __iomem *base,unsigned int irq_start, -u32 vic_sources,u32 resume_sources) +static void __init __vic_init (void __iomem *base,unsigned int irq_start, +u32 vic_sources,u32 resume_sources, +struct device_node *node) {unsigned int i;u32 cellid =0 ;@@ -375,5 +384,46 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,vic_set_irq_sources (base, irq_start, vic_sources); -vic_pm_register (base, irq_start, resume_sources); +vic_register (base, irq_start, resume_sources, node); +} + +/** +* vic_init() - initialise a vectored interrupt controller +* @base: iomem base address +* @irq_start: starting interrupt number, must be muliple of 32 +* @vic_sources: bitmask of interrupt sources to allow +* @resume_sources: bitmask of interrupt sources to allow for resume +*/ +void __init vic_init (void __iomem *base,unsigned int irq_start, +u32 vic_sources,u32 resume_sources) +{ +__vic_init (base, irq_start, vic_sources, resume_sources,NULL ); +} + +#ifdef CONFIG_OF +int __init vic_of_init (struct device_node *node,struct device_node *parent) +{ +void __iomem *regs; +int irq_base; + +if (WARN (parent,"non-root VICs are not supported" )) +return -EINVAL ; + + regs =of_iomap (node,0 ); +if (WARN_ON (!regs)) +return -EIO ; + + irq_base =irq_alloc_descs (-1 ,0 ,32 ,numa_node_id ()); +if (WARN_ON (irq_base <0 )) + goto out_unmap; + +__vic_init (regs, irq_base, ~0 , ~0 , node); + +return 0 ; + + out_unmap: +iounmap (regs); + +return -EIO ; } +#endif /* CONFIG OF */ arch/arm/include/asm/hardware/vic.h +9
-1@@ -41,7 +41,15 @@#define VIC_PL192_VECT_ADDR 0xF00#ifndef __ASSEMBLY__ +#include <linux/compiler.h> +#include <linux/types.h> + +struct device_node ;void vic_init (void __iomem *base,unsigned int irq_start,u32 vic_sources,u32 resume_sources); -#endif +#ifdef CONFIG_OF +int vic_of_init (struct device_node *node,struct device_node *parent); +#endif /* CONFIG_OF */ + +#endif /* __ASSEMBLY__ */ #endif Signature · 1 line
1.7.4.1
PATCH v2 1/10 ARM: vic: device tree binding
In reply to Jamie IlesQuoted 6 lines · Jamie Iles
This adds a device tree binding for the VIC based on the
of_irq_init()support. This adds an irqdomain to the vic and always registers all vics in the static vic array rather than for pm only to keep track of the irq domain. structirq_data::hwirqis used where appropriate rather than runtime masking.
Quoted 7 lines
v2: - use
irq_domain_simple_ops
- remove stub implementation ofvic_of_initfor !CONFIG_OF
- Make VIC selectIRQ_DOMAINCc Rob Herring <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Jamie Iles <[email protected]>
Looks good. One minor comment below, but otherwise:
Quoted 266 lines
--- Documentation/devicetree/bindings/arm/vic.txt | 29 +++++++ arch/arm/common/Kconfig | 1 + arch/arm/common/vic.c | 106 ++++++++++++++++++------- arch/arm/include/asm/hardware/vic.h | 10 ++- 4 files changed, 117 insertions(+), 29 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/vic.txtDocumentation/devicetree/bindings/arm/vic.txt new file +29
-0@@ -0,0 +1,29 @@ +* ARM Vectored Interrupt Controller + +One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM +system for interrupt routing. For multiple controllers they can either be +nested or have the outputs wire-OR'd together. + +Required properties: + +- compatible : should be one of + "arm,pl190-vic" + "arm,pl192-vic" +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : The number of cells to define the interrupts. Must be 1 as + the VIC has no configuration options for interrupt sources. The cell is a u32 + and defines the interrupt number. +- reg : The register bank for the VIC. + +Optional properties: + +- interrupts : Interrupt source for parent controllers if the VIC is nested. + +Example: + + vic0: interrupt-controller at 60000 { + compatible = "arm,pl192-vic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x60000 0x1000>; + };arch/arm/common/Kconfig +1
-0@@ -2,6 +2,7 @@ config ARM_GIC bool config ARM_VIC + select IRQ_DOMAIN bool config ARM_VIC_NRarch/arm/common/vic.c +78
-28@@ -22,6 +22,10 @@#include <linux/init.h> #include <linux/list.h> #include <linux/io.h> +#include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/syscore_ops.h> #include <linux/device.h> #include <linux/amba/bus.h> @@ -29,7 +33,6 @@#include <asm/mach/irq.h> #include <asm/hardware/vic.h> -#ifdef CONFIG_PM /** * struct vic_device - VIC PM device * @irq: The IRQ number for the base of the VIC. @@ -40,6 +43,7 @@* @int_enable: Save for VIC_INT_ENABLE. * @soft_int: Save for VIC_INT_SOFT. * @protect: Save for VIC_PROTECT. +* @domain: The IRQ domain for the VIC. */ struct vic_device {void __iomem *base;@@ -50,13 +54,13 @@ struct vic_device {u32 int_enable;u32 soft_int;u32 protect; +struct irq_domain domain; };/* we cannot allocate memory when VICs are initially registered */ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR ];static int vic_id; -#endif /* CONFIG_PM */ /** * vic_init2 - common initialisation code @@ -156,39 +160,50 @@ static int __init vic_pm_init(void)return 0 ; }late_initcall (vic_pm_init); +#endif /* CONFIG_PM */ /** -* vic_pm_register - Register a VIC for later power management control +* vic_register() - Register a VIC. * @base: The base address of the VIC. * @irq: The base IRQ for the VIC. * @resume_sources: bitmask of interrupts allowed for resume sources. +* @node: The device tree node associated with the VIC. * * Register the VIC with the system device tree so that it can be notified * of suspend and resume requests and ensure that the correct actions are * taken to re-instate the settings on resume. +* +* This also configures the IRQ domain for the VIC. */ -static void __init vic_pm_register (void __iomem *base,unsigned int irq,u32 resume_sources) +static void __init vic_register (void __iomem *base,unsigned int irq, +u32 resume_sources,struct device_node *node) {struct vic_device *v; -if (vic_id >=ARRAY_SIZE (vic_devices)) +if (vic_id >=ARRAY_SIZE (vic_devices)) {printk (KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n" , __func__); -else { - v = &vic_devices[vic_id]; - v->base = base; - v->resume_sources = resume_sources; - v->irq = irq; - vic_id++; +return ; } + + v = &vic_devices[vic_id]; + v->base = base; + v->resume_sources = resume_sources; + v->irq = irq; + vic_id++; + + v->domain.irq_base = irq; + v->domain.nr_irq =32 ; +#ifdef CONFIG_OF_IRQ + v->domain.of_node =of_node_get (node); + v->domain.ops = &irq_domain_simple_ops; +#endif /* CONFIG_OF */ +irq_domain_add (&v->domain); } -#else -static inline void vic_pm_register (void __iomem *base,unsigned int irq,u32 arg1) { } -#endif /* CONFIG_PM */ static void vic_ack_irq (struct irq_data *d) {void __iomem *base =irq_data_get_irq_chip_data (d); -unsigned int irq = d->irq &31 ; +unsigned int irq = d->hwirq;writel (1 << irq, base +VIC_INT_ENABLE_CLEAR );/* moreover, clear the soft-triggered, in case it was the reason */ writel (1 << irq, base +VIC_INT_SOFT_CLEAR );@@ -197,14 +212,14 @@ static void vic_ack_irq(struct irq_data *d)static void vic_mask_irq (struct irq_data *d) {void __iomem *base =irq_data_get_irq_chip_data (d); -unsigned int irq = d->irq &31 ; +unsigned int irq = d->hwirq;writel (1 << irq, base +VIC_INT_ENABLE_CLEAR ); }static void vic_unmask_irq (struct irq_data *d) {void __iomem *base =irq_data_get_irq_chip_data (d); -unsigned int irq = d->irq &31 ; +unsigned int irq = d->hwirq;writel (1 << irq, base +VIC_INT_ENABLE ); }@@ -226,7 +241,7 @@ static struct vic_device *vic_from_irq(unsigned int irq)static int vic_set_wake (struct irq_data *d,unsigned int on) {struct vic_device *v =vic_from_irq (d->irq); -unsigned int off = d->irq &31 ; +unsigned int off = d->hwirq;u32 bit =1 << off;if (!v)@@ -331,15 +346,9 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,vic_set_irq_sources (base, irq_start, vic_sources); } -/** -* vic_init - initialise a vectored interrupt controller -* @base: iomem base address -* @irq_start: starting interrupt number, must be muliple of 32 -* @vic_sources: bitmask of interrupt sources to allow -* @resume_sources: bitmask of interrupt sources to allow for resume -*/ -void __init vic_init (void __iomem *base,unsigned int irq_start, -u32 vic_sources,u32 resume_sources) +static void __init __vic_init (void __iomem *base,unsigned int irq_start, +u32 vic_sources,u32 resume_sources, +struct device_node *node) {unsigned int i;u32 cellid =0 ;@@ -375,5 +384,46 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,vic_set_irq_sources (base, irq_start, vic_sources); -vic_pm_register (base, irq_start, resume_sources); +vic_register (base, irq_start, resume_sources, node); +} + +/** +* vic_init() - initialise a vectored interrupt controller +* @base: iomem base address +* @irq_start: starting interrupt number, must be muliple of 32 +* @vic_sources: bitmask of interrupt sources to allow +* @resume_sources: bitmask of interrupt sources to allow for resume +*/ +void __init vic_init (void __iomem *base,unsigned int irq_start, +u32 vic_sources,u32 resume_sources) +{ +__vic_init (base, irq_start, vic_sources, resume_sources,NULL ); +} + +#ifdef CONFIG_OF +int __init vic_of_init (struct device_node *node,struct device_node *parent) +{ +void __iomem *regs; +int irq_base; + +if (WARN (parent,"non-root VICs are not supported" )) +return -EINVAL ; + + regs =of_iomap (node,0 ); +if (WARN_ON (!regs)) +return -EIO ; + + irq_base =irq_alloc_descs (-1 ,0 ,32 ,numa_node_id ()); +if (WARN_ON (irq_base <0 )) + goto out_unmap; + +__vic_init (regs, irq_base, ~0 , ~0 , node); + +return 0 ; + + out_unmap: +iounmap (regs); + +return -EIO ; } +#endif /* CONFIG OF */ arch/arm/include/asm/hardware/vic.h +0
-0@@ -41,7 +41,15 @@#define VIC_PL192_VECT_ADDR 0xF00#ifndef __ASSEMBLY__
arch/arm/include/asm/hardware/vic.h line 52
Quoted 10 lines
arch/arm/include/asm/hardware/vic.h +7
-1+#include <linux/compiler.h> +#include <linux/types.h> + +struct device_node ;void vic_init (void __iomem *base,unsigned int irq_start,u32 vic_sources,u32 resume_sources); -#endif +#ifdef CONFIG_OF +int vic_of_init (struct device_node *node,struct device_node *parent); +#endif /* CONFIG_OF */
You don't need an ifdef around this.
Rob
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
In reply to Jamie IlesAdd a handler for the VIC that is suitable for MULTI_IRQ_HANDLER platforms. This can replace the ASM entry macros for platforms that use the VIC.
v2: - allow the handler be used for !CONFIG_OF
- use irq_domain_to_irq()
--- arch/arm/common/vic.c | 29 +++++++++++++++++++++++++++++ arch/arm/include/asm/hardware/vic.h | 4 ++++ 2 files changed, 33 insertions(+), 0 deletions(-)
arch/arm/common/vic.c +29 -0
@@ -427,3 +427,32 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)return -EIO ; }#endif /* CONFIG OF */ + +#ifdef CONFIG_MULTI_IRQ_HANDLER +static void vic_single_handle_irq (struct vic_device *vic,struct pt_regs *regs) +{ +u32 stat, irq; +bool handled = false; + +while (!handled) { + stat =readl_relaxed (vic->base +VIC_IRQ_STATUS ); +if (!stat) +break ; + +while (stat) { + irq =fls (stat) -1 ; +handle_IRQ (irq_domain_to_irq (&vic->domain, irq), regs); + stat &= ~(1 << irq); + handled = true; + } + } +} + +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ +int i; + +for (i =0 ; i < vic_id; ++i) +vic_single_handle_irq (&vic_devices[i], regs); +} +#endif /* CONFIG_MULTI_IRQ_HANDLER */
arch/arm/include/asm/hardware/vic.h +4 -0
@@ -45,11 +45,15 @@#include <linux/types.h> struct device_node ; +struct pt_regs ; +void vic_init (void __iomem *base,unsigned int irq_start,u32 vic_sources,u32 resume_sources);#ifdef CONFIG_OF int vic_of_init (struct device_node *node,struct device_node *parent);#endif /* CONFIG_OF */ +void vic_handle_irq (struct pt_regs *regs); +#endif /* __ASSEMBLY__ */ #endif
Signature · 1 line
1.7.4.1
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Review
Quoted 12 lines · Jamie Iles
(quoted diff) +12
-0+static void vic_single_handle_irq(struct vic_device *vic, struct pt_regs *regs) +{ + ? ? ? u32 stat, irq; + ? ? ? bool handled = false; + + ? ? ? while (!handled) { + ? ? ? ? ? ? ? stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); + ? ? ? ? ? ? ? if (!stat) + ? ? ? ? ? ? ? ? ? ? ? break; + + ? ? ? ? ? ? ? while (stat) { + ? ? ? ? ? ? ? ? ? ? ? irq = fls(stat) - 1;
Isn't fls "find last set"?
That means IRQs with higher numbers will be handled first will it not?
For U300 IRQs with lower numbers will be handled first by iteratively testing bit 0 and shifting right:
-1002: tst \irqstat, #1 - bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b
So I would use ffs() for this to work the same way as before in U300.
Since this can have some performance impact, if the platforms differ in whether they handle IRQs from low to high or from high to low might need to be a flag passed in to vic_init() or so...
Yours,
Linus Walleij
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Hi Linus,
Quoted 28 lines · Linus Walleij
Review
Quoted 12 lines · Jamie Iles
(quoted diff) +12
-0+static void vic_single_handle_irq(struct vic_device *vic, struct pt_regs *regs) +{ + ? ? ? u32 stat, irq; + ? ? ? bool handled = false; + + ? ? ? while (!handled) { + ? ? ? ? ? ? ? stat = readl_relaxed(vic->base + VIC_IRQ_STATUS); + ? ? ? ? ? ? ? if (!stat) + ? ? ? ? ? ? ? ? ? ? ? break; + + ? ? ? ? ? ? ? while (stat) { + ? ? ? ? ? ? ? ? ? ? ? irq = fls(stat) - 1;Isn't fls "find last set"?
That means IRQs with higher numbers will be handled first will it not?
For U300 IRQs with lower numbers will be handled first by iteratively testing bit 0 and shifting right:
-1002: tst \irqstat, #1
(quoted diff) +0
-4- bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b
Quoted 6 lines
So I would use
ffs()for this to work the same way as before in U300.Since this can have some performance impact, if the platforms differ in whether they handle IRQs from low to high or from high to low might need to be a flag passed in to
vic_init()or so...
I don't know how important the ordering is, but if it is important then we could have vic_handle_irq_msb_first() and vic_handle_irq_lsb_first() as the handlers so there isn't any additional indirection/selection in the interrupt hot-path.
Jamie
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
In reply to Jamie IlesQuoted 32 lines · Jamie Iles
Add a handler for the VIC that is suitable for
MULTI_IRQ_HANDLERplatforms. This can replace the ASM entry macros for platforms that use the VIC.v2: - allow the handler be used for !CONFIG_OF
- useirq_domain_to_irq()Cc Rob Herring <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Jamie Iles <[email protected]>--- arch/arm/common/vic.c | 29 +++++++++++++++++++++++++++++ arch/arm/include/asm/hardware/vic.h | 4 ++++ 2 files changed, 33 insertions(+), 0 deletions(-)arch/arm/common/vic.c +9
-0@@ -427,3 +427,32 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)return -EIO ; }#endif /* CONFIG OF */ + +#ifdef CONFIG_MULTI_IRQ_HANDLER +static void vic_single_handle_irq (struct vic_device *vic,struct pt_regs *regs) +{ +u32 stat, irq; +bool handled = false; + +while (!handled) { + stat =readl_relaxed (vic->base +VIC_IRQ_STATUS );
arch/arm/common/vic.c int __init vic_of_init(struct device_node *node, struct device_node *parent) · line 448
Quoted 10 lines
arch/arm/common/vic.c +10
-0+if (!stat) +break ; + +while (stat) { + irq =fls (stat) -1 ; +handle_IRQ (irq_domain_to_irq (&vic->domain, irq), regs); + stat &= ~(1 << irq); + handled = true; + } + }
I don't follow why this is written this way. The way I see it, there are two conditions:
1) first read will show no irqs pending (!stat), which will break out of the outer while() loop.
2) or there will be irqs pending, it will enter the second while() loop, which unconditionally sets the handled flag, and causes the outer loop to exit immediately after the inner loop exits.
Why isn't it simply written this way:
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
irq = fls(stat) - 1;
handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
stat &= ~(1 << irq);
}g.
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 8 lines · Grant Likely
Why isn't it simply written this way:
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS);
? ? ? ?while (stat) {
? ? ? ? ? ? ? ?irq = fls(stat) - 1;
? ? ? ? ? ? ? ?handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ?}
That is indeed closer to the assembly loop most platforms have implemented.
Jamie can you test this approach? And also use ffs() insteadof fls()...
Thanks,
Linus Walleij
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 12 lines · Linus Walleij
Quoted 8 lines · Grant Likely
Why isn't it simply written this way:
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS);
? ? ? ?while (stat) {
? ? ? ? ? ? ? ?irq = fls(stat) - 1;
? ? ? ? ? ? ? ?handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ?}
Quoted 5 lines
That is indeed closer to the assembly loop most platforms have implemented.
Jamie can you test this approach? And also use
ffs()insteadoffls()...
OK, here it is (and it works)! That does make it a lot simpler, thanks guys! I've updated the vic-dt branch in my repo too.
Jamie
8<------
From: Jamie Iles <[email protected]>
Subject: [PATCHv3] ARM: vic: MULTI_IRQ_HANDLER handler
Add a handler for the VIC that is suitable for MULTI_IRQ_HANDLER platforms. This can replace the ASM entry macros for platforms that use the VIC.
v3: - simplify irq handling loop as suggested by Grant
- service interrupts from msb->lsb order
v2: - allow the handler be used for !CONFIG_OF
- use irq_domain_to_irq()
--- arch/arm/common/vic.c | 22 ++++++++++++++++++++++ arch/arm/include/asm/hardware/vic.h | 4 ++++ 2 files changed, 26 insertions(+), 0 deletions(-)
arch/arm/common/vic.c +22 -0
@@ -427,3 +427,25 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)return -EIO ; }#endif /* CONFIG OF */ + +#ifdef CONFIG_MULTI_IRQ_HANDLER +static void vic_single_handle_irq (struct vic_device *vic,struct pt_regs *regs) +{ +u32 stat, irq; + + stat =readl_relaxed (vic->base +VIC_IRQ_STATUS ); +while (stat) { + irq =ffs (stat) -1 ; +handle_IRQ (irq_domain_to_irq (&vic->domain, irq), regs); + stat &= ~(1 << irq); + } +} + +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ +int i; + +for (i =0 ; i < vic_id; ++i) +vic_single_handle_irq (&vic_devices[i], regs); +} +#endif /* CONFIG_MULTI_IRQ_HANDLER */
arch/arm/include/asm/hardware/vic.h +4 -0
@@ -45,11 +45,15 @@#include <linux/types.h> struct device_node ; +struct pt_regs ; +void vic_init (void __iomem *base,unsigned int irq_start,u32 vic_sources,u32 resume_sources);#ifdef CONFIG_OF int vic_of_init (struct device_node *node,struct device_node *parent);#endif /* CONFIG_OF */ +void vic_handle_irq (struct pt_regs *regs); +#endif /* __ASSEMBLY__ */ #endif
Signature · 1 line
1.7.4.1
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 32 lines · Jamie Iles
Quoted 12 lines · Linus Walleij
Quoted 8 lines · Grant Likely
Why isn't it simply written this way:
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS);
? ? ? ?while (stat) {
? ? ? ? ? ? ? ?irq = fls(stat) - 1;
? ? ? ? ? ? ? ?handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ?}Quoted 5 lines
That is indeed closer to the assembly loop most platforms have implemented.
Jamie can you test this approach? And also use
ffs()insteadoffls()...OK, here it is (and it works)! That does make it a lot simpler, thanks guys! I've updated the vic-dt branch in my repo too.
Jamie
8<------
From: Jamie Iles <[email protected]>
Subject: [PATCHv3] ARM: vic:MULTI_IRQ_HANDLERhandlerAdd a handler for the VIC that is suitable for
MULTI_IRQ_HANDLERplatforms. This can replace the ASM entry macros for platforms that use the VIC.
Quoted 8 lines
v3: - simplify irq handling loop as suggested by Grant
- service interrupts frommsb->lsborder
v2: - allow the handler be used for !CONFIG_OF
- useirq_domain_to_irq()Cc Rob Herring <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Jamie Iles <[email protected]>
Quoted 58 lines
--- arch/arm/common/vic.c | 22 ++++++++++++++++++++++ arch/arm/include/asm/hardware/vic.h | 4 ++++ 2 files changed, 26 insertions(+), 0 deletions(-)arch/arm/common/vic.c +22
-0@@ -427,3 +427,25 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)return -EIO ; }#endif /* CONFIG OF */ + +#ifdef CONFIG_MULTI_IRQ_HANDLER +static void vic_single_handle_irq (struct vic_device *vic,struct pt_regs *regs) +{ +u32 stat, irq; + + stat =readl_relaxed (vic->base +VIC_IRQ_STATUS ); +while (stat) { + irq =ffs (stat) -1 ; +handle_IRQ (irq_domain_to_irq (&vic->domain, irq), regs); + stat &= ~(1 << irq); + } +} + +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ +int i; + +for (i =0 ; i < vic_id; ++i) +vic_single_handle_irq (&vic_devices[i], regs); +} +#endif /* CONFIG_MULTI_IRQ_HANDLER */ arch/arm/include/asm/hardware/vic.h +4
-0@@ -45,11 +45,15 @@#include <linux/types.h> struct device_node ; +struct pt_regs ; +void vic_init (void __iomem *base,unsigned int irq_start,u32 vic_sources,u32 resume_sources);#ifdef CONFIG_OF int vic_of_init (struct device_node *node,struct device_node *parent);#endif /* CONFIG_OF */ +void vic_handle_irq (struct pt_regs *regs); +#endif /* __ASSEMBLY__ */ #endif Signature · 1 line
1.7.4.1
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
In reply to Jamie IlesQuoted 10 lines · Jamie Iles
arch/arm/common/vic.c +10
-0+#ifdef CONFIG_MULTI_IRQ_HANDLER +static void vic_single_handle_irq (struct vic_device *vic,struct pt_regs *regs) +{ +u32 stat, irq; + + stat =readl_relaxed (vic->base +VIC_IRQ_STATUS ); +while (stat) { + irq =ffs (stat) -1 ; +handle_IRQ (irq_domain_to_irq (&vic->domain, irq), regs); + stat &= ~(1 << irq);
arch/arm/common/vic.c int __init vic_of_init(struct device_node *node, struct device_node *parent) · line 450
Quoted 10 lines
arch/arm/common/vic.c +10
-0+ } +} + +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ +int i; + +for (i =0 ; i < vic_id; ++i) +vic_single_handle_irq (&vic_devices[i], regs); +}
And if we receive another interrupt after the read of the register, we'll have to exit all the way back (possibly to userspace) before re-entering the IRQ handling paths back to this point to process it.
Is there any particular reason folk are destroying the built-in efficiency of the IRQ handling which is common-place in the existing assembly approach?
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 17 lines · Russell King - ARM Linux
Quoted 16 lines · Jamie Iles
arch/arm/common/vic.c +16
-0+#ifdef CONFIG_MULTI_IRQ_HANDLER +static void vic_single_handle_irq (struct vic_device *vic,struct pt_regs *regs) +{ +u32 stat, irq; + + stat =readl_relaxed (vic->base +VIC_IRQ_STATUS ); +while (stat) { + irq =ffs (stat) -1 ; +handle_IRQ (irq_domain_to_irq (&vic->domain, irq), regs); + stat &= ~(1 << irq); + } +} + +asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ +int i;
Quoted 8 lines
arch/arm/common/vic.c int __init vic_of_init(struct device_node *node, struct device_node *parent) · line 450
Quoted 4 lines
arch/arm/common/vic.c +4
-0+ +for (i =0 ; i < vic_id; ++i) +vic_single_handle_irq (&vic_devices[i], regs); +}And if we receive another interrupt after the read of the register, we'll have to exit all the way back (possibly to userspace) before re-entering the IRQ handling paths back to this point to process it.
OK, so how about something like this instead:
static int vic_single_handle_irq(struct vic_device *vic,
struct pt_regs *regs)
{
u32 stat, irq;
int handled = 0;
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
irq = ffs(stat) - 1;
handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
stat &= ~(1 << irq);
handled = 1;
}
return handled;
}asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
{
int i, handled;
do {
handled = 0;
for (i = 0; i < vic_id; ++i)
if (vic_single_handle_irq(&vic_devices[i], regs))
handled = 1;
} while (handled);
}which I think should keep handling IRQ's until no VIC has them pending (or as best can be determined).
Quoted 3 lines
Is there any particular reason folk are destroying the built-in efficiency of the IRQ handling which is common-place in the existing assembly approach?
Well this approach makes a single image kernel a bit easier. The other thing is that it plays a lot nicer with dynamic irq_desc assignment. Grant's IRQ domain patches make this quite easy here, but I can't see an obvious way to do that with the assembly method.
Jamie
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 10 lines · Jamie Iles
Quoted 4 lines · Russell King - ARM Linux
And if we receive another interrupt after the read of the register, we'll have to exit all the way back (possibly to userspace) before re-entering the IRQ handling paths back to this point to process it.
OK, so how about something like this instead:
static int
vic_single_handle_irq(struct vic_device *vic, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct pt_regs *regs)
Is it single really? This handles all active IRQs on the VIC instance. Can it be renamed vic_handle_irq()?
Quoted 12 lines
{
? ? ? ?u32 stat, irq;
? ? ? ?int handled = 0;? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS);
? ? ? ?while (stat) {
? ? ? ? ? ? ? ?irq = ffs(stat) - 1;
? ? ? ? ? ? ? ?handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ? ? ? ? ?handled = 1;
? ? ? ?}
Quoted 2 lines
? ? ? ?return handled;
}
No, if we receive another IRQ *after* the read of the register was the question, right?
Just replace
stat &= ~(1 << irq);
with a second
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
It'll work just fine, the IRQ line should be low when you read it the second time, else it is probably fully proper to call the IRQ handler again anyway.
Just my ?0.01..
Linus Walleij
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 7 lines · Linus Walleij
No, if we receive another IRQ *after* the read of the register was the question, right?
Just replace
stat &= ~(1 << irq);
Quoted 7 lines
with a second
stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS);It'll work just fine, the IRQ line should be low when you read it the second time, else it is probably fully proper to call the IRQ handler again anyway.
It depends on what kind of behaviour you want. There are two solutions:
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
irq = ffs(stat) - 1;
handle_irq(irq);
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
}This gives priority to the lowest numbered interrupts; if these get stuck then they can exclude higher numbered interrupts. This is what we implement in the assembly code versions, and as far as I know, no one has ever complained about that behaviour.
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
while (stat) {
irq = ffs(stat) - 1;
stat &= ~(1 << irq);
handle_irq(irq);
}
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
}This ensures that we process all interrupts found pending before we re-check for any new interrupts pending. Arguably this is a much fairer implementation (and may mean if things get irrevokably stuck, things like sysrq via the console uart may still work.)
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 10 lines · Russell King - ARM Linux
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?while (stat) {
? ? ? ? ? ? ? ?while (stat) {
? ? ? ? ? ? ? ? ? ? ? ?irq = ffs(stat) - 1;
? ? ? ? ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ? ? ? ? ? ? ? ? ?handle_irq(irq);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?stat =readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?}
Quoted 4 lines
This ensures that we process all interrupts found pending before we re-check for any new interrupts pending. ?Arguably this is a much fairer implementation (and may mean if things get irrevokably stuck, things like sysrq via the console uart may still work.)
I really like the looks of this, Jamie can you do it like that?
Maybe some smallish comment about what's going on can be good for future generations reading that code...
Yours,
Linus Walleij
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 13 lines · Linus Walleij
Quoted 10 lines · Russell King - ARM Linux
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?while (stat) {
? ? ? ? ? ? ? ?while (stat) {
? ? ? ? ? ? ? ? ? ? ? ?irq = ffs(stat) - 1;
? ? ? ? ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ? ? ? ? ? ? ? ? ?handle_irq(irq);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?stat =readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?}
Quoted 6 lines
Quoted 4 lines
This ensures that we process all interrupts found pending before we re-check for any new interrupts pending. ?Arguably this is a much fairer implementation (and may mean if things get irrevokably stuck, things like sysrq via the console uart may still work.)
I really like the looks of this, Jamie can you do it like that?
Yup, I'll respin either tonight or tomorrow night and rebase ontop of the asm/exception.h patch. Do we also want the behaviour so that it keeps looping over all VIC's until there are no pending interrupts? I think that's probably worth it.
Quoted 2 lines
Maybe some smallish comment about what's going on can be good for future generations reading that code...
OK, will do.
Thanks Linus and Russell!
Jamie
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
In reply to Linus WalleijQuoted 18 lines · Linus Walleij
Quoted 10 lines · Russell King - ARM Linux
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?while (stat) {
? ? ? ? ? ? ? ?while (stat) {
? ? ? ? ? ? ? ? ? ? ? ?irq = ffs(stat) - 1;
? ? ? ? ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ? ? ? ? ? ? ? ? ?handle_irq(irq);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?stat =readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?}Quoted 4 lines
This ensures that we process all interrupts found pending before we re-check for any new interrupts pending. ?Arguably this is a much fairer implementation (and may mean if things get irrevokably stuck, things like sysrq via the console uart may still work.)
Quoted 4 lines
I really like the looks of this, Jamie can you do it like that?
Maybe some smallish comment about what's going on can be good for future generations reading that code...
Bear in mind that it gets a little more complex when you have more than one VIC, because the outer loop should be across all VICs.
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 19 lines · Russell King - ARM Linux
Quoted 18 lines · Linus Walleij
Quoted 14 lines · Russell King - ARM Linux
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?while (stat) {
? ? ? ? ? ? ? ?while (stat) {
? ? ? ? ? ? ? ? ? ? ? ?irq = ffs(stat) - 1;
? ? ? ? ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ? ? ? ? ? ? ? ? ?handle_irq(irq);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?stat =readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?}This ensures that we process all interrupts found pending before we re-check for any new interrupts pending. ?Arguably this is a much fairer implementation (and may mean if things get irrevokably stuck, things like sysrq via the console uart may still work.)
Quoted 7 lines
Quoted 4 lines
I really like the looks of this, Jamie can you do it like that?
Maybe some smallish comment about what's going on can be good for future generations reading that code...
Bear in mind that it gets a little more complex when you have more than one VIC, because the outer loop should be across all VICs.
OK, so I think what I posted yesterday does that (updated for slightly better naming) and with a description. In the spirit of fairness iterating over the VIC's this way seemed right to me.
/*
* Handle each interrupt in a single VIC. Returns non-zero if we've
* handled at least one interrupt. This does a single read of the
* status register and handles all interrupts in order from LSB first. */
static int handle_one_vic(struct vic_device *vic,
struct pt_regs *regs)
{
u32 stat, irq;
int handled = 0;
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
irq = ffs(stat) - 1;
handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
stat &= ~(1 << irq);
handled = 1;
}
return handled;
}/*
* Keep iterating over all registered VIC's until there are no pending
* interrupts.
*/
asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
{
int i, handled;
do {
for (i = 0, handled = 0; i < vic_id; ++i)
handled |= vic_single_handle_irq(&vic_devices[i],
regs))
} while (handled);
}Jamie
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 25 lines · Jamie Iles
Quoted 24 lines · Russell King - ARM Linux
Quoted 22 lines · Linus Walleij
Quoted 10 lines · Russell King - ARM Linux
? ? ? ?stat =
readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?while (stat) {
? ? ? ? ? ? ? ?while (stat) {
? ? ? ? ? ? ? ? ? ? ? ?irq = ffs(stat) - 1;
? ? ? ? ? ? ? ? ? ? ? ?stat &= ~(1 << irq);
? ? ? ? ? ? ? ? ? ? ? ?handle_irq(irq);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?stat =readl_relaxed(vic->base + VIC_IRQ_STATUS); ? ? ? ?}Quoted 4 lines
This ensures that we process all interrupts found pending before we re-check for any new interrupts pending. ?Arguably this is a much fairer implementation (and may mean if things get irrevokably stuck, things like sysrq via the console uart may still work.)
I really like the looks of this, Jamie can you do it like that?
Maybe some smallish comment about what's going on can be good for future generations reading that code...
Quoted 6 lines
Quoted 2 lines
Bear in mind that it gets a little more complex when you have more than one VIC, because the outer loop should be across all VICs.
OK, so I think what I posted yesterday does that (updated for slightly better naming) and with a description. In the spirit of fairness iterating over the VIC's this way seemed right to me.
Yes.
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
In reply to Russell King - ARM LinuxQuoted 9 lines · Russell King - ARM Linux
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
while (stat) {
while (stat) {
irq = ffs(stat) - 1;
stat &= ~(1 << irq);
handle_irq(irq);
}
stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
}The inner loop could be a do { } while() construct to avoid evaluating stat twice on each outer loop itteration. Maybe gcc is smart enough to notice though, maybe not.
Nicolas
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
In reply to Jamie Iles2011/9/28 Jamie Iles <[email protected]>:
Quoted 19 lines
Add a handler for the VIC that is suitable for
MULTI_IRQ_HANDLERplatforms. ?This can replace the ASM entry macros for platforms that use the VIC.v2: ? ? - allow the handler be used for !CONFIG_OF ? ? ? ?- use
irq_domain_to_irq()Cc Rob Herring <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Jamie Iles <[email protected]>---
?arch/arm/common/vic.c ? ? ? ? ? ? ? | ? 29 +++++++++++++++++++++++++++++ ?arch/arm/include/asm/hardware/vic.h | ? ?4 ++++
?2 files changed, 33 insertions(+), 0 deletions(-)arch/arm/common/vic.c +0
-0
arch/arm/common/vic.c int __init vic_of_init(struct device_node *node, struct device_node *parent) · line 458
Quoted 9 lines
arch/arm/common/vic.c +8
-0+asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ + ? ? ? int i; + + ? ? ? for (i = 0; i < vic_id; ++i) + ? ? ? ? ? ? ? vic_single_handle_irq(&vic_devices[i], regs); +} +#endif /* CONFIG_MULTI_IRQ_HANDLER */
__exception_irq_entry doesn't compile with CONFIG_FUNCTION_GRAPH_TRACER enabled. Either this file, or arch/arm/include/asm/system.h needs an #include <linux/ftrace.h>
Cheers,
Zoltan
PATCH v2 2/10 ARM: vic: MULTI_IRQ_HANDLER handler
Quoted 21 lines · Zoltan Devai
2011/9/28 Jamie Iles <[email protected]>:
Quoted 19 lines
Add a handler for the VIC that is suitable for
MULTI_IRQ_HANDLERplatforms. ?This can replace the ASM entry macros for platforms that use the VIC.v2: ? ? - allow the handler be used for !CONFIG_OF ? ? ? ?- use
irq_domain_to_irq()Cc Rob Herring <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Jamie Iles <[email protected]>---
?arch/arm/common/vic.c ? ? ? ? ? ? ? | ? 29 +++++++++++++++++++++++++++++ ?arch/arm/include/asm/hardware/vic.h | ? ?4 ++++
?2 files changed, 33 insertions(+), 0 deletions(-)arch/arm/common/vic.c +0
-0
Quoted 12 lines
arch/arm/common/vic.c int __init vic_of_init(struct device_node *node, struct device_node *parent) · line 458
Quoted 8 lines
arch/arm/common/vic.c +8
-0+asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) +{ + ? ? ? int i; + + ? ? ? for (i = 0; i < vic_id; ++i) + ? ? ? ? ? ? ? vic_single_handle_irq(&vic_devices[i], regs); +} +#endif /* CONFIG_MULTI_IRQ_HANDLER */
__exception_irq_entrydoesn't compile withCONFIG_FUNCTION_GRAPH_TRACERenabled. Either this file, orarch/arm/include/asm/system.hneeds an #include <linux/ftrace.h>
Thanks Zoltan, I'm just sending a patch now!
Jamie
PATCH v2 3/10 ARM: ep93xx: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for ep93xx to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-ep93xx/adssphere.c | 2 + arch/arm/mach-ep93xx/edb93xx.c | 9 +++++ arch/arm/mach-ep93xx/gesbc9312.c | 2 + arch/arm/mach-ep93xx/include/mach/entry-macro.S | 42 ----------------------- arch/arm/mach-ep93xx/micro9.c | 5 +++ arch/arm/mach-ep93xx/simone.c | 2 + arch/arm/mach-ep93xx/snappercl15.c | 2 + arch/arm/mach-ep93xx/ts72xx.c | 2 + 9 files changed, 25 insertions(+), 42 deletions(-)
arch/arm/Kconfig +1 -0
@@ -377,6 +377,7 @@ config ARCH_EP93XX select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_HOLES_MEMORYMODEL select ARCH_USES_GETTIMEOFFSET + select MULTI_IRQ_HANDLER help This enables support for the Cirrus EP93xx series of CPUs.
arch/arm/mach-ep93xx/adssphere.c +2 -0
@@ -16,6 +16,7 @@#include <mach/hardware.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -36,6 +37,7 @@ MACHINE_START(ADSSPHERE, "ADS Sphere board") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = adssphere_init_machine,MACHINE_END
arch/arm/mach-ep93xx/edb93xx.c +9 -0
@@ -38,6 +38,7 @@#include <mach/fb.h> #include <mach/ep93xx_spi.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -243,6 +244,7 @@ MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -254,6 +256,7 @@ MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -265,6 +268,7 @@ MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -276,6 +280,7 @@ MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -287,6 +292,7 @@ MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board") .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -298,6 +304,7 @@ MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -309,6 +316,7 @@ MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
@@ -320,6 +328,7 @@ MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = edb93xx_init_machine,MACHINE_END
arch/arm/mach-ep93xx/gesbc9312.c +2 -0
@@ -16,6 +16,7 @@#include <mach/hardware.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -36,6 +37,7 @@ MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = gesbc9312_init_machine,MACHINE_END
arch/arm/mach-ep93xx/include/mach/entry-macro.S +0 -42
51 lines not on this page · raw message
arch/arm/mach-ep93xx/micro9.c +5 -0
@@ -18,6 +18,7 @@#include <mach/hardware.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -80,6 +81,7 @@ MACHINE_START(MICRO9, "Contec Micro9-High") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine,MACHINE_END
@@ -91,6 +93,7 @@ MACHINE_START(MICRO9M, "Contec Micro9-Mid") .boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine,MACHINE_END
@@ -102,6 +105,7 @@ MACHINE_START(MICRO9L, "Contec Micro9-Lite") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine,MACHINE_END
@@ -113,6 +117,7 @@ MACHINE_START(MICRO9S, "Contec Micro9-Slim") .boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = micro9_init_machine,MACHINE_END
arch/arm/mach-ep93xx/simone.c +2 -0
@@ -25,6 +25,7 @@#include <mach/hardware.h> #include <mach/fb.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -69,6 +70,7 @@ MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = simone_init_machine,MACHINE_END
arch/arm/mach-ep93xx/snappercl15.c +2 -0
@@ -31,6 +31,7 @@#include <mach/hardware.h> #include <mach/fb.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -166,6 +167,7 @@ MACHINE_START(SNAPPER_CL15, "Bluewater Systems Snapper CL15") .boot_params = EP93XX_SDCE0_PHYS_BASE + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = snappercl15_init_machine,MACHINE_END
arch/arm/mach-ep93xx/ts72xx.c +2 -0
@@ -23,6 +23,7 @@#include <mach/hardware.h> #include <mach/ts72xx.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/map.h> #include <asm/mach/arch.h>
@@ -260,6 +261,7 @@ MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ts72xx_map_io, .init_irq = ep93xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &ep93xx_timer, .init_machine = ts72xx_init_machine,MACHINE_END
Signature · 1 line
1.7.4.1
PATCH v2 3/10 ARM: ep93xx: convert to MULTI_IRQ_HANDLER
Quoted 5 lines · Jamie Iles
- ? ? ? ? ? ? ? .macro ?get_irqnr_and_base, irqnr, irqstat, base, tmp
- ? ? ? ? ? ? ? ldr ? ? \base, =(EP93XX_AHB_VIRT_BASE)
- ? ? ? ? ? ? ? orr ? ? \base, \base, #0x000b0000
- ? ? ? ? ? ? ? mov ? ? \irqnr, #0
- ? ? ? ? ? ? ? ldr ? ? \irqstat, [\base] ? ? ? ? ? ? ? @ lower 32 interrupts
Quoted 8 lines
- ? ? ? ? ? ? ? cmp ? ? \irqstat, #0
- ? ? ? ? ? ? ? bne ? ? 1001f
-
- ? ? ? ? ? ? ? eor ? ? \base, \base, #0x00070000
- ? ? ? ? ? ? ? ldr ? ? \irqstat, [\base] ? ? ? ? ? ? ? @ upper 32 interrupts
- ? ? ? ? ? ? ? cmp ? ? \irqstat, #0
- ? ? ? ? ? ? ? beq ? ? 1002f
- ? ? ? ? ? ? ? mov ? ? \irqnr, #0x20
Two VIC instances again...
Yours,
Linus Walleij
PATCH v2 4/10 ARM: netx: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for netx to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-netx/include/mach/entry-macro.S | 13 ------------- arch/arm/mach-netx/nxdb500.c | 2 ++ arch/arm/mach-netx/nxdkn.c | 2 ++ arch/arm/mach-netx/nxeb500hmi.c | 2 ++ 5 files changed, 7 insertions(+), 13 deletions(-)
arch/arm/Kconfig +1 -0
@@ -416,6 +416,7 @@ config ARCH_NETX select CPU_ARM926T select ARM_VIC select GENERIC_CLOCKEVENTS + select MULTI_IRQ_HANDLER help This enables support for systems based on the Hilscher NetX Soc
arch/arm/mach-netx/include/mach/entry-macro.S +0 -13
@@ -18,22 +18,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <mach/hardware.h> .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - ldr \base, =io_p2v(0x001ff000) - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, [\base, #0] - clz \irqnr, \irqstat - rsb \irqnr, \irqnr, #31 - cmp \irqstat, #0 - .endm -
arch/arm/mach-netx/nxdb500.c +2 -0
@@ -28,6 +28,7 @@#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <mach/eth.h>
@@ -203,6 +204,7 @@ MACHINE_START(NXDB500, "Hilscher nxdb500") .boot_params = 0x80000100, .map_io = netx_map_io, .init_irq = netx_init_irq, + .handle_irq = vic_handle_irq, .timer = &netx_timer, .init_machine = nxdb500_init,MACHINE_END
arch/arm/mach-netx/nxdkn.c +2 -0
@@ -28,6 +28,7 @@#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <mach/eth.h>
@@ -96,6 +97,7 @@ MACHINE_START(NXDKN, "Hilscher nxdkn") .boot_params = 0x80000100, .map_io = netx_map_io, .init_irq = netx_init_irq, + .handle_irq = vic_handle_irq, .timer = &netx_timer, .init_machine = nxdkn_init,MACHINE_END
arch/arm/mach-netx/nxeb500hmi.c +2 -0
@@ -28,6 +28,7 @@#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/hardware/vic.h> #include <mach/netx-regs.h> #include <mach/eth.h>
@@ -180,6 +181,7 @@ MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi") .boot_params = 0x80000100, .map_io = netx_map_io, .init_irq = netx_init_irq, + .handle_irq = vic_handle_irq, .timer = &netx_timer, .init_machine = nxeb500hmi_init,MACHINE_END
Signature · 1 line
1.7.4.1
PATCH v2 5/10 ARM: nomadik: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for nomadik to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-nomadik/board-nhk8815.c | 2 + arch/arm/mach-nomadik/include/mach/entry-macro.S | 30 ---------------------- 3 files changed, 3 insertions(+), 30 deletions(-)
arch/arm/Kconfig +1 -0
@@ -859,6 +859,7 @@ config ARCH_NOMADIK select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB + select MULTI_IRQ_HANDLER help Support for the Nomadik platform by ST-Ericsson
arch/arm/mach-nomadik/board-nhk8815.c +2 -0
@@ -21,6 +21,7 @@#include <linux/mtd/onenand.h> #include <linux/mtd/partitions.h> #include <linux/io.h> +#include <asm/hardware/vic.h> #include <asm/sizes.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -279,6 +280,7 @@ MACHINE_START(NOMADIK, "NHK8815") .boot_params = 0x100, .map_io = cpu8815_map_io, .init_irq = cpu8815_init_irq, + .handle_irq = vic_handle_irq, .timer = &nomadik_timer, .init_machine = nhk8815_platform_init,MACHINE_END
arch/arm/mach-nomadik/include/mach/entry-macro.S +0 -30
@@ -6,38 +6,8 @@ * warranty of any kind, whether express or implied. */ -#include <mach/hardware.h> -#include <mach/irqs.h> - .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - ldr \base, =IO_ADDRESS(NOMADIK_IC_BASE) - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - /* This stanza gets the irq mask from one of two status registers */ - mov \irqnr, #0 - ldr \irqstat, [\base, #VIC_REG_IRQSR0] @ get masked status - cmp \irqstat, #0 - bne 1001f - add \irqnr, \irqnr, #32 - ldr \irqstat, [\base, #VIC_REG_IRQSR1] @ get masked status - -1001: tst \irqstat, #15 - bne 1002f - add \irqnr, \irqnr, #4 - movs \irqstat, \irqstat, lsr #4 - bne 1001b -1002: tst \irqstat, #1 - bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b -1003: /* EQ will be set if no irqs pending */ - .endm
Signature · 1 line
1.7.4.1
PATCH v2 5/10 ARM: nomadik: convert to MULTI_IRQ_HANDLER
Quoted 7 lines · Jamie Iles
- ? ? ? /* This stanza gets the irq mask from one of two status registers */
- ? ? ? mov ? ? \irqnr, #0
- ? ? ? ldr ? ? \irqstat, [\base, #VIC_REG_IRQSR0] ? ? ?@ get masked status
- ? ? ? cmp ? ? \irqstat, #0
- ? ? ? bne ? ? 1001f
- ? ? ? add ? ? \irqnr, \irqnr, #32
- ? ? ? ldr ? ? \irqstat, [\base, #VIC_REG_IRQSR1] ? ? ?@ get masked status
As you can see the Nomadik also has two daisy-chained VICs, just like the U300, so this also breaks.
Yours,
Linus Walleij
PATCH v2 6/10 ARM: s3c64xx: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for s3c64xx to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-s3c64xx/include/mach/entry-macro.S | 7 ++++--- arch/arm/mach-s3c64xx/mach-anw6410.c | 2 ++ arch/arm/mach-s3c64xx/mach-crag6410.c | 2 ++ arch/arm/mach-s3c64xx/mach-hmt.c | 2 ++ arch/arm/mach-s3c64xx/mach-mini6410.c | 2 ++ arch/arm/mach-s3c64xx/mach-ncp.c | 2 ++ arch/arm/mach-s3c64xx/mach-real6410.c | 2 ++ arch/arm/mach-s3c64xx/mach-smartq5.c | 2 ++ arch/arm/mach-s3c64xx/mach-smartq7.c | 2 ++ arch/arm/mach-s3c64xx/mach-smdk6400.c | 2 ++ arch/arm/mach-s3c64xx/mach-smdk6410.c | 2 ++ 12 files changed, 25 insertions(+), 3 deletions(-)
arch/arm/Kconfig +1 -0
@@ -734,6 +734,7 @@ config ARCH_S3C64XX select SAMSUNG_GPIOLIB_4BIT select HAVE_S3C2410_I2C if I2C select HAVE_S3C2410_WATCHDOG if WATCHDOG + select MULTI_IRQ_HANDLER help Samsung S3C64XX series based systems
arch/arm/mach-s3c64xx/include/mach/entry-macro.S +4 -3
@@ -12,7 +12,8 @@ * warranty of any kind, whether express or implied. */ -#include <mach/map.h> -#include <mach/irqs.h> + .macro disable_fiq + .endm -#include <asm/entry-macro-vic2.S> + .macro arch_ret_to_user, tmp1, tmp2 + .endm
arch/arm/mach-s3c64xx/mach-anw6410.c +2 -0
@@ -30,6 +30,7 @@#include <video/platform_lcd.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h>
@@ -236,6 +237,7 @@ MACHINE_START(ANW6410, "A&W6410") .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = anw6410_map_io, .init_machine = anw6410_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-crag6410.c +2 -0
@@ -37,6 +37,7 @@#include <linux/mfd/wm831x/irq.h> #include <linux/mfd/wm831x/gpio.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h>
@@ -768,6 +769,7 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")/* Maintainer: Mark Brown <[email protected]> */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = crag6410_map_io, .init_machine = crag6410_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-hmt.c +2 -0
@@ -29,6 +29,7 @@#include <mach/hardware.h> #include <mach/map.h> +#include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach-types.h>
@@ -267,6 +268,7 @@ MACHINE_START(HMT, "Airgoo-HMT")/* Maintainer: Peter Korsgaard <[email protected]> */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = hmt_map_io, .init_machine = hmt_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-mini6410.c +2 -0
@@ -24,6 +24,7 @@#include <linux/serial_core.h> #include <linux/types.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h>
@@ -351,6 +352,7 @@ MACHINE_START(MINI6410, "MINI6410")/* Maintainer: Darius Augulis <[email protected]> */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = mini6410_map_io, .init_machine = mini6410_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-ncp.c +2 -0
@@ -25,6 +25,7 @@#include <video/platform_lcd.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h>
@@ -99,6 +100,7 @@ MACHINE_START(NCP, "NCP")/* Maintainer: Samsung Electronics */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = ncp_map_io, .init_machine = ncp_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-real6410.c +2 -0
@@ -25,6 +25,7 @@#include <linux/serial_core.h> #include <linux/types.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h>
@@ -332,6 +333,7 @@ MACHINE_START(REAL6410, "REAL6410") .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = real6410_map_io, .init_machine = real6410_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-smartq5.c +2 -0
@@ -17,6 +17,7 @@#include <linux/leds.h> #include <linux/platform_device.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -148,6 +149,7 @@ MACHINE_START(SMARTQ5, "SmartQ 5")/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = smartq_map_io, .init_machine = smartq5_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-smartq7.c +2 -0
@@ -17,6 +17,7 @@#include <linux/leds.h> #include <linux/platform_device.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -164,6 +165,7 @@ MACHINE_START(SMARTQ7, "SmartQ 7")/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */ .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = smartq_map_io, .init_machine = smartq7_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-smdk6400.c +2 -0
@@ -22,6 +22,7 @@#include <asm/mach-types.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h>
@@ -88,6 +89,7 @@ MACHINE_START(SMDK6400, "SMDK6400") .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6400_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdk6400_map_io, .init_machine = smdk6400_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s3c64xx/mach-smdk6410.c +2 -0
@@ -43,6 +43,7 @@#include <video/platform_lcd.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/irq.h>
@@ -745,6 +746,7 @@ MACHINE_START(SMDK6410, "SMDK6410") .boot_params = S3C64XX_PA_SDRAM + 0x100, .init_irq = s3c6410_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdk6410_map_io, .init_machine = smdk6410_machine_init, .timer = &s3c24xx_timer,
Signature · 1 line
1.7.4.1
PATCH v2 7/10 ARM: spear: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for spear to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-spear3xx/include/mach/entry-macro.S | 27 --------------- arch/arm/mach-spear3xx/spear300_evb.c | 2 + arch/arm/mach-spear3xx/spear310_evb.c | 2 + arch/arm/mach-spear3xx/spear320_evb.c | 2 + arch/arm/mach-spear6xx/include/mach/entry-macro.S | 36 --------------------- arch/arm/mach-spear6xx/spear600_evb.c | 2 + 7 files changed, 9 insertions(+), 63 deletions(-)
arch/arm/Kconfig +1 -0
@@ -897,6 +897,7 @@ config PLAT_SPEAR select CLKSRC_MMIO select GENERIC_CLOCKEVENTS select HAVE_CLK + select MULTI_IRQ_HANDLER help Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
arch/arm/mach-spear3xx/include/mach/entry-macro.S +0 -27
@@ -11,35 +11,8 @@ * warranty of any kind, whether express or implied. */ -#include <asm/hardware/vic.h> -#include <mach/hardware.h> - .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =VA_SPEAR3XX_ML1_VIC_BASE - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get status - teq \irqstat, #0 - beq 1001f @ this will set/reset - @ zero register - /* - * Following code will find bit position of least significang - * bit set in irqstat, using following equation - * least significant bit set in n = (n & ~(n-1)) - */ - sub \tmp, \irqstat, #1 @ tmp = irqstat - 1 - mvn \tmp, \tmp @ tmp = ~tmp - and \irqstat, \irqstat, \tmp @ irqstat &= tmp - /* Now, irqstat is = bit no. of 1st bit set in vic irq status */ - clz \tmp, \irqstat @ tmp = leading zeros - rsb \irqnr, \tmp, #0x1F @ irqnr = 32 - tmp - 1 - -1001: /* EQ will be set if no irqs pending */ - .endm
arch/arm/mach-spear3xx/spear300_evb.c +2 -0
@@ -11,6 +11,7 @@* warranty of any kind, whether express or implied. */ +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h>
@@ -67,6 +68,7 @@ MACHINE_START(SPEAR300, "ST-SPEAR300-EVB") .boot_params = 0x00000100, .map_io = spear3xx_map_io, .init_irq = spear3xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &spear3xx_timer, .init_machine = spear300_evb_init,MACHINE_END
arch/arm/mach-spear3xx/spear310_evb.c +2 -0
@@ -11,6 +11,7 @@* warranty of any kind, whether express or implied. */ +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h>
@@ -73,6 +74,7 @@ MACHINE_START(SPEAR310, "ST-SPEAR310-EVB") .boot_params = 0x00000100, .map_io = spear3xx_map_io, .init_irq = spear3xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &spear3xx_timer, .init_machine = spear310_evb_init,MACHINE_END
arch/arm/mach-spear3xx/spear320_evb.c +2 -0
@@ -11,6 +11,7 @@* warranty of any kind, whether express or implied. */ +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h>
@@ -71,6 +72,7 @@ MACHINE_START(SPEAR320, "ST-SPEAR320-EVB") .boot_params = 0x00000100, .map_io = spear3xx_map_io, .init_irq = spear3xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &spear3xx_timer, .init_machine = spear320_evb_init,MACHINE_END
arch/arm/mach-spear6xx/include/mach/entry-macro.S +0 -36
@@ -11,44 +11,8 @@ * warranty of any kind, whether express or implied. */ -#include <asm/hardware/vic.h> -#include <mach/hardware.h> - .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, =VA_SPEAR6XX_CPU_VIC_PRI_BASE - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get status - mov \irqnr, #0 - teq \irqstat, #0 - bne 1001f - ldr \base, =VA_SPEAR6XX_CPU_VIC_SEC_BASE - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get status - teq \irqstat, #0 - beq 1002f @ this will set/reset - @ zero register - mov \irqnr, #32 -1001: - /* - * Following code will find bit position of least significang - * bit set in irqstat, using following equation - * least significant bit set in n = (n & ~(n-1)) - */ - sub \tmp, \irqstat, #1 @ tmp = irqstat - 1 - mvn \tmp, \tmp @ tmp = ~tmp - and \irqstat, \irqstat, \tmp @ irqstat &= tmp - /* Now, irqstat is = bit no. of 1st bit set in vic irq status */ - clz \tmp, \irqstat @ tmp = leading zeros - - rsb \tmp, \tmp, #0x1F @ tmp = 32 - tmp - 1 - add \irqnr, \irqnr, \tmp - -1002: /* EQ will be set if no irqs pending */ - .endm
arch/arm/mach-spear6xx/spear600_evb.c +2 -0
@@ -11,6 +11,7 @@* warranty of any kind, whether express or implied. */ +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h>
@@ -46,6 +47,7 @@ MACHINE_START(SPEAR600, "ST-SPEAR600-EVB") .boot_params = 0x00000100, .map_io = spear6xx_map_io, .init_irq = spear6xx_init_irq, + .handle_irq = vic_handle_irq, .timer = &spear6xx_timer, .init_machine = spear600_evb_init,MACHINE_END
Signature · 1 line
1.7.4.1
PATCH v2 8/10 ARM: u300: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for u300 to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-u300/include/mach/entry-macro.S | 24 ------------------------ arch/arm/mach-u300/u300.c | 2 ++ 3 files changed, 3 insertions(+), 24 deletions(-)
arch/arm/Kconfig +1 -0
@@ -838,6 +838,7 @@ config ARCH_U300 select CLKDEV_LOOKUP select HAVE_MACH_CLKDEV select GENERIC_GPIO + select MULTI_IRQ_HANDLER help Support for ST-Ericsson U300 series mobile platforms.
arch/arm/mach-u300/include/mach/entry-macro.S +0 -24
@@ -8,33 +8,9 @@ * Low-level IRQ helper macros for ST-Ericsson U300 * Author: Linus Walleij <[email protected]> */ -#include <mach/hardware.h> -#include <asm/hardware/vic.h> .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status - mov \irqnr, #0 - teq \irqstat, #0 - bne 1002f -1001: ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status - mov \irqnr, #32 - teq \irqstat, #0 - beq 1003f -1002: tst \irqstat, #1 - bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b -1003: /* EQ will be set if no irqs pending */ - .endm
arch/arm/mach-u300/u300.c +2 -0
@@ -19,6 +19,7 @@#include <linux/io.h> #include <mach/hardware.h> #include <mach/platform.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/memory.h>
@@ -65,6 +66,7 @@ MACHINE_START(U300, MACH_U300_STRING) .map_io = u300_map_io, .reserve = u300_reserve, .init_irq = u300_init_irq, + .handle_irq = vic_handle_irq, .timer = &u300_timer, .init_machine = u300_init_machine,MACHINE_END
Signature · 1 line
1.7.4.1
PATCH v2 8/10 ARM: u300: convert to MULTI_IRQ_HANDLER
Hold your horses:
Quoted 30 lines · Jamie Iles
arch/arm/mach-u300/include/mach/entry-macro.S +0
-0@@ -8,33 +8,9 @@?* Low-level IRQ helper macros for ST-Ericsson U300 ?* Author: Linus Walleij <[email protected]> ?*/
arch/arm/mach-u300/include/mach/entry-macro.S +0
-2-#include <mach/hardware.h> -#include <asm/hardware/vic.h>? ? ? ?.macro ?disable_fiq
? ? ? ?.endm- ? ? ? .macro ?get_irqnr_preamble, base, tmp
- ? ? ? .endm
-
? ? ? ?.macro ?arch_ret_to_user, tmp1, tmp2
? ? ? ?.endm
-
- ? ? ? .macro ?get_irqnr_and_base, irqnr, irqstat, base, tmp
- ? ? ? ldr ? ? \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE
- ? ? ? ldr ? ? \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
- ? ? ? mov ? ? \irqnr, #0
- ? ? ? teq ? ? \irqstat, #0
- ? ? ? bne ? ? 1002f
-1001: ?ldr ? ? \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE
- ? ? ? ldr ? ? \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
- ? ? ? mov ? ? \irqnr, #32
- ? ? ? teq ? ? \irqstat, #0
Quoted 8 lines
- ? ? ? beq ? ? 1003f
-1002: ?tst ? ? \irqstat, #1
- ? ? ? bne ? ? 1003f
- ? ? ? add ? ? \irqnr, \irqnr, #1
- ? ? ? movs ? ?\irqstat, \irqstat, lsr #1
- ? ? ? bne ? ? 1002b
-1003: ? ? ? ? ?/* EQ will be set if no irqs pending */
- ? ? ? .endm
When I inspect patch 2 in this series I get the feeling that it assumes that there is one and only one VIC bank with 32 interrupts involved. This is not the case in the U300, it has 64 possible IRQ sources by OR:in the output IRQ signal from two VIC:s and feeding the resulting IRQ line into the CPU.
So in the code above we first check the 32 bits at the first VIC instance, and if that is zero we go on to check the other 32 bits.
vic_single_handle_irq() needs to be modified to handle several ranges or atleast two.
Note that in mach-u300/core.c we initialize each VIC like this:vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]); vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
So I think the easiest may be to let vic_init() add registered VIC ranges to a list or array, and increas some num_vics variable to that vic_single_handle_irq() can traverse both ranges in order.
Yours,
Linus Walleij
PATCH v2 8/10 ARM: u300: convert to MULTI_IRQ_HANDLER
Hi Linus,
Quoted 40 lines · Linus Walleij
Hold your horses:
Quoted 36 lines · Jamie Iles
arch/arm/mach-u300/include/mach/entry-macro.S +0
-0@@ -8,33 +8,9 @@?* Low-level IRQ helper macros for ST-Ericsson U300 ?* Author: Linus Walleij <[email protected]> ?*/
arch/arm/mach-u300/include/mach/entry-macro.S +0
-2-#include <mach/hardware.h> -#include <asm/hardware/vic.h>? ? ? ?.macro ?disable_fiq
? ? ? ?.endm- ? ? ? .macro ?get_irqnr_preamble, base, tmp
- ? ? ? .endm
-
? ? ? ?.macro ?arch_ret_to_user, tmp1, tmp2
? ? ? ?.endm
-
- ? ? ? .macro ?get_irqnr_and_base, irqnr, irqstat, base, tmp
- ? ? ? ldr ? ? \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE
- ? ? ? ldr ? ? \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
- ? ? ? mov ? ? \irqnr, #0
- ? ? ? teq ? ? \irqstat, #0
- ? ? ? bne ? ? 1002f
-1001: ?ldr ? ? \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE
- ? ? ? ldr ? ? \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
- ? ? ? mov ? ? \irqnr, #32
- ? ? ? teq ? ? \irqstat, #0
- ? ? ? beq ? ? 1003f
-1002: ?tst ? ? \irqstat, #1
- ? ? ? bne ? ? 1003f
- ? ? ? add ? ? \irqnr, \irqnr, #1
- ? ? ? movs ? ?\irqstat, \irqstat, lsr #1
- ? ? ? bne ? ? 1002b
Quoted 8 lines
Quoted 2 lines
-1003: ? ? ? ? ?/* EQ will be set if no irqs pending */
- ? ? ? .endmWhen I inspect patch 2 in this series I get the feeling that it assumes that there is one and only one VIC bank with 32 interrupts involved. This is not the case in the U300, it has 64 possible IRQ sources by OR:in the output IRQ signal from two VIC:s and feeding the resulting IRQ line into the CPU.
No, it will handle more than one vic, and it will check them in the order the vic_init() is called. I've tested this on picoxcell that has 2 vic's in the same configuration as this.
Quoted 5 lines
So in the code above we first check the 32 bits at the first VIC instance, and if that is zero we go on to check the other 32 bits.
vic_single_handle_irq()needs to be modified to handle several ranges or atleast two.
The platform IRQ handler is actually vic_handle_irq() that internally calls vic_single_handle_irq() for each registered vic (in the order of registration).
Quoted 8 lines
Note that in
mach-u300/core.cwe initialize each VIC like this:vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);So I think the easiest may be to let
vic_init()add registered VIC ranges to a list or array, and increas somenum_vicsvariable to thatvic_single_handle_irq()can traverse both ranges in order.
Jamie
PATCH v2 8/10 ARM: u300: convert to MULTI_IRQ_HANDLER
Quoted 6 lines · Jamie Iles
Quoted 2 lines
vic_single_handle_irq()needs to be modified to handle several ranges or atleast two.The platform IRQ handler is actually
vic_handle_irq()that internally callsvic_single_handle_irq()for each registered vic (in the order of registration).
Ah I get it I'm dead wrong as usual :-)
I tried to apply them to test but Iget into dependency trouble with the referenced required patches, do you have some handy git branch with all stuff applied in order that I can pull in and test off?
Yours,
Linus Walleij
PATCH v2 8/10 ARM: u300: convert to MULTI_IRQ_HANDLER
Quoted 9 lines · Linus Walleij
Quoted 6 lines · Jamie Iles
Quoted 2 lines
vic_single_handle_irq()needs to be modified to handle several ranges or atleast two.The platform IRQ handler is actually
vic_handle_irq()that internally callsvic_single_handle_irq()for each registered vic (in the order of registration).
Quoted 6 lines
Ah I get it I'm dead wrong as usual :-)
I tried to apply them to test but Iget into dependency trouble with the referenced required patches, do you have some handy git branch with all stuff applied in order that I can pull in and test off?
Sure,
git://github.com/jamieiles/linux-2.6-ji.git vic-dt
has all of the dependencies in there too. Thanks for taking a look at the patches Linus!
Jamie
PATCH v2 9/10 ARM: versatile: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for versatile to help building multi platform kernels.
--- arch/arm/Kconfig | 1 + arch/arm/mach-versatile/include/mach/entry-macro.S | 30 -------------------- arch/arm/mach-versatile/versatile_ab.c | 2 + arch/arm/mach-versatile/versatile_dt.c | 2 + arch/arm/mach-versatile/versatile_pb.c | 2 + 5 files changed, 7 insertions(+), 30 deletions(-)
arch/arm/Kconfig +1 -0
@@ -277,6 +277,7 @@ config ARCH_VERSATILE select PLAT_VERSATILE_CLCD select PLAT_VERSATILE_FPGA_IRQ select ARM_TIMER_SP804 + select MULTI_IRQ_HANDLER help This enables support for ARM Ltd Versatile board.
arch/arm/mach-versatile/include/mach/entry-macro.S +0 -30
@@ -7,39 +7,9 @@ * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ -#include <mach/hardware.h> -#include <mach/platform.h> -#include <asm/hardware/vic.h> .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - ldr \base, =IO_ADDRESS(VERSATILE_VIC_BASE) - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status - mov \irqnr, #0 - teq \irqstat, #0 - beq 1003f - -1001: tst \irqstat, #15 - bne 1002f - add \irqnr, \irqnr, #4 - movs \irqstat, \irqstat, lsr #4 - bne 1001b -1002: tst \irqstat, #1 - bne 1003f - add \irqnr, \irqnr, #1 - movs \irqstat, \irqstat, lsr #1 - bne 1002b -1003: /* EQ will be set if no irqs pending */ - -@ clz \irqnr, \irqstat - at 1003: /* EQ will be set if we reach MAXIRQNUM */ - .endm -
arch/arm/mach-versatile/versatile_ab.c +2 -0
@@ -27,6 +27,7 @@#include <mach/hardware.h> #include <asm/irq.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -39,6 +40,7 @@ MACHINE_START(VERSATILE_AB, "ARM-Versatile AB") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, + .handle_irq = vic_handle_irq, .timer = &versatile_timer, .init_machine = versatile_init,MACHINE_END
arch/arm/mach-versatile/versatile_dt.c +2 -0
@@ -24,6 +24,7 @@#include <linux/init.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <asm/hardware/vic.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -45,6 +46,7 @@ DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, + .handle_irq = vic_handle_irq, .timer = &versatile_timer, .init_machine = versatile_dt_init, .dt_compat = versatile_dt_match,
arch/arm/mach-versatile/versatile_pb.c +2 -0
@@ -28,6 +28,7 @@#include <linux/io.h> #include <mach/hardware.h> +#include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach-types.h>
@@ -107,6 +108,7 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, + .handle_irq = vic_handle_irq, .timer = &versatile_timer, .init_machine = versatile_pb_init,MACHINE_END
Signature · 1 line
1.7.4.1
PATCH v2 10/10 ARM: samsung: convert to MULTI_IRQ_HANDLER
In reply to Jamie IlesNow that there is a generic IRQ handler for multiple VIC devices use it for samsung to help building multi platform kernels.
--- arch/arm/Kconfig | 3 ++ arch/arm/mach-s5p64x0/include/mach/entry-macro.S | 7 ++-- arch/arm/mach-s5p64x0/mach-smdk6440.c | 2 + arch/arm/mach-s5p64x0/mach-smdk6450.c | 2 + arch/arm/mach-s5pc100/include/mach/entry-macro.S | 25 --------------- arch/arm/mach-s5pc100/mach-smdkc100.c | 2 + arch/arm/mach-s5pv210/include/mach/entry-macro.S | 37 ---------------------- arch/arm/mach-s5pv210/mach-aquila.c | 2 + arch/arm/mach-s5pv210/mach-goni.c | 2 + arch/arm/mach-s5pv210/mach-smdkc110.c | 2 + arch/arm/mach-s5pv210/mach-smdkv210.c | 2 + arch/arm/mach-s5pv210/mach-torbreck.c | 2 + 12 files changed, 23 insertions(+), 65 deletions(-)
arch/arm/Kconfig +3 -0
@@ -751,6 +751,7 @@ config ARCH_S5P64X0 select HAVE_SCHED_CLOCK select HAVE_S3C2410_I2C if I2C select HAVE_S3C_RTC if RTC_CLASS + select MULTI_IRQ_HANDLER help Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440, SMDK6450.
@@ -766,6 +767,7 @@ config ARCH_S5PC100 select HAVE_S3C2410_I2C if I2C select HAVE_S3C_RTC if RTC_CLASS select HAVE_S3C2410_WATCHDOG if WATCHDOG + select MULTI_IRQ_HANDLER help Samsung S5PC100 series based systems
@@ -785,6 +787,7 @@ config ARCH_S5PV210 select HAVE_S3C2410_I2C if I2C select HAVE_S3C_RTC if RTC_CLASS select HAVE_S3C2410_WATCHDOG if WATCHDOG + select MULTI_IRQ_HANDLER help Samsung S5PV210/S5PC110 series based systems
arch/arm/mach-s5p64x0/include/mach/entry-macro.S +4 -3
@@ -10,7 +10,8 @@ * published by the Free Software Foundation. */ -#include <mach/map.h> -#include <plat/irqs.h> + .macro disable_fiq + .endm -#include <asm/entry-macro-vic2.S> + .macro arch_ret_to_user, tmp1, tmp2 + .endm
arch/arm/mach-s5p64x0/mach-smdk6440.c +2 -0
@@ -24,6 +24,7 @@#include <linux/gpio.h> #include <linux/pwm_backlight.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h>
@@ -174,6 +175,7 @@ MACHINE_START(SMDK6440, "SMDK6440") .boot_params = S5P64X0_PA_SDRAM + 0x100, .init_irq = s5p6440_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdk6440_map_io, .init_machine = smdk6440_machine_init, .timer = &s5p_timer,
arch/arm/mach-s5p64x0/mach-smdk6450.c +2 -0
@@ -24,6 +24,7 @@#include <linux/gpio.h> #include <linux/pwm_backlight.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/irq.h>
@@ -193,6 +194,7 @@ MACHINE_START(SMDK6450, "SMDK6450") .boot_params = S5P64X0_PA_SDRAM + 0x100, .init_irq = s5p6450_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdk6450_map_io, .init_machine = smdk6450_machine_init, .timer = &s5p_timer,
arch/arm/mach-s5pc100/include/mach/entry-macro.S +0 -25
@@ -12,39 +12,14 @@ * warranty of any kind, whether express or implied. */ -#include <asm/hardware/vic.h> -#include <mach/map.h> -#include <plat/irqs.h> - .macro disable_fiq .endm .macro get_irqnr_preamble, base, tmp - ldr \base, =VA_VIC0 .endm .macro arch_ret_to_user, tmp1, tmp2 .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - @ check the vic0 - mov \irqnr, # S5P_IRQ_OFFSET + 31 - ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] - teq \irqstat, #0 - - @ otherwise try vic1 - addeq \tmp, \base, #(VA_VIC1 - VA_VIC0) - addeq \irqnr, \irqnr, #32 - ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] - teqeq \irqstat, #0 - - @ otherwise try vic2 - addeq \tmp, \base, #(VA_VIC2 - VA_VIC0) - addeq \irqnr, \irqnr, #32 - ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] - teqeq \irqstat, #0 - - clzne \irqstat, \irqstat - subne \irqnr, \irqnr, \irqstat .endm
arch/arm/mach-s5pc100/mach-smdkc100.c +2 -0
@@ -25,6 +25,7 @@#include <linux/input.h> #include <linux/pwm_backlight.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h>
@@ -256,6 +257,7 @@ MACHINE_START(SMDKC100, "SMDKC100")/* Maintainer: Byungho Min <[email protected]> */ .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pc100_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdkc100_map_io, .init_machine = smdkc100_machine_init, .timer = &s3c24xx_timer,
arch/arm/mach-s5pv210/include/mach/entry-macro.S +0 -37
@@ -10,45 +10,8 @@ * published by the Free Software Foundation. */ -#include <asm/hardware/vic.h> -#include <mach/map.h> -#include <plat/irqs.h> - .macro disable_fiq .endm - .macro get_irqnr_preamble, base, tmp - ldr \base, =VA_VIC0 - .endm - .macro arch_ret_to_user, tmp1, tmp2 .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - @ check the vic0 - mov \irqnr, # S5P_IRQ_OFFSET + 31 - ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] - teq \irqstat, #0 - - @ otherwise try vic1 - addeq \tmp, \base, #(VA_VIC1 - VA_VIC0) - addeq \irqnr, \irqnr, #32 - ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] - teqeq \irqstat, #0 - - @ otherwise try vic2 - addeq \tmp, \base, #(VA_VIC2 - VA_VIC0) - addeq \irqnr, \irqnr, #32 - ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] - teqeq \irqstat, #0 - - @ otherwise try vic3 - addeq \tmp, \base, #(VA_VIC3 - VA_VIC0) - addeq \irqnr, \irqnr, #32 - ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] - teqeq \irqstat, #0 - - clzne \irqstat, \irqstat - subne \irqnr, \irqnr, \irqstat - .endm
arch/arm/mach-s5pv210/mach-aquila.c +2 -0
@@ -22,6 +22,7 @@#include <linux/input.h> #include <linux/gpio.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h>
@@ -680,6 +681,7 @@ MACHINE_START(AQUILA, "Aquila")Kyungmin Park <[email protected]> */ .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pv210_init_irq, + .handle_irq = vic_handle_irq, .map_io = aquila_map_io, .init_machine = aquila_machine_init, .timer = &s5p_timer,
arch/arm/mach-s5pv210/mach-goni.c +2 -0
@@ -27,6 +27,7 @@#include <linux/gpio.h> #include <linux/interrupt.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h>
@@ -899,6 +900,7 @@ MACHINE_START(GONI, "GONI")/* Maintainers: Kyungmin Park <[email protected]> */ .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pv210_init_irq, + .handle_irq = vic_handle_irq, .map_io = goni_map_io, .init_machine = goni_machine_init, .timer = &s5p_timer,
arch/arm/mach-s5pv210/mach-smdkc110.c +2 -0
@@ -15,6 +15,7 @@#include <linux/i2c.h> #include <linux/sysdev.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h>
@@ -138,6 +139,7 @@ MACHINE_START(SMDKC110, "SMDKC110")/* Maintainer: Kukjin Kim <[email protected]> */ .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pv210_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdkc110_map_io, .init_machine = smdkc110_machine_init, .timer = &s5p_timer,
arch/arm/mach-s5pv210/mach-smdkv210.c +2 -0
@@ -20,6 +20,7 @@#include <linux/delay.h> #include <linux/pwm_backlight.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h>
@@ -321,6 +322,7 @@ MACHINE_START(SMDKV210, "SMDKV210")/* Maintainer: Kukjin Kim <[email protected]> */ .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pv210_init_irq, + .handle_irq = vic_handle_irq, .map_io = smdkv210_map_io, .init_machine = smdkv210_machine_init, .timer = &s5p_timer,
arch/arm/mach-s5pv210/mach-torbreck.c +2 -0
@@ -14,6 +14,7 @@#include <linux/init.h> #include <linux/serial_core.h> +#include <asm/hardware/vic.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/setup.h>
@@ -127,6 +128,7 @@ MACHINE_START(TORBRECK, "TORBRECK")/* Maintainer: Hyunchul Ko <[email protected]> */ .boot_params = S5P_PA_SDRAM + 0x100, .init_irq = s5pv210_init_irq, + .handle_irq = vic_handle_irq, .map_io = torbreck_map_io, .init_machine = torbreck_machine_init, .timer = &s5p_timer,
Signature · 1 line
1.7.4.1