From e03f9088e22ca7e2b0de826466540e2527518e52 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 3 Dec 2014 21:18:03 +0900 Subject: irqchip: renesas-intc-irqpin: r8a7779 IRLM setup support Add r8a7779 specific support for IRLM bit configuration in the INTC-IRQPIN driver. Without this code we need special workaround code in arch/arm/mach-shmobile. The IRLM bit for the INTC hardware exists on various older SH-based SoCs and is used to select between two modes for the external interrupt pins IRQ0 to IRQ3: IRLM = 0: (default from reset on r8a7779) In this mode the pins IRQ0 to IRQ3 are used together to give a value between 0 and 15 to the SoC. External logic is required for masking. This mode is not supported by the INTC-IRQPIN driver. IRLM = 1: (needs this patch or configuration elsewhere) In this mode IRQ0 to IRQ3 operate as 4 individual external interrupt pins. In this mode the SMSC ethernet chip can be used via IRQ1 on r8a7779 Marzen. This mode is the only supported mode by the INTC-IRQPIN driver. For this patch to work the r8a7779 DTS needs to pass the ICR0 register as the last register bank. Signed-off-by: Magnus Damm Cc: Magnus Damm Cc: horms@verge.net.au Cc: jason@lakedaemon.net Link: http://lkml.kernel.org/r/20141203121803.5936.35881.sendpatchset@w520 Signed-off-by: Thomas Gleixner --- .../devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt index c73acd060093..4f7946ae8adc 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt @@ -9,6 +9,11 @@ Required properties: - "renesas,intc-irqpin-r8a7778" (R-Car M1A) - "renesas,intc-irqpin-r8a7779" (R-Car H1) - "renesas,intc-irqpin-sh73a0" (SH-Mobile AG5) + +- reg: Base address and length of each register bank used by the external + IRQ pins driven by the interrupt controller hardware module. The base + addresses, length and number of required register banks varies with soctype. + - #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in interrupts.txt in this directory -- cgit v1.2.3 From 19f92b237b1700d30b788f00b16a627ffbfdf0e5 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 13 Jan 2015 14:23:25 -0800 Subject: irqchip: omap-intc: Fix support for dm814 and dm816 On dm81xx we have 128 interrupts like am33xx has. Let's add compatible flags for dm814x and dm816x, and document the existing binding. As the dm81xx are booting in device tree only mode, we can now also remove ti81xx_init_irq() legacy function. Signed-off-by: Tony Lindgren Reviewed-by: Felipe Balbi Cc: Brian Hutchinson Cc: Jason Cooper Link: http://lkml.kernel.org/r/1421187806-6804-2-git-send-email-tony@atomide.com Signed-off-by: Thomas Gleixner --- .../interrupt-controller/ti,omap-intc-irq.txt | 28 ++++++++++++++++++++++ drivers/irqchip/irq-omap-intc.c | 14 ++++------- include/linux/irqchip/irq-omap-intc.h | 1 - 3 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt new file mode 100644 index 000000000000..38ce5d037722 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt @@ -0,0 +1,28 @@ +Omap2/3 intc controller + +On TI omap2 and 3 the intc interrupt controller can provide +96 or 128 IRQ signals to the ARM host depending on the SoC. + +Required Properties: +- compatible: should be one of + "ti,omap2-intc" + "ti,omap3-intc" + "ti,dm814-intc" + "ti,dm816-intc" + "ti,am33xx-intc" + +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode interrupt + source, should be 1 for intc +- interrupts: interrupt reference to primary interrupt controller + +Please refer to interrupts.txt in this directory for details of the common +Interrupt Controllers bindings used by client devices. + +Example: + intc: interrupt-controller@48200000 { + compatible = "ti,omap3-intc"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x48200000 0x1000>; + }; diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c index c03f140acbae..b444d0e48f1f 100644 --- a/drivers/irqchip/irq-omap-intc.c +++ b/drivers/irqchip/irq-omap-intc.c @@ -380,14 +380,6 @@ void __init omap3_init_irq(void) set_handle_irq(omap_intc_handle_irq); } -void __init ti81xx_init_irq(void) -{ - omap_nr_irqs = 96; - omap_nr_pending = 4; - omap_init_irq(OMAP34XX_IC_BASE, NULL); - set_handle_irq(omap_intc_handle_irq); -} - static int __init intc_of_init(struct device_node *node, struct device_node *parent) { @@ -399,7 +391,9 @@ static int __init intc_of_init(struct device_node *node, if (WARN_ON(!node)) return -ENODEV; - if (of_device_is_compatible(node, "ti,am33xx-intc")) { + if (of_device_is_compatible(node, "ti,dm814-intc") || + of_device_is_compatible(node, "ti,dm816-intc") || + of_device_is_compatible(node, "ti,am33xx-intc")) { omap_nr_irqs = 128; omap_nr_pending = 4; } @@ -415,4 +409,6 @@ static int __init intc_of_init(struct device_node *node, IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init); IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init); +IRQCHIP_DECLARE(dm814x_intc, "ti,dm814-intc", intc_of_init); +IRQCHIP_DECLARE(dm816x_intc, "ti,dm816-intc", intc_of_init); IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init); diff --git a/include/linux/irqchip/irq-omap-intc.h b/include/linux/irqchip/irq-omap-intc.h index e06b370cfc0d..bda426ab0ab7 100644 --- a/include/linux/irqchip/irq-omap-intc.h +++ b/include/linux/irqchip/irq-omap-intc.h @@ -20,7 +20,6 @@ void omap2_init_irq(void); void omap3_init_irq(void); -void ti81xx_init_irq(void); int omap_irq_pending(void); void omap_intc_save_context(void); -- cgit v1.2.3 From f848526f3768a80cb3fbcf503306e2c29a80a83c Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 15 Jan 2015 12:33:59 +0200 Subject: irqchip: Devicetree: document Conexant Digicolor irq binding Signed-off-by: Baruch Siach Cc: linux-arm-kernel@lists.infradead.org Cc: Arnd Bergmann Cc: Sergei Shtylyov Cc: Mark Rutland Cc: Jason Cooper Link: http://lkml.kernel.org/r/505a65c8861e5210d94227bc0eec89cab0593fca.1421317616.git.baruch@tkos.co.il Signed-off-by: Thomas Gleixner --- .../bindings/interrupt-controller/digicolor-ic.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt new file mode 100644 index 000000000000..42d41ec84c7b --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt @@ -0,0 +1,21 @@ +Conexant Digicolor Interrupt Controller + +Required properties: + +- compatible : should be "cnxt,cx92755-ic" +- reg : Specifies base physical address and size of the interrupt controller + registers (IC) area +- interrupt-controller : Identifies the node as an interrupt controller +- #interrupt-cells : Specifies the number of cells needed to encode an + interrupt source. The value shall be 1. +- syscon: A phandle to the syscon node describing UC registers + +Example: + + intc: interrupt-controller@f0000040 { + compatible = "cnxt,cx92755-ic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0xf0000040 0x40>; + syscon = <&uc_regs>; + }; -- cgit v1.2.3 From fb7e7deb7fc348ae131268d30e391c8184285de6 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 20 Jan 2015 16:52:59 +0000 Subject: irqchip: gic: Allow interrupt level to be set for PPIs During a recent cleanup of the arm64 DTs it has become clear that the handling of PPIs in xxxx_set_type() is incorrect. The ARM TRMs for GICv2 and later allow for "implementation defined" support for setting the edge or level type of the PPI interrupts and don't restrict the activation level of the signal. Current ARM implementations do restrict the PPI level type to IRQ_TYPE_LEVEL_LOW, but licensees of the IP can decide to shoot themselves in the foot at any time. Signed-off-by: Liviu Dudau Acked-by: Marc Zyngier Cc: LAKML Cc: Russell King Cc: Rob Herring Cc: Mark Rutland Cc: Ian Campbell Cc: Jason Cooper Cc: Haojian Zhuang Link: http://lkml.kernel.org/r/1421772779-25764-1-git-send-email-Liviu.Dudau@arm.com Signed-off-by: Thomas Gleixner --- Documentation/devicetree/bindings/arm/gic.txt | 8 ++++++-- drivers/irqchip/irq-gic-common.c | 18 ++++++++++++------ drivers/irqchip/irq-gic-common.h | 2 +- drivers/irqchip/irq-gic-v3.c | 8 ++++---- drivers/irqchip/irq-gic.c | 9 ++++++--- drivers/irqchip/irq-hip04.c | 9 ++++++--- 6 files changed, 35 insertions(+), 19 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt index 8112d0c3675a..c97484b73e72 100644 --- a/Documentation/devicetree/bindings/arm/gic.txt +++ b/Documentation/devicetree/bindings/arm/gic.txt @@ -32,12 +32,16 @@ Main node required properties: The 3rd cell is the flags, encoded as follows: bits[3:0] trigger type and level flags. 1 = low-to-high edge triggered - 2 = high-to-low edge triggered + 2 = high-to-low edge triggered (invalid for SPIs) 4 = active high level-sensitive - 8 = active low level-sensitive + 8 = active low level-sensitive (invalid for SPIs). bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of the 8 possible cpus attached to the GIC. A bit set to '1' indicated the interrupt is wired to that CPU. Only valid for PPI interrupts. + Also note that the configurability of PPI interrupts is IMPLEMENTATION + DEFINED and as such not guaranteed to be present (most SoC available + in 2014 seem to ignore the setting of this flag and use the hardware + default value). - reg : Specifies base physical address(s) and size of the GIC registers. The first region is the GIC distributor register base and size. The 2nd region is diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index 61541ff24397..ad96ebb0c7ab 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c @@ -21,7 +21,7 @@ #include "irq-gic-common.h" -void gic_configure_irq(unsigned int irq, unsigned int type, +int gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)) { u32 enablemask = 1 << (irq % 32); @@ -29,16 +29,17 @@ void gic_configure_irq(unsigned int irq, unsigned int type, u32 confmask = 0x2 << ((irq % 16) * 2); u32 confoff = (irq / 16) * 4; bool enabled = false; - u32 val; + u32 val, oldval; + int ret = 0; /* * Read current configuration register, and insert the config * for "irq", depending on "type". */ - val = readl_relaxed(base + GIC_DIST_CONFIG + confoff); - if (type == IRQ_TYPE_LEVEL_HIGH) + val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff); + if (type & IRQ_TYPE_LEVEL_MASK) val &= ~confmask; - else if (type == IRQ_TYPE_EDGE_RISING) + else if (type & IRQ_TYPE_EDGE_BOTH) val |= confmask; /* @@ -54,15 +55,20 @@ void gic_configure_irq(unsigned int irq, unsigned int type, /* * Write back the new configuration, and possibly re-enable - * the interrupt. + * the interrupt. If we tried to write a new configuration and failed, + * return an error. */ writel_relaxed(val, base + GIC_DIST_CONFIG + confoff); + if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val && val != oldval) + ret = -EINVAL; if (enabled) writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); if (sync_access) sync_access(); + + return ret; } void __init gic_dist_config(void __iomem *base, int gic_irqs, diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index b41f02481c3a..35a9884778bd 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -20,7 +20,7 @@ #include #include -void gic_configure_irq(unsigned int irq, unsigned int type, +int gic_configure_irq(unsigned int irq, unsigned int type, void __iomem *base, void (*sync_access)(void)); void gic_dist_config(void __iomem *base, int gic_irqs, void (*sync_access)(void)); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 1a146ccee701..6e508038f31b 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -238,7 +238,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type) if (irq < 16) return -EINVAL; - if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) + /* SPIs have restrictions on the supported types */ + if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && + type != IRQ_TYPE_EDGE_RISING) return -EINVAL; if (gic_irq_in_rdist(d)) { @@ -249,9 +251,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) rwp_wait = gic_dist_wait_for_rwp; } - gic_configure_irq(irq, type, base, rwp_wait); - - return 0; + return gic_configure_irq(irq, type, base, rwp_wait); } static u64 gic_mpidr_to_affinity(u64 mpidr) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index d617ee5a3d8a..4634cf7d0ec3 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -188,12 +188,15 @@ static int gic_set_type(struct irq_data *d, unsigned int type) { void __iomem *base = gic_dist_base(d); unsigned int gicirq = gic_irq(d); + int ret; /* Interrupt configuration for SGIs can't be changed */ if (gicirq < 16) return -EINVAL; - if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) + /* SPIs have restrictions on the supported types */ + if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && + type != IRQ_TYPE_EDGE_RISING) return -EINVAL; raw_spin_lock(&irq_controller_lock); @@ -201,11 +204,11 @@ static int gic_set_type(struct irq_data *d, unsigned int type) if (gic_arch_extn.irq_set_type) gic_arch_extn.irq_set_type(d, type); - gic_configure_irq(gicirq, type, base, NULL); + ret = gic_configure_irq(gicirq, type, base, NULL); raw_spin_unlock(&irq_controller_lock); - return 0; + return ret; } static int gic_retrigger(struct irq_data *d) diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index 6bc2deb73d53..7d6ffb5de84f 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c @@ -120,21 +120,24 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type) { void __iomem *base = hip04_dist_base(d); unsigned int irq = hip04_irq(d); + int ret; /* Interrupt configuration for SGIs can't be changed */ if (irq < 16) return -EINVAL; - if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) + /* SPIs have restrictions on the supported types */ + if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && + type != IRQ_TYPE_EDGE_RISING) return -EINVAL; raw_spin_lock(&irq_controller_lock); - gic_configure_irq(irq, type, base, NULL); + ret = gic_configure_irq(irq, type, base, NULL); raw_spin_unlock(&irq_controller_lock); - return 0; + return ret; } #ifdef CONFIG_SMP -- cgit v1.2.3