Skip to contentSkip to conversation

irqchip: gic: killing gic_arch_extn and co, slowly

PATCH Superseded Marc Zyngier 7 participants 37 messages Jan 19, 2015 – Jan 21, 2015

Subsystems (13)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v4 cover irqchip: gic: killing gic_arch_extn and co, slowly

The gic_arch_extn hack that a number of platform use has been nagging me for too long. It is only there for the benefit of a few platform, and yet it impacts all GIC users. Moreover, it gives people the wrong idea ("let's use it to put some new custom hack in there"...).

But now that stacked irq domains have been merged into 3.19, the time has come for gic_arch_extn to meet the Big Bit Bucket.

This patch series takes several steps towards the elimination of gic_arch_extn:

- moves Tegra's legacy interrupt controller support to drivers/irqchip, implementing a stacked domain on top of the standard GIC.

- OMAP, imx6 and exynos are also converted to stacked domains, but their implementation is left in place (the code is far too intricately mixed with other details of the platform for me to even try to move it). Some OMAP variants get a special treatment as we also kill the crossbar horror (more on that below).

- shmobile, ux500 and zynq are only slightly modified.

- The GIC itself is cleaned up, and some other bits and bobs are adjusted for a good measure.

About the TI crossbar:

- The allocation of interrupts in this domain is fairly similar to what we do for MSI (see the GICv2m driver), and stacked domains have proved to be a fitting solution.

- The current description in DT is currently entierely inaccurate, and as we're already breaking it for the WUGEN block, we might as well do it again for the crossbar.

- The way crossbar, WUGEN and GIC interract is quite complex (this is effectively a stack of three interrupt controllers with interesting exceptions and braindead routing), and stacked domains are the right abstraction for that.

- Other platforms (Freescale Vybrid) are starting to come up with the same type of things, and it'd be good to avoid them following the same broken model.

- It removes a few lines from the code base so it can't completely be a bad idea!

So this patch series does exactly that: make the crossbar a stacked interrupt controller that only takes care of setting up the routing, fix the DTs to represent the actual HW, and remove a bit of the craziness from the GIC code.

It is worth realizing that:

- I haven't been able to test this as much as I would have wanted to (it's only been tested on tegra2, omap4 and omap5).

- I've created DT bindings when needed, updated existing ones, but I haven't created a binding for platforms that already used an undocumented one (imx6, I'm looking at you).

- I've relaxed quite a bit of the locking in the GIC code. I believe this is safe, but someone else should give it a long hard look.

- This actively *breaks* existing setups. Once you boot a new kernel with an old DT, suspend/resume *will* be broken. Old kernels on a new DT won't even boot! You've been warned. This really outline the necessity of actually describing the HW in device trees...

As for the patches, they are on top of 3.19-rc3 + the patch posted here [4].

I've pushed the code to:
git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/die-gic-arch-extn-die-die-die

I'm still targetting 3.20 for this, but obviously things are getting quite tight. I'd very much like to hear from the maintainers about their views concerning this series.

Thanks,

	 M.

* From v4 [3]:
- Rebased on top of the patch working around hardcoded IRQ on OMAP4/5 [4]
- Fixed more iMX6 DTs (Stephan)
- Fixed Exynos4/5 DTs

* From v2 [2]:
- Addressed numerous comments from Thierry
- Merged bug fixes from Nishanth
- Merged bug fix from Stefan

* From v1 [1]:
- Rebased on 3.19-rc3
- Fixed a number of additional platforms
- Added crossbar conversion to stacked domains
- Merged bug fixes from Nishanth

[4]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317286.html
[3]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/315385.html
[2]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/314041.html
[1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/307338.html

Marc Zyngier (21):
ARM: tegra: irq: nuke leftovers from non-DT support
irqchip: tegra: add DT-based support for legacy interrupt controller
ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
ARM: tegra: update DTs to expose legacy interrupt controller
DT: tegra: add binding for the legacy interrupt controller
ARM: tegra: remove old LIC support
genirq: Add irqchip_set_wake_parent
irqchip: crossbar: convert dra7 crossbar to stacked domains
DT: update ti,irq-crossbar binding
irqchip: GIC: get rid of routable domain
DT: arm,gic: kill arm,routable-irqs
DT: omap4/5: add binding for the wake-up generator
ARM: omap: convert wakeupgen to stacked domains
ARM: imx6: convert GPC to stacked domains
ARM: exynos4/5: convert pmu wakeup to stacked domains
DT: exynos: update PMU binding
irqchip: gic: add an entry point to set up irqchip flags
ARM: shmobile: remove use of gic_arch_extn.irq_set_wake
ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags
ARM: zynq: switch from gic_arch_extn to gic_set_irqchip_flags
irqchip: gic: Drop support for gic_arch_extn

 Documentation/devicetree/bindings/arm/gic.txt      |   6 -
 .../devicetree/bindings/arm/omap/crossbar.txt      |  18 +-
 .../devicetree/bindings/arm/samsung/pmu.txt        |  13 +
 .../interrupt-controller/nvidia,tegra-ictlr.txt    |  43 +++
 .../interrupt-controller/ti,omap4-wugen-mpu        |  33 ++
 arch/arm/boot/dts/am4372.dtsi                      |  11 +-
 arch/arm/boot/dts/am437x-gp-evm.dts                |   1 -
 arch/arm/boot/dts/am437x-sk-evm.dts                |   1 -
 arch/arm/boot/dts/am43x-epos-evm.dts               |   1 -
 arch/arm/boot/dts/am57xx-beagle-x15.dts            |   3 +-
 arch/arm/boot/dts/dra7-evm.dts                     |   2 +-
 arch/arm/boot/dts/dra7.dtsi                        |  43 ++-
 arch/arm/boot/dts/dra72-evm.dts                    |   1 -
 arch/arm/boot/dts/dra72x.dtsi                      |   3 +-
 arch/arm/boot/dts/dra74x.dtsi                      |   5 +-
 arch/arm/boot/dts/exynos4.dtsi                     |   4 +
 arch/arm/boot/dts/exynos5250.dtsi                  |   4 +
 arch/arm/boot/dts/exynos5420.dtsi                  |   4 +
 arch/arm/boot/dts/imx6qdl.dtsi                     |   7 +-
 arch/arm/boot/dts/imx6sl.dtsi                      |   6 +-
 arch/arm/boot/dts/imx6sx.dtsi                      |   6 +-
 arch/arm/boot/dts/omap4-duovero.dtsi               |   2 -
 arch/arm/boot/dts/omap4-panda-common.dtsi          |   8 +-
 arch/arm/boot/dts/omap4-sdp.dts                    |   8 +-
 arch/arm/boot/dts/omap4-var-som-om44.dtsi          |   2 -
 arch/arm/boot/dts/omap4.dtsi                       |  18 +-
 arch/arm/boot/dts/omap5-cm-t54.dts                 |   1 -
 arch/arm/boot/dts/omap5-uevm.dts                   |   2 -
 arch/arm/boot/dts/omap5.dtsi                       |  26 +-
 arch/arm/boot/dts/tegra114.dtsi                    |  16 +-
 arch/arm/boot/dts/tegra124.dtsi                    |  16 +-
 arch/arm/boot/dts/tegra20.dtsi                     |  15 +-
 arch/arm/boot/dts/tegra30.dtsi                     |  16 +-
 arch/arm/mach-exynos/exynos.c                      |  14 +-
 arch/arm/mach-exynos/suspend.c                     | 122 ++++++-
 arch/arm/mach-imx/common.h                         |   1 -
 arch/arm/mach-imx/gpc.c                            | 127 +++++--
 arch/arm/mach-imx/mach-imx6q.c                     |   1 -
 arch/arm/mach-imx/mach-imx6sl.c                    |   1 -
 arch/arm/mach-imx/mach-imx6sx.c                    |   1 -
 arch/arm/mach-omap2/omap-wakeupgen.c               | 125 +++++--
 arch/arm/mach-omap2/omap-wakeupgen.h               |   1 -
 arch/arm/mach-omap2/omap4-common.c                 |  21 +-
 arch/arm/mach-shmobile/intc-sh73a0.c               |   7 +-
 arch/arm/mach-shmobile/setup-r8a7779.c             |   7 +-
 arch/arm/mach-tegra/iomap.h                        |  15 -
 arch/arm/mach-tegra/irq.c                          | 209 +-----------
 arch/arm/mach-tegra/irq.h                          |   6 -
 arch/arm/mach-tegra/tegra.c                        |   1 -
 arch/arm/mach-ux500/cpu.c                          |   2 +-
 arch/arm/mach-zynq/common.c                        |   2 +-
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-crossbar.c                     | 207 +++++++-----
 drivers/irqchip/irq-gic.c                          | 112 +------
 drivers/irqchip/irq-tegra.c                        | 368 +++++++++++++++++++++
 include/linux/irq.h                                |   1 +
 include/linux/irqchip/arm-gic.h                    |   9 +-
 include/linux/irqchip/irq-crossbar.h               |  11 -
 kernel/irq/chip.c                                  |  16 +
 59 files changed, 1111 insertions(+), 622 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
 create mode 100644 drivers/irqchip/irq-tegra.c
 delete mode 100644 include/linux/irqchip/irq-crossbar.h
Signature · 1 line
2.1.4
#1 lore raw

PATCH v4 1/21 ARM: tegra: irq: nuke leftovers from non-DT support

The GIC is now always initialized from DT on tegra, and there is no point in keeping non-DT init code.

---
 arch/arm/mach-tegra/irq.c | 8 --------
 1 file changed, 8 deletions(-)
arch/arm/mach-tegra/irq.c +0 -8
index ab95f53..7f87a50 100644
@@ -283,13 +283,5 @@ void __init tegra_init_irq(void)
 	gic_arch_extn.irq_set_wake = tegra_set_wake;
 	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
 
-	/*
-	 * Check if there is a devicetree present, since the GIC will be
-	 * initialized elsewhere under DT.
-	 */
-	if (!of_have_populated_dt())
-		gic_init(0, 29, distbase,
-			IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
-
 	tegra114_gic_cpu_pm_registration();
 }
Signature · 1 line
2.1.4
#2 lore raw

PATCH v4 2/21 irqchip: tegra: add DT-based support for legacy interrupt controller

In reply to Marc Zyngier

Tegra's LIC (Legacy Interrupt Controller) has been so far only supported as a weird extension of the GIC, which is not exactly pretty.

The stacked IRQ domain framework fits this pretty well, and allows the LIC code to be turned into a standalone irqchip. In the process, make the driver DT aware, something that was sorely missing from the mach-tegra implementation.

---
 drivers/irqchip/Makefile    |   1 +
 drivers/irqchip/irq-tegra.c | 368 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 369 insertions(+)
 create mode 100644 drivers/irqchip/irq-tegra.c
drivers/irqchip/Makefile +1 -0
index 9516a32..59f34be 100644
@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_HIP04)		+= irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
 obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o
+obj-$(CONFIG_ARCH_TEGRA)		+= irq-tegra.o
 obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
 obj-$(CONFIG_DW_APB_ICTL)		+= irq-dw-apb-ictl.o
 obj-$(CONFIG_METAG)			+= irq-metag-ext.o
drivers/irqchip/irq-tegra.c new file +368 -0

368 lines not on this page · raw message

Signature · 1 line
2.1.4
#3 lore raw

PATCH v4 2/21 irqchip: tegra: add DT-based support for legacy interrupt controller

Quoted 9 lines · Marc Zyngier

Tegra's LIC (Legacy Interrupt Controller) has been so far only supported as a weird extension of the GIC, which is not exactly pretty.

The stacked IRQ domain framework fits this pretty well, and allows the LIC code to be turned into a standalone irqchip. In the process, make the driver DT aware, something that was sorely missing from the mach-tegra implementation.

Note that the GIC isn't really stacked on top of the LIC. Each IRQ is presented to both the LIC and the GIC (as an SPI). The LIC is only used to wakeup the CPU in case the GIC is not powered. The LIC can also generate interrupts towards the AVP/ARM7, but that's outside the scope of Linux ofcourse. The LIC can also be used to force an IRQ and that forced IRQ will be propagated to the GIC. (see also figure 2, page 36 of the Tegra K1 TRM)

Cheers,

Peter.

#4 lore raw

PATCH v4 3/21 ARM: tegra: skip gic_arch_extn setup if DT has a LIC node

In reply to Marc Zyngier

If we detect that our DT has a LIC node, don't setup gic_arch_extn, and skip tegra_legacy_irq_syscore_init as well.

This is only a temporary measure until that code is removed for good.

---
 arch/arm/mach-tegra/irq.c   | 12 ++++++++++++
 arch/arm/mach-tegra/tegra.c |  1 -
 2 files changed, 12 insertions(+), 1 deletion(-)
arch/arm/mach-tegra/irq.c +12 -0
index 7f87a50..1593c4c 100644
@@ -255,11 +255,22 @@ static void tegra114_gic_cpu_pm_registration(void)
 static void tegra114_gic_cpu_pm_registration(void) { }
 #endif
 
+static const struct of_device_id tegra_ictlr_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-ictlr" },
+	{ .compatible = "nvidia,tegra30-ictlr" },
+	{ }
+};
+
 void __init tegra_init_irq(void)
 {
 	int i;
 	void __iomem *distbase;
 
+	if (of_find_matching_node(NULL, tegra_ictlr_match))
+		goto skip_extn_setup;
+
+	tegra_legacy_irq_syscore_init();
+
 	distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
 	num_ictlrs = readl_relaxed(distbase + GIC_DIST_CTR) & 0x1f;
 
@@ -283,5 +294,6 @@ void __init tegra_init_irq(void)
 	gic_arch_extn.irq_set_wake = tegra_set_wake;
 	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
 
+skip_extn_setup:
 	tegra114_gic_cpu_pm_registration();
 }
arch/arm/mach-tegra/tegra.c +0 -1
index ef016af..c33fba7 100644
@@ -82,7 +82,6 @@ static void __init tegra_dt_init_irq(void)
 {
 	tegra_init_irq();
 	irqchip_init();
-	tegra_legacy_irq_syscore_init();
 }
 
 static void __init tegra_dt_init(void)
Signature · 1 line
2.1.4
#5 lore raw

PATCH v4 4/21 ARM: tegra: update DTs to expose legacy interrupt controller

In reply to Marc Zyngier

Describe the legacy interrupt controller in every tegra DTSI files, and make it the parent of most interrupts.

---
 arch/arm/boot/dts/tegra114.dtsi | 16 +++++++++++++++-
 arch/arm/boot/dts/tegra124.dtsi | 16 +++++++++++++++-
 arch/arm/boot/dts/tegra20.dtsi  | 15 ++++++++++++++-
 arch/arm/boot/dts/tegra30.dtsi  | 16 +++++++++++++++-
 4 files changed, 59 insertions(+), 4 deletions(-)
arch/arm/boot/dts/tegra114.dtsi +15 -1
index 4296b53..f58a3d9 100644
@@ -8,7 +8,7 @@
 
 / {
 	compatible = "nvidia,tegra114";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&lic>;
 
 	host1x at 50000000 {
 		compatible = "nvidia,tegra114-host1x", "simple-bus";
@@ -134,6 +134,19 @@
 		      <0x50046000 0x2000>;
 		interrupts = <GIC_PPI 9
 			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
+	};
+
+	lic: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra30-ictlr";
+		reg = <0x60004000 0x100>,
+		      <0x60004100 0x50>,
+		      <0x60004200 0x50>,
+		      <0x60004300 0x50>,
+		      <0x60004400 0x50>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
 	};
 
 	timer at 60005000 {
@@ -766,5 +779,6 @@
 				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
 			<GIC_PPI 10
 				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+		interrupt-parent = <&gic>;
 	};
 };
arch/arm/boot/dts/tegra124.dtsi +15 -1
index 4be06c6..db85695 100644
@@ -10,7 +10,7 @@
 
 / {
 	compatible = "nvidia,tegra124";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&lic>;
 	#address-cells = <2>;
 	#size-cells = <2>;
 
@@ -173,6 +173,7 @@
 		      <0x0 0x50046000 0x0 0x2000>;
 		interrupts = <GIC_PPI 9
 			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
 	};
 
 	gpu at 0,57000000 {
@@ -190,6 +191,18 @@
 		status = "disabled";
 	};
 
+	lic: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra30-ictlr";
+		reg = <0x0 0x60004000 0x0 0x100>,
+		      <0x0 0x60004100 0x0 0x100>,
+		      <0x0 0x60004200 0x0 0x100>,
+		      <0x0 0x60004300 0x0 0x100>,
+		      <0x0 0x60004400 0x0 0x100>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+	};
+
 	timer at 0,60005000 {
 		compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
 		reg = <0x0 0x60005000 0x0 0x400>;
@@ -955,5 +968,6 @@
 				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10
 				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+		interrupt-parent = <&gic>;
 	};
 };
arch/arm/boot/dts/tegra20.dtsi +14 -1
index 8acf5d8..362bb21 100644
@@ -7,7 +7,7 @@
 
 / {
 	compatible = "nvidia,tegra20";
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&lic>;
 
 	host1x at 50000000 {
 		compatible = "nvidia,tegra20-host1x", "simple-bus";
@@ -142,6 +142,7 @@
 
 	timer at 50004600 {
 		compatible = "arm,cortex-a9-twd-timer";
+		interrupt-parent = <&intc>;
 		reg = <0x50040600 0x20>;
 		interrupts = <GIC_PPI 13
 			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
@@ -154,6 +155,7 @@
 		       0x50040100 0x0100>;
 		interrupt-controller;
 		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
 	};
 
 	cache-controller at 50043000 {
@@ -165,6 +167,17 @@
 		cache-level = <2>;
 	};
 
+	lic: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra20-ictlr";
+		reg = <0x60004000 0x100>,
+		      <0x60004100 0x50>,
+		      <0x60004200 0x50>,
+		      <0x60004300 0x50>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+	};
+
 	timer at 60005000 {
 		compatible = "nvidia,tegra20-timer";
 		reg = <0x60005000 0x60>;
arch/arm/boot/dts/tegra30.dtsi +15 -1
index 99475f6..6bea674 100644
@@ -8,7 +8,7 @@
 
 / {
 	compatible = "nvidia,tegra30";
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&lic>;
 
 	pcie-controller at 00003000 {
 		compatible = "nvidia,tegra30-pcie";
@@ -228,6 +228,7 @@
 	timer at 50004600 {
 		compatible = "arm,cortex-a9-twd-timer";
 		reg = <0x50040600 0x20>;
+		interrupt-parent = <&intc>;
 		interrupts = <GIC_PPI 13
 			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		clocks = <&tegra_car TEGRA30_CLK_TWD>;
@@ -239,6 +240,7 @@
 		       0x50040100 0x0100>;
 		interrupt-controller;
 		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
 	};
 
 	cache-controller at 50043000 {
@@ -250,6 +252,18 @@
 		cache-level = <2>;
 	};
 
+	lic: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra30-ictlr";
+		reg = <0x60004000 0x100>,
+		      <0x60004100 0x50>,
+		      <0x60004200 0x50>,
+		      <0x60004300 0x50>,
+		      <0x60004400 0x50>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+	};
+
 	timer at 60005000 {
 		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
 		reg = <0x60005000 0x400>;
Signature · 1 line
2.1.4
#6 lore raw

PATCH v4 5/21 DT: tegra: add binding for the legacy interrupt controller

In reply to Marc Zyngier
---
 .../interrupt-controller/nvidia,tegra-ictlr.txt    | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt new file +43 -0
new file mode 100644
index 0000000..1099fe0
@@ -0,0 +1,43 @@
+NVIDIA Legacy Interrupt Controller
+
+All Tegra SoCs contain a legacy interrupt controller that routes
+interrupts to the GIC, and also serves as a wakeup source. It is also
+referred to as "ictlr", hence the name of the binding.
+
+The HW block exposes a number of interrupt controllers, each
+implementing a set of 32 interrupts.
+
+Required properties:
+
+- compatible : should be: "nvidia,tegra<chip>-ictlr". The LIC on
+  subsequent SoCs remained backwards-compatible with Tegra30, so on
+  Tegra generations later than Tegra30 the compatible value should
+  include "nvidia,tegra30-ictlr".	
+- reg : Specifies base physical address and size of the registers.
+  Each controller must be described separately (Tegra20 has 4 of them,
+  whereas Tegra30 and later have 5"  
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+  to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+  interrupt specifier must be that of the GIC.
+- Only SPIs can use the ictlr as an interrupt parent. SGIs and PPIs
+  are explicitly forbidden.
+
+Example:
+
+	ictlr: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x60004000 64>,
+		      <0x60004100 64>,
+		      <0x60004200 64>,
+		      <0x60004300 64>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+	};
Signature · 1 line
2.1.4
#7 lore raw

PATCH v4 6/21 ARM: tegra: remove old LIC support

In reply to Marc Zyngier

Now that all DTs have been updated, entierely drop support for the non-DT code.

This is likely to break platforms that do not update their DT, so print a warning at boot time.

---
 arch/arm/mach-tegra/iomap.h |  15 ----
 arch/arm/mach-tegra/irq.c   | 201 +-------------------------------------------
 arch/arm/mach-tegra/irq.h   |   6 --
 3 files changed, 2 insertions(+), 220 deletions(-)
arch/arm/mach-tegra/iomap.h +0 -15
index ee79808..81dc950 100644
@@ -31,21 +31,6 @@
 #define TEGRA_ARM_INT_DIST_BASE		0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE		SZ_4K
 
-#define TEGRA_PRIMARY_ICTLR_BASE	0x60004000
-#define TEGRA_PRIMARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_SECONDARY_ICTLR_BASE	0x60004100
-#define TEGRA_SECONDARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_TERTIARY_ICTLR_BASE	0x60004200
-#define TEGRA_TERTIARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_QUATERNARY_ICTLR_BASE	0x60004300
-#define TEGRA_QUATERNARY_ICTLR_SIZE	SZ_64
-
-#define TEGRA_QUINARY_ICTLR_BASE	0x60004400
-#define TEGRA_QUINARY_ICTLR_SIZE	SZ_64
-
 #define TEGRA_TMR1_BASE			0x60005000
 #define TEGRA_TMR1_SIZE			SZ_8
 
arch/arm/mach-tegra/irq.c +2 -199

229 lines not on this page · raw message

arch/arm/mach-tegra/irq.h +0 -6
index bc05ce5..5142649 100644
@@ -19,10 +19,4 @@
 
 bool tegra_pending_sgi(void);
 
-#ifdef CONFIG_PM_SLEEP
-int tegra_legacy_irq_syscore_init(void);
-#else
-static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
-#endif
-
 #endif
Signature · 1 line
2.1.4
#8 lore raw

PATCH v4 7/21 genirq: Add irqchip_set_wake_parent

In reply to Marc Zyngier

This proves to be useful with stacked domains, when the current domain doesn't implement wake-up, but expect the parent to do so.

---
 include/linux/irq.h |  1 +
 kernel/irq/chip.c   | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)
include/linux/irq.h +1 -0
index d09ec7a..3057c48 100644
@@ -460,6 +460,7 @@ extern void irq_chip_eoi_parent(struct irq_data *data);
 extern int irq_chip_set_affinity_parent(struct irq_data *data,
 					const struct cpumask *dest,
 					bool force);
+extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
 #endif
 
 /* Handling of unhandled and spurious interrupts: */
kernel/irq/chip.c +16 -0
index 6f1c7a5..eb9a4ea 100644
@@ -948,6 +948,22 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data)
 
 	return -ENOSYS;
 }
+
+/**
+ * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt
+ * @data:	Pointer to interrupt specific data
+ * @on:		Whether to set or reset the wake-up capability of this irq
+ *
+ * Conditional, as the underlying parent chip might not implement it.
+ */
+int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on)
+{
+	data = data->parent_data;
+	if (data->chip->irq_set_wake)
+		return data->chip->irq_set_wake(data, on);
+
+	return -ENOSYS;
+}
 #endif
 
 /**
Signature · 1 line
2.1.4
#9 lore raw

PATCH v4 8/21 irqchip: crossbar: convert dra7 crossbar to stacked domains

In reply to Marc Zyngier

Support for the TI crossbar used on the DRA7 family of chips is implemented as an ugly hack on the side of the GIC.

Converting it to stacked domains makes it slightly more palatable, as it results in a cleanup.

Unfortunately, as the DT bindings failed to acknowledge the fact that this is actually yet another interrupt controller (the third, actually), we have yet another breakage. Oh well.

---
 arch/arm/boot/dts/am57xx-beagle-x15.dts |   3 +-
 arch/arm/boot/dts/dra7-evm.dts          |   2 +-
 arch/arm/boot/dts/dra7.dtsi             |  35 +++---
 arch/arm/boot/dts/dra72-evm.dts         |   1 -
 arch/arm/boot/dts/dra72x.dtsi           |   3 +-
 arch/arm/boot/dts/dra74x.dtsi           |   5 +-
 arch/arm/mach-omap2/omap4-common.c      |   4 -
 drivers/irqchip/irq-crossbar.c          | 207 ++++++++++++++++++--------------
 include/linux/irqchip/irq-crossbar.h    |  11 --
 9 files changed, 146 insertions(+), 125 deletions(-)
 delete mode 100644 include/linux/irqchip/irq-crossbar.h
arch/arm/boot/dts/am57xx-beagle-x15.dts +1 -2
index 49edbda..c2241c2 100644
@@ -335,7 +335,6 @@
 	mcp_rtc: rtc at 6f {
 		compatible = "microchip,mcp7941x";
 		reg = <0x6f>;
-		interrupt-parent = <&gic>;
 		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>;  /* IRQ_SYS_1N */
 
 		pinctrl-names = "default";
@@ -358,7 +357,7 @@
 
 &uart3 {
 	status = "okay";
-	interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+	interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
 			      <&dra7_pmx_core 0x248>;
 
 	pinctrl-names = "default";
arch/arm/boot/dts/dra7-evm.dts +1 -1
index 10b725c..048cfeb 100644
@@ -423,7 +423,7 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart1_pins>;
-	interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+	interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
 			      <&dra7_pmx_core 0x3e0>;
 };
 
arch/arm/boot/dts/dra7.dtsi +19 -16
index 22771bc..6f90673 100644
@@ -13,14 +13,13 @@
 #include "skeleton.dtsi"
 
 #define MAX_SOURCES 400
-#define DIRECT_IRQ(irq) (MAX_SOURCES + irq)
 
 / {
 	#address-cells = <1>;
 	#size-cells = <1>;
 
 	compatible = "ti,dra7xx";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&crossbar_mpu>;
 
 	aliases {
 		i2c0 = &i2c1;
@@ -50,18 +49,19 @@
 			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+		interrupt-parent = <&gic>;
 	};
 
 	gic: interrupt-controller at 48211000 {
 		compatible = "arm,cortex-a15-gic";
 		interrupt-controller;
 		#interrupt-cells = <3>;
-		arm,routable-irqs = <192>;
 		reg = <0x48211000 0x1000>,
 		      <0x48212000 0x1000>,
 		      <0x48214000 0x2000>,
 		      <0x48216000 0x2000>;
 		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
 	};
 
 	/*
@@ -91,8 +91,8 @@
 		ti,hwmods = "l3_main_1", "l3_main_2";
 		reg = <0x44000000 0x1000000>,
 		      <0x45000000 0x1000>;
-		interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI DIRECT_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
+		interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+				      <&gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
 		prm: prm at 4ae06000 {
 			compatible = "ti,dra7-prm";
@@ -344,7 +344,7 @@
 		uart1: serial at 4806a000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806a000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -355,7 +355,7 @@
 		uart2: serial at 4806c000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806c000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -366,7 +366,7 @@
 		uart3: serial at 48020000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48020000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -377,7 +377,7 @@
 		uart4: serial at 4806e000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806e000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
                         status = "disabled";
@@ -388,7 +388,7 @@
 		uart5: serial at 48066000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48066000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -399,7 +399,7 @@
 		uart6: serial at 48068000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48068000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -410,7 +410,7 @@
 		uart7: serial at 48420000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48420000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart7";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -419,7 +419,7 @@
 		uart8: serial at 48422000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48422000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart8";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -428,7 +428,7 @@
 		uart9: serial at 48424000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48424000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart9";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -437,7 +437,7 @@
 		uart10: serial at 4ae2b000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4ae2b000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart10";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -1333,9 +1333,12 @@
 			status = "disabled";
 		};
 
-		crossbar_mpu: crossbar at 4a020000 {
+		crossbar_mpu: crossbar at 4a002a48 {
 			compatible = "ti,irq-crossbar";
 			reg = <0x4a002a48 0x130>;
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			#interrupt-cells = <3>;
 			ti,max-irqs = <160>;
 			ti,max-crossbar-sources = <MAX_SOURCES>;
 			ti,reg-size = <2>;
arch/arm/boot/dts/dra72-evm.dts +0 -1
index 89085d0..298df33 100644
@@ -137,7 +137,6 @@
 		pinctrl-0 = <&tps65917_pins_default>;
 
 		interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
-		interrupt-parent = <&gic>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 
arch/arm/boot/dts/dra72x.dtsi +2 -1
index e5a3d23..e782bf1 100644
@@ -25,6 +25,7 @@
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
arch/arm/boot/dts/dra74x.dtsi +3 -2
index 10173fa..0fc758d 100644
@@ -41,8 +41,9 @@
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI DIRECT_IRQ(132) IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	ocp {
arch/arm/mach-omap2/omap4-common.c +0 -4
index cc30e49..b88520d 100644
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/export.h>
 #include <linux/irqchip/arm-gic.h>
-#include <linux/irqchip/irq-crossbar.h>
 #include <linux/of_address.h>
 #include <linux/reboot.h>
 #include <linux/genalloc.h>
@@ -306,8 +305,5 @@ void __init omap_gic_of_init(void)
 
 skip_errata_init:
 	omap_wakeupgen_init();
-#ifdef CONFIG_IRQ_CROSSBAR
-	irqcrossbar_init();
-#endif
 	irqchip_init();
 }
drivers/irqchip/irq-crossbar.c +120 -87

298 lines not on this page · raw message

include/linux/irqchip/irq-crossbar.h deleted +0 -11
deleted file mode 100644
index e5537b8..0000000
@@ -1,11 +0,0 @@
-/*
- *  drivers/irqchip/irq-crossbar.h
- *
- *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-int irqcrossbar_init(void);
Signature · 1 line
2.1.4
#10 lore raw

PATCH v4 9/21 DT: update ti,irq-crossbar binding

In reply to Marc Zyngier

Make it look like a real interrupt controller.

---
 .../devicetree/bindings/arm/omap/crossbar.txt          | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)
Documentation/devicetree/bindings/arm/omap/crossbar.txt +5 -13
index 4139db3..a9b28d7 100644
@@ -9,7 +9,9 @@ inputs.
 Required properties:
 - compatible : Should be "ti,irq-crossbar"
 - reg: Base address and the size of the crossbar registers.
-- ti,max-irqs: Total number of irqs available at the interrupt controller.
+- interrupt-controller: indicates that this block is an interrupt controller.
+- interrupt-parent: the interrupt controller this block is connected to.
+- ti,max-irqs: Total number of irqs available at the parent interrupt controller.
 - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed.
 - ti,reg-size: Size of a individual register in bytes. Every individual
 	    register is assumed to be of same size. Valid sizes are 1, 2, 4.
@@ -27,13 +29,13 @@ Optional properties:
   when the interrupt controller irq is unused (when not provided, default is 0)
 
 Examples:
-		crossbar_mpu: @4a020000 {
+		crossbar_mpu: crossbar at 4a002a48 {
 			compatible = "ti,irq-crossbar";
 			reg = <0x4a002a48 0x130>;
 			ti,max-irqs = <160>;
 			ti,max-crossbar-sources = <400>;
 			ti,reg-size = <2>;
-			ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>;
+			ti,irqs-reserved = <0 1 2 3 5 6 131 132>;
 			ti,irqs-skip = <10 133 139 140>;
 		};
 
@@ -44,10 +46,6 @@ Documentation/devicetree/bindings/arm/gic.txt for further details.
 
 An interrupt consumer on an SoC using crossbar will use:
 	interrupts = <GIC_SPI request_number interrupt_level>
-When the request number is between 0 to that described by
-"ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the
-request_number is greater than "ti,max-crossbar-sources", then it is mapped as a
-quirky hardware mapping direct to GIC.
 
 Example:
 	device_x at 0x4a023000 {
@@ -55,9 +53,3 @@ Example:
 		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
 		...
 	};
-
-	device_y at 0x4a033000 {
-		/* Direct mapped GIC SPI 1 used */
-		interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>;
-		...
-	};
Signature · 1 line
2.1.4
#11 lore raw

PATCH v4 10/21 irqchip: GIC: get rid of routable domain

In reply to Marc Zyngier

The only user of the so called "routable domain" functionality now being fixed, let's clean up the GIC.

---
 drivers/irqchip/irq-gic.c       | 59 ++++-------------------------------------
 include/linux/irqchip/arm-gic.h |  6 -----
 2 files changed, 5 insertions(+), 60 deletions(-)
drivers/irqchip/irq-gic.c +5 -54
index d617ee5..9c30a76 100644
@@ -795,15 +795,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 		irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
 				    handle_fasteoi_irq, NULL, NULL);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-
-		gic_routable_irq_domain_ops->map(d, irq, hw);
 	}
 	return 0;
 }
 
 static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
 {
-	gic_routable_irq_domain_ops->unmap(d, irq);
 }
 
 static int gic_irq_domain_xlate(struct irq_domain *d,
@@ -822,16 +819,8 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
 	*out_hwirq = intspec[1] + 16;
 
 	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
-	if (!intspec[0]) {
-		ret = gic_routable_irq_domain_ops->xlate(d, controller,
-							 intspec,
-							 intsize,
-							 out_hwirq,
-							 out_type);
-
-		if (IS_ERR_VALUE(ret))
-			return ret;
-	}
+	if (!intspec[0])
+		*out_hwirq += 16;
 
 	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
 
@@ -888,37 +877,6 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.xlate = gic_irq_domain_xlate,
 };
 
-/* Default functions for routable irq domain */
-static int gic_routable_irq_domain_map(struct irq_domain *d, unsigned int irq,
-			      irq_hw_number_t hw)
-{
-	return 0;
-}
-
-static void gic_routable_irq_domain_unmap(struct irq_domain *d,
-					  unsigned int irq)
-{
-}
-
-static int gic_routable_irq_domain_xlate(struct irq_domain *d,
-				struct device_node *controller,
-				const u32 *intspec, unsigned int intsize,
-				unsigned long *out_hwirq,
-				unsigned int *out_type)
-{
-	*out_hwirq += 16;
-	return 0;
-}
-
-static const struct irq_domain_ops gic_default_routable_irq_domain_ops = {
-	.map = gic_routable_irq_domain_map,
-	.unmap = gic_routable_irq_domain_unmap,
-	.xlate = gic_routable_irq_domain_xlate,
-};
-
-const struct irq_domain_ops *gic_routable_irq_domain_ops =
-					&gic_default_routable_irq_domain_ops;
-
 void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 			   void __iomem *dist_base, void __iomem *cpu_base,
 			   u32 percpu_offset, struct device_node *node)
@@ -926,7 +884,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	irq_hw_number_t hwirq_base;
 	struct gic_chip_data *gic;
 	int gic_irqs, irq_base, i;
-	int nr_routable_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
@@ -982,15 +939,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 	gic->gic_irqs = gic_irqs;
 
 	if (node) {		/* DT case */
-		const struct irq_domain_ops *ops = &gic_irq_domain_hierarchy_ops;
-
-		if (!of_property_read_u32(node, "arm,routable-irqs",
-					  &nr_routable_irqs)) {
-			ops = &gic_irq_domain_ops;
-			gic_irqs = nr_routable_irqs;
-		}
-
-		gic->domain = irq_domain_add_linear(node, gic_irqs, ops, gic);
+		gic->domain = irq_domain_add_linear(node, gic_irqs,
+						    &gic_irq_domain_hierarchy_ops,
+						    gic);
 	} else {		/* Non-DT case */
 		/*
 		 * For primary GICs, skip over SGIs.
include/linux/irqchip/arm-gic.h +0 -6
index 71d706d..3978c5b 100644
@@ -115,11 +115,5 @@ int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
 unsigned long gic_get_sgir_physaddr(void);
 
-extern const struct irq_domain_ops *gic_routable_irq_domain_ops;
-static inline void __init register_routable_domain_ops
-					(const struct irq_domain_ops *ops)
-{
-	gic_routable_irq_domain_ops = ops;
-}
 #endif /* __ASSEMBLY */
 #endif
Signature · 1 line
2.1.4
#12 lore raw

PATCH v4 11/21 DT: arm,gic: kill arm,routable-irqs

In reply to Marc Zyngier

Nobody will regret it.

---
 Documentation/devicetree/bindings/arm/gic.txt | 6 ------
 1 file changed, 6 deletions(-)
Documentation/devicetree/bindings/arm/gic.txt +0 -6
index 8112d0c..631cb71 100644
@@ -52,11 +52,6 @@ Optional
   regions, used when the GIC doesn't have banked registers. The offset is
   cpu-offset * cpu-nr.
 
-- arm,routable-irqs : Total number of gic irq inputs which are not directly
-		  connected from the peripherals, but are routed dynamically
-		  by a crossbar/multiplexer preceding the GIC. The GIC irq
-		  input line is assigned dynamically when the corresponding
-		  peripheral's crossbar line is mapped.
 Example:
 
 	intc: interrupt-controller at fff11000 {
@@ -64,7 +59,6 @@ Example:
 		#interrupt-cells = <3>;
 		#address-cells = <1>;
 		interrupt-controller;
-		arm,routable-irqs = <160>;
 		reg = <0xfff11000 0x1000>,
 		      <0xfff10100 0x100>;
 	};
Signature · 1 line
2.1.4
#13 lore raw

PATCH v4 12/21 DT: omap4/5: add binding for the wake-up generator

In reply to Marc Zyngier
---
 .../interrupt-controller/ti,omap4-wugen-mpu        | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu new file +33 -0
new file mode 100644
index 0000000..43effa0
@@ -0,0 +1,33 @@
+TI OMAP4 Wake-up Generator
+
+All TI OMAP4/5 (and their derivatives) an interrupt controller that
+routes interrupts to the GIC, and also serves as a wakeup source. It
+is also referred to as "WUGEN-MPU", hence the name of the binding.
+
+Reguired properties:
+
+- compatible : should contain at least "ti,omap4-wugen-mpu" or
+  "ti,omap5-wugen-mpu"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+  to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+  interrupt specifier must be that of the GIC.
+- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
+  are explicitly forbiden.
+
+Example:
+
+       wakeupgen: interrupt-controller at 48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
+       };
Signature · 1 line
2.1.4
maintainer
#14 lore raw

PATCH v4 12/21 DT: omap4/5: add binding for the wake-up generator

Quoted 1 line · Marc Zyngier
Quoted 47 lines
---
 .../interrupt-controller/ti,omap4-wugen-mpu        | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu new file +33 -0
new file mode 100644
index 0000000..43effa0
@@ -0,0 +1,33 @@
+TI OMAP4 Wake-up Generator
+
+All TI OMAP4/5 (and their derivatives) an interrupt controller that
+routes interrupts to the GIC, and also serves as a wakeup source. It
+is also referred to as "WUGEN-MPU", hence the name of the binding.
+
+Reguired properties:
+
+- compatible : should contain at least "ti,omap4-wugen-mpu" or
+  "ti,omap5-wugen-mpu"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+  to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+  interrupt specifier must be that of the GIC.
+- Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
+  are explicitly forbiden.
+
+Example:
+
+       wakeupgen: interrupt-controller at 48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
+       };
Signature · 1 line
2.1.4
#15 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

In reply to Marc Zyngier

OMAP4/5 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the WUGEN HW block, kernels with this patch applied won't have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

On a platform with this patch applied, the system looks like this:

root at bacon-fat:~# cat /proc/interrupts
CPU0 CPU1

 16:          0          0     WUGEN  37  gp_timer
 19:     233799     155916       GIC  27  arch_timer
 23:          0          0     WUGEN   9  l3-dbg-irq
 24:          1          0     WUGEN  10  l3-app-irq
 27:        282          0     WUGEN  13  omap-dma-engine
 44:          0          0  4ae10000.gpio  13  DMA
294:          0          0     WUGEN  20  gpmc
297:        506          0     WUGEN  56  48070000.i2c
298:          0          0     WUGEN  57  48072000.i2c
299:          0          0     WUGEN  61  48060000.i2c
300:          0          0     WUGEN  62  4807a000.i2c
301:          8          0     WUGEN  60  4807c000.i2c
308:       2439          0     WUGEN  74  OMAP UART2
312:        362          0     WUGEN  83  mmc2
313:        502          0     WUGEN  86  mmc0
314:         13          0     WUGEN  94  mmc1
350:          0          0      PRCM  pinctrl, pinctrl
406:   35155709          0       GIC 109  ehci_hcd:usb1
407:          0          0     WUGEN   7  palmas
409:          0          0     WUGEN 119  twl6040
410:          0          0   twl6040   5  twl6040_irq_ready
411:          0          0   twl6040   0  twl6040_irq_th
IPI0:          0          1  CPU wakeup interrupts
IPI1:          0          0  Timer broadcast interrupts
IPI2:      95334     902334  Rescheduling interrupts
IPI3:          0          0  Function call interrupts
IPI4:        479        648  Single function call interrupts
IPI5:          0          0  CPU stop interrupts
IPI6:          0          0  IRQ work interrupts
IPI7:          0          0  completion interrupts
Err:          0
---
 arch/arm/boot/dts/am4372.dtsi             |  11 ++-
 arch/arm/boot/dts/am437x-gp-evm.dts       |   1 -
 arch/arm/boot/dts/am437x-sk-evm.dts       |   1 -
 arch/arm/boot/dts/am43x-epos-evm.dts      |   1 -
 arch/arm/boot/dts/dra7.dtsi               |  12 ++-
 arch/arm/boot/dts/dra72x.dtsi             |   2 +-
 arch/arm/boot/dts/dra74x.dtsi             |   2 +-
 arch/arm/boot/dts/omap4-duovero.dtsi      |   2 -
 arch/arm/boot/dts/omap4-panda-common.dtsi |   8 +-
 arch/arm/boot/dts/omap4-sdp.dts           |   8 +-
 arch/arm/boot/dts/omap4-var-som-om44.dtsi |   2 -
 arch/arm/boot/dts/omap4.dtsi              |  18 ++++-
 arch/arm/boot/dts/omap5-cm-t54.dts        |   1 -
 arch/arm/boot/dts/omap5-uevm.dts          |   2 -
 arch/arm/boot/dts/omap5.dtsi              |  26 ++++---
 arch/arm/mach-omap2/omap-wakeupgen.c      | 125 +++++++++++++++++++++++-------
 arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
 arch/arm/mach-omap2/omap4-common.c        |  17 ++--
 18 files changed, 162 insertions(+), 78 deletions(-)
arch/arm/boot/dts/am4372.dtsi +10 -1
index b62a1cd..9d672a7 100644
@@ -15,7 +15,7 @@
 
 / {
 	compatible = "ti,am4372", "ti,am43";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&wakeupgen>;
 
 
 	aliases {
@@ -48,6 +48,15 @@
 		#interrupt-cells = <3>;
 		reg = <0x48241000 0x1000>,
 		      <0x48240100 0x0100>;
+		interrupt-parent = <&gic>;
+	};
+
+	wakeupgen: interrupt-controller at 48281000 {
+		compatible = "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
 	};
 
 	l2-cache-controller at 48242000 {
arch/arm/boot/dts/am437x-gp-evm.dts +0 -1
index 7eaae4c..69f2313 100644
@@ -280,7 +280,6 @@
 		reg = <0x24>;
 		compatible = "ti,tps65218";
 		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
-		interrupt-parent = <&gic>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 
arch/arm/boot/dts/am437x-sk-evm.dts +0 -1
index 53bbfc9..029bade 100644
@@ -334,7 +334,6 @@
 	tps at 24 {
 		compatible = "ti,tps65218";
 		reg = <0x24>;
-		interrupt-parent = <&gic>;
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
arch/arm/boot/dts/am43x-epos-evm.dts +0 -1
index 662261d..2d26bc1 100644
@@ -333,7 +333,6 @@
 		reg = <0x24>;
 		compatible = "ti,tps65218";
 		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
-		interrupt-parent = <&gic>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 
arch/arm/boot/dts/dra7.dtsi +10 -2
index 6f90673..a530016 100644
@@ -64,6 +64,14 @@
 		interrupt-parent = <&gic>;
 	};
 
+	wakeupgen: interrupt-controller at 48281000 {
+		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
+	};
+
 	/*
 	 * The soc node represents the soc top level view. It is used for IPs
 	 * that are not memory mapped in the MPU view or for the MPU itself.
@@ -92,7 +100,7 @@
 		reg = <0x44000000 0x1000000>,
 		      <0x45000000 0x1000>;
 		interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
-				      <&gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+				      <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
 		prm: prm at 4ae06000 {
 			compatible = "ti,dra7-prm";
@@ -1337,7 +1345,7 @@
 			compatible = "ti,irq-crossbar";
 			reg = <0x4a002a48 0x130>;
 			interrupt-controller;
-			interrupt-parent = <&gic>;
+			interrupt-parent = <&wakeupgen>;
 			#interrupt-cells = <3>;
 			ti,max-irqs = <160>;
 			ti,max-crossbar-sources = <MAX_SOURCES>;
arch/arm/boot/dts/dra72x.dtsi +1 -1
index e782bf1..f7fb0d0 100644
@@ -25,7 +25,7 @@
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupt-parent = <&gic>;
+		interrupt-parent = <&wakeupgen>;
 		interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
arch/arm/boot/dts/dra74x.dtsi +1 -1
index 0fc758d..00eeed7 100644
@@ -41,7 +41,7 @@
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupt-parent = <&gic>;
+		interrupt-parent = <&wakeupgen>;
 		interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
 	};
arch/arm/boot/dts/omap4-duovero.dtsi +0 -2
index e860ccd..f2a94fa 100644
@@ -173,14 +173,12 @@
 	twl: twl at 48 {
 		reg = <0x48>;
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;		/* IRQ_SYS_1N cascaded to gic */
-		interrupt-parent = <&gic>;
 	};
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
 		reg = <0x4b>;
 		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;		/* IRQ_SYS_2N cascaded to gic */
-		interrupt-parent = <&gic>;
 		ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>;		/* gpio_160 */
 
 		vio-supply = <&v1v8>;
arch/arm/boot/dts/omap4-panda-common.dtsi +3 -5
index 1505135..7c15fb2 100644
@@ -372,7 +372,6 @@
 		reg = <0x48>;
 		/* IRQ# = 7 */
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-		interrupt-parent = <&gic>;
 	};
 
 	twl6040: twl at 4b {
@@ -384,7 +383,6 @@
 
 		/* IRQ# = 119 */
 		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-		interrupt-parent = <&gic>;
 		ti,audpwron-gpio = <&gpio4 31 GPIO_ACTIVE_HIGH>;  /* gpio line 127 */
 
 		vio-supply = <&v1v8>;
@@ -479,17 +477,17 @@
 };
 
 &uart2 {
-	interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
+	interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core OMAP4_UART2_RX>;
 };
 
 &uart3 {
-	interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+	interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core OMAP4_UART3_RX>;
 };
 
 &uart4 {
-	interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+	interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core OMAP4_UART4_RX>;
 };
 
arch/arm/boot/dts/omap4-sdp.dts +3 -5
index 3e1da43..8aca8da 100644
@@ -363,7 +363,6 @@
 		reg = <0x48>;
 		/* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-		interrupt-parent = <&gic>;
 	};
 
 	twl6040: twl at 4b {
@@ -375,7 +374,6 @@
 
 		/* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
 		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-		interrupt-parent = <&gic>;
 		ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
 
 		vio-supply = <&v1v8>;
@@ -570,21 +568,21 @@
 };
 
 &uart2 {
-	interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
+	interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core OMAP4_UART2_RX>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart2_pins>;
 };
 
 &uart3 {
-	interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+	interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core OMAP4_UART3_RX>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart3_pins>;
 };
 
 &uart4 {
-	interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+	interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core OMAP4_UART4_RX>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart4_pins>;
arch/arm/boot/dts/omap4-var-som-om44.dtsi +0 -2
index 062701e..a4f1ba2 100644
@@ -185,7 +185,6 @@
 		reg = <0x48>;
 		/* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-		interrupt-parent = <&gic>;
 	};
 
 	twl6040: twl at 4b {
@@ -197,7 +196,6 @@
 
 		/* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
 		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-		interrupt-parent = <&gic>;
 		ti,audpwron-gpio = <&gpio6 22 0>; /* gpio 182 */
 
 		vio-supply = <&v1v8>;
arch/arm/boot/dts/omap4.dtsi +14 -4
index 074147c..7cb5236 100644
@@ -14,7 +14,7 @@
 
 / {
 	compatible = "ti,omap4430", "ti,omap4";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&wakeupgen>;
 
 	aliases {
 		i2c0 = &i2c1;
@@ -56,6 +56,7 @@
 		#interrupt-cells = <3>;
 		reg = <0x48241000 0x1000>,
 		      <0x48240100 0x0100>;
+		interrupt-parent = <&gic>;
 	};
 
 	L2: l2-cache-controller at 48242000 {
@@ -70,6 +71,15 @@
 		clocks = <&mpu_periphclk>;
 		reg = <0x48240600 0x20>;
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
+	};
+
+	wakeupgen: interrupt-controller at 48281000 {
+		compatible = "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
 	};
 
 	/*
@@ -319,7 +329,7 @@
 		uart2: serial at 4806c000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806c000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 		};
@@ -327,7 +337,7 @@
 		uart3: serial at 48020000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48020000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 		};
@@ -335,7 +345,7 @@
 		uart4: serial at 4806e000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806e000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
 		};
arch/arm/boot/dts/omap5-cm-t54.dts +0 -1
index b54b271..61ad2ea 100644
@@ -412,7 +412,6 @@
 	palmas: palmas at 48 {
 		compatible = "ti,palmas";
 		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-		interrupt-parent = <&gic>;
 		reg = <0x48>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
arch/arm/boot/dts/omap5-uevm.dts +0 -2
index 159720d..74777a6 100644
@@ -311,7 +311,6 @@
 	palmas: palmas at 48 {
 		compatible = "ti,palmas";
 		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-		interrupt-parent = <&gic>;
 		reg = <0x48>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
@@ -521,7 +520,6 @@
 		pinctrl-0 = <&twl6040_pins>;
 
 		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
-		interrupt-parent = <&gic>;
 		ti,audpwron-gpio = <&gpio5 13 0>;  /* gpio line 141 */
 
 		vio-supply = <&smps7_reg>;
arch/arm/boot/dts/omap5.dtsi +17 -9
index b321fdf..b056156 100644
@@ -18,7 +18,7 @@
 	#size-cells = <1>;
 
 	compatible = "ti,omap5";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&wakeupgen>;
 
 	aliases {
 		i2c0 = &i2c1;
@@ -79,6 +79,7 @@
 			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>;
+		interrupt-parent = <&gic>;
 	};
 
 	pmu {
@@ -95,6 +96,15 @@
 		      <0x48212000 0x1000>,
 		      <0x48214000 0x2000>,
 		      <0x48216000 0x2000>;
+		interrupt-parent = <&gic>;
+	};
+
+	wakeupgen: interrupt-controller at 48281000 {
+		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
 	};
 
 	/*
@@ -458,7 +468,7 @@
 		uart1: serial at 4806a000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806a000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 		};
@@ -466,7 +476,7 @@
 		uart2: serial at 4806c000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806c000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 		};
@@ -474,7 +484,7 @@
 		uart3: serial at 48020000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48020000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 		};
@@ -482,7 +492,7 @@
 		uart4: serial at 4806e000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806e000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
 		};
@@ -490,7 +500,7 @@
 		uart5: serial at 48066000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48066000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
 		};
@@ -498,7 +508,7 @@
 		uart6: serial at 48068000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x48068000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 		};
@@ -883,14 +893,12 @@
 			usbhsohci: ohci at 4a064800 {
 				compatible = "ti,ohci-omap3";
 				reg = <0x4a064800 0x400>;
-				interrupt-parent = <&gic>;
 				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			usbhsehci: ehci at 4a064c00 {
 				compatible = "ti,ehci-omap";
 				reg = <0x4a064c00 0x400>;
-				interrupt-parent = <&gic>;
 				interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
arch/arm/mach-omap2/omap-wakeupgen.c +95 -30

192 lines not on this page · raw message

arch/arm/mach-omap2/omap-wakeupgen.h +0 -1
index b3c8ecc..a3491ad 100644
@@ -33,7 +33,6 @@
 #define OMAP_TIMESTAMPCYCLELO			0xc08
 #define OMAP_TIMESTAMPCYCLEHI			0xc0c
 
-extern int __init omap_wakeupgen_init(void);
 extern void __iomem *omap_get_wakeupgen_base(void);
 extern int omap_secure_apis_support(void);
 #endif
arch/arm/mach-omap2/omap4-common.c +8 -9
index b88520d..c108e9d 100644
@@ -255,26 +255,26 @@ static int __init omap4_sar_ram_init(void)
 }
 omap_early_initcall(omap4_sar_ram_init);
 
-static struct of_device_id gic_match[] = {
-	{ .compatible = "arm,cortex-a9-gic", },
-	{ .compatible = "arm,cortex-a15-gic", },
+static struct of_device_id intc_match[] = {
+	{ .compatible = "ti,omap4-wugen-mpu", },
+	{ .compatible = "ti,omap5-wugen-mpu", },
 	{ },
 };
 
-static struct device_node *gic_node;
+static struct device_node *intc_node;
 
 unsigned int omap4_xlate_irq(unsigned int hwirq)
 {
 	struct of_phandle_args irq_data;
 	unsigned int irq;
 
-	if (!gic_node)
-		gic_node = of_find_matching_node(NULL, gic_match);
+	if (!intc_node)
+		intc_node = of_find_matching_node(NULL, intc_match);
 
-	if (WARN_ON(!gic_node))
+	if (WARN_ON(!intc_node))
 		return hwirq;
 
-	irq_data.np = gic_node;
+	irq_data.np = intc_node;
 	irq_data.args_count = 3;
 	irq_data.args[0] = 0;
 	irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START;
@@ -304,6 +304,5 @@ void __init omap_gic_of_init(void)
 	WARN_ON(!twd_base);
 
 skip_errata_init:
-	omap_wakeupgen_init();
 	irqchip_init();
 }
Signature · 1 line
2.1.4
maintainer
#16 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 15 lines · Marc Zyngier

OMAP4/5 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the WUGEN HW block, kernels with this patch applied won't have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

On a platform with this patch applied, the system looks like this:

Quoted 8 lines

root at bacon-fat:~# cat /proc/interrupts
CPU0 CPU1

 16:          0          0     WUGEN  37  gp_timer
 19:     233799     155916       GIC  27  arch_timer
 23:          0          0     WUGEN   9  l3-dbg-irq
 24:          1          0     WUGEN  10  l3-app-irq
 27:        282          0     WUGEN  13  omap-dma-engine

44: 0 0 4ae10000.gpio 13 DMA

You may want to update this part for the fix :)

I gave this a quick boot test on am437x-gp-evm and the interrupts look OK with the fix also applied:

# cat /proc/interrupts 
            CPU0       
 16:        657     WUGEN  68  gp_timer
 18:          0     WUGEN   9  l3-dbg-irq
 19:          0     WUGEN  10  l3-app-irq
 20:          5     WUGEN  12  edma
 22:          0     WUGEN  14  edma_error
 23:         96     WUGEN  72  OMAP UART0
 33:          0  44e07000.gpio   6  mmc0
158:         52     WUGEN  70  44e0b000.i2c
159:          0     WUGEN  71  4802a000.i2c
160:         35     WUGEN  64  mmc0
161:          0     WUGEN  40  4a100000.ethernet
162:       7739     WUGEN  41  4a100000.ethernet
163:       7608     WUGEN  42  4a100000.ethernet
164:          0     WUGEN  43  4a100000.ethernet
170:          0     WUGEN 100  gpmc
180:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0

Also verified that suspend and resume to a serial console event works on omap4430-sdp. So please feel free to add:

#17 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 25 lines · Tony Lindgren
Quoted 15 lines · Marc Zyngier

OMAP4/5 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the WUGEN HW block, kernels with this patch applied won't have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

On a platform with this patch applied, the system looks like this:

Quoted 8 lines

root at bacon-fat:~# cat /proc/interrupts
CPU0 CPU1

 16:          0          0     WUGEN  37  gp_timer
 19:     233799     155916       GIC  27  arch_timer
 23:          0          0     WUGEN   9  l3-dbg-irq
 24:          1          0     WUGEN  10  l3-app-irq
 27:        282          0     WUGEN  13  omap-dma-engine

44: 0 0 4ae10000.gpio 13 DMA

Quoted 1 line

You may want to update this part for the fix :)

Ah, yes. Thanks for noticing this.

Quoted 22 lines

I gave this a quick boot test on am437x-gp-evm and the interrupts look OK with the fix also applied:

# cat /proc/interrupts 
            CPU0       
 16:        657     WUGEN  68  gp_timer
 18:          0     WUGEN   9  l3-dbg-irq
 19:          0     WUGEN  10  l3-app-irq
 20:          5     WUGEN  12  edma
 22:          0     WUGEN  14  edma_error
 23:         96     WUGEN  72  OMAP UART0
 33:          0  44e07000.gpio   6  mmc0
158:         52     WUGEN  70  44e0b000.i2c
159:          0     WUGEN  71  4802a000.i2c
160:         35     WUGEN  64  mmc0
161:          0     WUGEN  40  4a100000.ethernet
162:       7739     WUGEN  41  4a100000.ethernet
163:       7608     WUGEN  42  4a100000.ethernet
164:          0     WUGEN  43  4a100000.ethernet
170:          0     WUGEN 100  gpmc
180:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
Quoted 8 lines
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0

Interesting. No TWD timer on this one?

Quoted 4 lines

Also verified that suspend and resume to a serial console event works on omap4430-sdp. So please feel free to add:

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
maintainer
#18 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 33 lines · Marc Zyngier
Quoted 22 lines · Tony Lindgren

I gave this a quick boot test on am437x-gp-evm and the interrupts look OK with the fix also applied:

# cat /proc/interrupts 
            CPU0       
 16:        657     WUGEN  68  gp_timer
 18:          0     WUGEN   9  l3-dbg-irq
 19:          0     WUGEN  10  l3-app-irq
 20:          5     WUGEN  12  edma
 22:          0     WUGEN  14  edma_error
 23:         96     WUGEN  72  OMAP UART0
 33:          0  44e07000.gpio   6  mmc0
158:         52     WUGEN  70  44e0b000.i2c
159:          0     WUGEN  71  4802a000.i2c
160:         35     WUGEN  64  mmc0
161:          0     WUGEN  40  4a100000.ethernet
162:       7739     WUGEN  41  4a100000.ethernet
163:       7608     WUGEN  42  4a100000.ethernet
164:          0     WUGEN  43  4a100000.ethernet
170:          0     WUGEN 100  gpmc
180:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
Quoted 8 lines
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0
Quoted 1 line

Interesting. No TWD timer on this one?

Good question, adding Felipe to cc. It eems to be there in the TRM in "Table 2-3. L4_PER Peripheral Memory Map" as MPU_PRV_TIMERS. Also seems to actually work with the attached patch:

# cat /proc/interrupts 
            CPU0       
 16:          0     WUGEN  67  gp_timer
 17:        529       GIC  29  twd
 18:          0     WUGEN   9  l3-dbg-irq
 19:          0     WUGEN  10  l3-app-irq
 20:          5     WUGEN  12  edma
 22:          0     WUGEN  14  edma_error
 23:        130     WUGEN  72  OMAP UART0
 34:          0  44e07000.gpio   6  mmc0
159:         52     WUGEN  70  44e0b000.i2c
160:          0     WUGEN  71  4802a000.i2c
161:         35     WUGEN  64  mmc0
162:          0     WUGEN  40  4a100000.ethernet
163:       8033     WUGEN  41  4a100000.ethernet
164:       7769     WUGEN  42  4a100000.ethernet
165:          0     WUGEN  43  4a100000.ethernet
171:          0     WUGEN 100  gpmc
181:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0

Hmm I wonder why we have the !is_smp() check in the TWD timer?

Regards,

Tony

8< -------------------

arch/arm/boot/dts/am4372.dtsi +8 -0
@@ -51,6 +51,14 @@
 		interrupt-parent = <&gic>;
 	};
 
+	local-timer at 48240600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		clocks = <&dpll_mpu_m2_ck>;
+		reg = <0x48240600 0x20>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
+	};
+
 	wakeupgen: interrupt-controller at 48281000 {
 		compatible = "ti,omap4-wugen-mpu";
 		interrupt-controller;
arch/arm/kernel/smp_twd.c +1 -1
@@ -388,7 +388,7 @@ static void __init twd_local_timer_of_register(struct device_node *np)
 {
 	int err;
 
-	if (!is_smp() || !setup_max_cpus)
+	if (!setup_max_cpus)
 		return;
 
 	twd_ppi = irq_of_parse_and_map(np, 0);
arch/arm/mach-omap2/board-generic.c +1 -1
@@ -237,7 +237,7 @@ DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)")
 	.init_late	= am43xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
-	.init_time	= omap3_gptimer_timer_init,
+	.init_time	= omap4_local_timer_init,
 	.dt_compat	= am43_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
#19 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 34 lines · Tony Lindgren
Quoted 33 lines · Marc Zyngier
Quoted 30 lines · Tony Lindgren

I gave this a quick boot test on am437x-gp-evm and the interrupts look OK with the fix also applied:

# cat /proc/interrupts
             CPU0
  16:        657     WUGEN  68  gp_timer
  18:          0     WUGEN   9  l3-dbg-irq
  19:          0     WUGEN  10  l3-app-irq
  20:          5     WUGEN  12  edma
  22:          0     WUGEN  14  edma_error
  23:         96     WUGEN  72  OMAP UART0
  33:          0  44e07000.gpio   6  mmc0
158:         52     WUGEN  70  44e0b000.i2c
159:          0     WUGEN  71  4802a000.i2c
160:         35     WUGEN  64  mmc0
161:          0     WUGEN  40  4a100000.ethernet
162:       7739     WUGEN  41  4a100000.ethernet
163:       7608     WUGEN  42  4a100000.ethernet
164:          0     WUGEN  43  4a100000.ethernet
170:          0     WUGEN 100  gpmc
180:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0
Quoted 7 lines
Quoted 1 line

Interesting. No TWD timer on this one?

Good question, adding Felipe to cc. It eems to be there in the TRM in "Table 2-3. L4_PER Peripheral Memory Map" as MPU_PRV_TIMERS. Also seems to actually work with the attached patch:

TWD is useless on this machine since single core and TWD as know die in low power states. All the broadcast stuff is for SMP machines.

Above is expected and correct and no patching is needed.

Regards,
Santosh

maintainer
#20 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 37 lines · santosh shilimkar
Quoted 36 lines · Tony Lindgren
Quoted 34 lines · Marc Zyngier
Quoted 22 lines · Tony Lindgren

I gave this a quick boot test on am437x-gp-evm and the interrupts look OK with the fix also applied:

# cat /proc/interrupts
            CPU0
 16:        657     WUGEN  68  gp_timer
 18:          0     WUGEN   9  l3-dbg-irq
 19:          0     WUGEN  10  l3-app-irq
 20:          5     WUGEN  12  edma
 22:          0     WUGEN  14  edma_error
 23:         96     WUGEN  72  OMAP UART0
 33:          0  44e07000.gpio   6  mmc0
158:         52     WUGEN  70  44e0b000.i2c
159:          0     WUGEN  71  4802a000.i2c
160:         35     WUGEN  64  mmc0
161:          0     WUGEN  40  4a100000.ethernet
162:       7739     WUGEN  41  4a100000.ethernet
163:       7608     WUGEN  42  4a100000.ethernet
164:          0     WUGEN  43  4a100000.ethernet
170:          0     WUGEN 100  gpmc
180:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
Quoted 8 lines
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0

Interesting. No TWD timer on this one?

Quoted 8 lines
Quoted 5 lines

Good question, adding Felipe to cc. It eems to be there in the TRM in "Table 2-3. L4_PER Peripheral Memory Map" as MPU_PRV_TIMERS. Also seems to actually work with the attached patch:

TWD is useless on this machine since single core and TWD as know die in low power states. All the broadcast stuff is for SMP machines.

Hmm it seems we should still use TWD during runtime and swich over to the gptimer for idle states for wake-up events.

Regards,

Tony

#21 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 43 lines · Tony Lindgren
Quoted 42 lines · santosh shilimkar
Quoted 41 lines · Tony Lindgren
Quoted 33 lines · Marc Zyngier
Quoted 22 lines · Tony Lindgren

I gave this a quick boot test on am437x-gp-evm and the interrupts look OK with the fix also applied:

# cat /proc/interrupts
             CPU0
  16:        657     WUGEN  68  gp_timer
  18:          0     WUGEN   9  l3-dbg-irq
  19:          0     WUGEN  10  l3-app-irq
  20:          5     WUGEN  12  edma
  22:          0     WUGEN  14  edma_error
  23:         96     WUGEN  72  OMAP UART0
  33:          0  44e07000.gpio   6  mmc0
158:         52     WUGEN  70  44e0b000.i2c
159:          0     WUGEN  71  4802a000.i2c
160:         35     WUGEN  64  mmc0
161:          0     WUGEN  40  4a100000.ethernet
162:       7739     WUGEN  41  4a100000.ethernet
163:       7608     WUGEN  42  4a100000.ethernet
164:          0     WUGEN  43  4a100000.ethernet
170:          0     WUGEN 100  gpmc
180:          0     WUGEN   7  tps65218
IPI0:          0  CPU wakeup interrupts
Quoted 8 lines
IPI1:          0  Timer broadcast interrupts
IPI2:          0  Rescheduling interrupts
IPI3:          0  Function call interrupts
IPI4:          0  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0
Quoted 1 line

Interesting. No TWD timer on this one?

Good question, adding Felipe to cc. It eems to be there in the TRM in "Table 2-3. L4_PER Peripheral Memory Map" as MPU_PRV_TIMERS. Also seems to actually work with the attached patch:

Quoted 8 lines
Quoted 3 lines

TWD is useless on this machine since single core and TWD as know die in low power states. All the broadcast stuff is for SMP machines.

Hmm it seems we should still use TWD during runtime and swich over to the gptimer for idle states for wake-up events.

Well timer wheel code don't support it so if you are serious, some one needs to do that. For me, it is not worth at all. You will have more to loose than gain with these time switching schemes since you have to keep 2 times alive, do switching, loose the idle time.

All of that is to save few CPU cycles since TWD is closer compared to other SOC timer.

Anyways I will let you fight it out but IIRC, I had a discussion a while back with tglx in one of the conference and the conclusion was it not worth doing.
Rather TWD hardware on SOC should be made wakeup capable and then everything is good.

Till you have support, using TWD on AM43XX will break CPUIDLE. Not sure if it is supported or some one cares about it. Just keep that aspect in mind.

Regards,
Santosh

maintainer
#22 lore raw

PATCH v4 13/21 ARM: omap: convert wakeupgen to stacked domains

Quoted 26 lines · santosh shilimkar
Quoted 10 lines · Tony Lindgren
Quoted 4 lines · santosh shilimkar

TWD is useless on this machine since single core and TWD as know die in low power states. All the broadcast stuff is for SMP machines.

Hmm it seems we should still use TWD during runtime and swich over to the gptimer for idle states for wake-up events.

Well timer wheel code don't support it so if you are serious, some one needs to do that. For me, it is not worth at all. You will have more to loose than gain with these time switching schemes since you have to keep 2 times alive, do switching, loose the idle time.

All of that is to save few CPU cycles since TWD is closer compared to other SOC timer.

Anyways I will let you fight it out but IIRC, I had a discussion a while back with tglx in one of the conference and the conclusion was it not worth doing.
Rather TWD hardware on SOC should be made wakeup capable and then everything is good.

Quoted 3 lines

Till you have support, using TWD on AM43XX will break CPUIDLE. Not sure if it is supported or some one cares about it. Just keep that aspect in mind.

Yes sure I'm aware of this. It should be easy to profile the speed gain to see if it would make much of a difference before starting to tinker with that.

The way I think it's possible to do would be to copy the TWD timer value to a wake-up capable gptimer before hitting any deeper idle state. Of course some aux timer support might be still needed :)

Regards,

Tony

#23 lore raw

PATCH v4 14/21 ARM: imx6: convert GPC to stacked domains

In reply to Marc Zyngier

IMX6 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the GPC block is actually the first interrupt controller in the chain, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

---
 arch/arm/boot/dts/imx6qdl.dtsi  |   7 ++-
 arch/arm/boot/dts/imx6sl.dtsi   |   6 +-
 arch/arm/boot/dts/imx6sx.dtsi   |   6 +-
 arch/arm/mach-imx/common.h      |   1 -
 arch/arm/mach-imx/gpc.c         | 127 ++++++++++++++++++++++++++++++++--------
 arch/arm/mach-imx/mach-imx6q.c  |   1 -
 arch/arm/mach-imx/mach-imx6sl.c |   1 -
 arch/arm/mach-imx/mach-imx6sx.c |   1 -
 8 files changed, 119 insertions(+), 31 deletions(-)
arch/arm/boot/dts/imx6qdl.dtsi +6 -1
index 4fc03b7..aff9ded 100644
@@ -53,6 +53,7 @@
 		interrupt-controller;
 		reg = <0x00a01000 0x1000>,
 		      <0x00a00100 0x100>;
+		interrupt-parent = <&intc>;
 	};
 
 	clocks {
@@ -82,7 +83,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
-		interrupt-parent = <&intc>;
+		interrupt-parent = <&gpc>;
 		ranges;
 
 		dma_apbh: dma-apbh at 00110000 {
@@ -122,6 +123,7 @@
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0x00a00600 0x20>;
 			interrupts = <1 13 0xf01>;
+			interrupt-parent = <&intc>;
 			clocks = <&clks IMX6QDL_CLK_TWD>;
 		};
 
@@ -694,8 +696,11 @@
 			gpc: gpc at 020dc000 {
 				compatible = "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
+				#interrupt-cells = <3>;
 				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			gpr: iomuxc-gpr at 020e0000 {
arch/arm/boot/dts/imx6sl.dtsi +5 -1
index 36ab8e0..0d0962b 100644
@@ -72,6 +72,7 @@
 		interrupt-controller;
 		reg = <0x00a01000 0x1000>,
 		      <0x00a00100 0x100>;
+		interrupt-parent = <&intc>;
 	};
 
 	clocks {
@@ -95,7 +96,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
-		interrupt-parent = <&intc>;
+		interrupt-parent = <&gpc>;
 		ranges;
 
 		ocram: sram at 00900000 {
@@ -603,7 +604,10 @@
 			gpc: gpc at 020dc000 {
 				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
+				#interrupt-cells = <3>;
 				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			gpr: iomuxc-gpr at 020e0000 {
arch/arm/boot/dts/imx6sx.dtsi +5 -1
index 7a24fee..dabaf89 100644
@@ -88,6 +88,7 @@
 		interrupt-controller;
 		reg = <0x00a01000 0x1000>,
 		      <0x00a00100 0x100>;
+		interrupt-parent = <&intc>;
 	};
 
 	clocks {
@@ -131,7 +132,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "simple-bus";
-		interrupt-parent = <&intc>;
+		interrupt-parent = <&gpc>;
 		ranges;
 
 		pmu {
@@ -700,7 +701,10 @@
 			gpc: gpc at 020dc000 {
 				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
+				#interrupt-cells = <3>;
 				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			iomuxc: iomuxc at 020e0000 {
arch/arm/mach-imx/common.h +0 -1
index cfcdb62..7052302 100644
@@ -102,7 +102,6 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 #endif
 void imx_src_init(void);
-void imx_gpc_init(void);
 void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
arch/arm/mach-imx/gpc.c +103 -24

177 lines not on this page · raw message

arch/arm/mach-imx/mach-imx6q.c +0 -1
index 5057d61..bbe6ff8 100644
@@ -390,7 +390,6 @@ static void __init imx6q_init_irq(void)
 	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
-	imx_gpc_init();
 	irqchip_init();
 }
 
arch/arm/mach-imx/mach-imx6sl.c +0 -1
index 24bfaaf..d39c274 100644
@@ -64,7 +64,6 @@ static void __init imx6sl_init_irq(void)
 	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
-	imx_gpc_init();
 	irqchip_init();
 }
 
arch/arm/mach-imx/mach-imx6sx.c +0 -1
index 7a96c65..72fa22d 100644
@@ -84,7 +84,6 @@ static void __init imx6sx_init_irq(void)
 	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
-	imx_gpc_init();
 	irqchip_init();
 }
 
Signature · 1 line
2.1.4
#24 lore raw

PATCH v4 14/21 ARM: imx6: convert GPC to stacked domains

Am Montag, den 19.01.2015, 09:44 +0000 schrieb Marc Zyngier:

Quoted 27 lines

IMX6 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the GPC block is actually the first interrupt controller in the chain, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

---
 arch/arm/boot/dts/imx6qdl.dtsi  |   7 ++-
 arch/arm/boot/dts/imx6sl.dtsi   |   6 +-
 arch/arm/boot/dts/imx6sx.dtsi   |   6 +-
 arch/arm/mach-imx/common.h      |   1 -
 arch/arm/mach-imx/gpc.c         | 127 ++++++++++++++++++++++++++++++++--------
 arch/arm/mach-imx/mach-imx6q.c  |   1 -
 arch/arm/mach-imx/mach-imx6sl.c |   1 -
 arch/arm/mach-imx/mach-imx6sx.c |   1 -
 8 files changed, 119 insertions(+), 31 deletions(-)

[...]

Quoted 186 lines
arch/arm/mach-imx/common.h +0 -1
@@ -102,7 +102,6 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 #endif
 void imx_src_init(void);
-void imx_gpc_init(void);
 void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
arch/arm/mach-imx/gpc.c +96 -22
index 5f3602e..838da3c 100644
@@ -22,6 +22,7 @@
 #define GPC_PGC_CPU_PDN		0x2a0
 
 #define IMR_NUM			4
+#define GPC_MAX_IRQS		(IMR_NUM * 32)
 
 static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
@@ -56,17 +57,17 @@ void imx_gpc_post_resume(void)
 
 static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-	unsigned int idx = d->hwirq / 32 - 1;
+	unsigned int idx = d->hwirq / 32;
 	u32 mask;
 
-	/* Sanity check for SPI irq */
-	if (d->hwirq < 32)
-		return -EINVAL;
-
 	mask = 1 << d->hwirq % 32;
 	gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
 				  gpc_wake_irqs[idx] & ~mask;
 
+	/*
+	 * Do *not* call into the parent, as the GIC doesn't have any
+	 * wake-up facility...
+	 */
 	return 0;
 }
 
@@ -96,7 +97,7 @@ void imx_gpc_hwirq_unmask(unsigned int hwirq)
 	void __iomem *reg;
 	u32 val;
 
-	reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+	reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
 	val = readl_relaxed(reg);
 	val &= ~(1 << hwirq % 32);
 	writel_relaxed(val, reg);
@@ -107,7 +108,7 @@ void imx_gpc_hwirq_mask(unsigned int hwirq)
 	void __iomem *reg;
 	u32 val;
 
-	reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+	reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
 	val = readl_relaxed(reg);
 	val |= 1 << (hwirq % 32);
 	writel_relaxed(val, reg);
@@ -115,37 +116,115 @@ void imx_gpc_hwirq_mask(unsigned int hwirq)
 
 static void imx_gpc_irq_unmask(struct irq_data *d)
 {
-	/* Sanity check for SPI irq */
-	if (d->hwirq < 32)
-		return;
-
 	imx_gpc_hwirq_unmask(d->hwirq);
+	irq_chip_unmask_parent(d);
 }
 
 static void imx_gpc_irq_mask(struct irq_data *d)
 {
-	/* Sanity check for SPI irq */
-	if (d->hwirq < 32)
-		return;
-
 	imx_gpc_hwirq_mask(d->hwirq);
+	irq_chip_mask_parent(d);
+}
+
+static struct irq_chip imx_gpc_chip = {
+	.name		= "GPC",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= imx_gpc_irq_mask,
+	.irq_unmask	= imx_gpc_irq_unmask,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= imx_gpc_irq_set_wake,
+};
+
+static int imx_gpc_domain_xlate(struct irq_domain *domain,
+				struct device_node *controller,
+				const u32 *intspec,
+				unsigned int intsize,
+				unsigned long *out_hwirq,
+				unsigned int *out_type)
+{
+	if (domain->of_node != controller)
+		return -EINVAL;	/* Shouldn't happen, really... */
+	if (intsize != 3)
+		return -EINVAL;	/* Not GIC compliant */
+	if (intspec[0] != 0)
+		return -EINVAL;	/* No PPI should point to this domain */
+
+	*out_hwirq = intspec[1];
+	*out_type = intspec[2];
+	return 0;
+}
+
+static int imx_gpc_domain_alloc(struct irq_domain *domain,
+				  unsigned int irq,
+				  unsigned int nr_irqs, void *data)
+{
+	struct of_phandle_args *args = data;
+	struct of_phandle_args parent_args;
+	irq_hw_number_t hwirq;
+	int i;
+
+	if (args->args_count != 3)
+		return -EINVAL;	/* Not GIC compliant */
+	if (args->args[0] != 0)
+		return -EINVAL;	/* No PPI should point to this domain */
+
+	hwirq = args->args[1];
+	if (hwirq >= GPC_MAX_IRQS)
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
+					      &imx_gpc_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
 }
 
-void __init imx_gpc_init(void)
+static struct irq_domain_ops imx_gpc_domain_ops = {
+	.xlate	= imx_gpc_domain_xlate,
+	.alloc	= imx_gpc_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
+static int __init imx_gpc_init(struct device_node *node,
+			       struct device_node *parent)
 {
-	struct device_node *np;
+	struct irq_domain *parent_domain, *domain;
 	int i;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
-	gpc_base = of_iomap(np, 0);
-	WARN_ON(!gpc_base);
+	if (!parent) {
+		pr_err("%s: no parent, giving up\n", node->full_name);
+		return -ENODEV;
+	}
+
+	parent_domain = irq_find_host(parent);
+	if (!parent_domain) {
+		pr_err("%s: unable to obtain parent domain\n", node->full_name);
+		return -ENXIO;
+	}
+
+	gpc_base = of_iomap(node, 0);
+	if (WARN_ON(!gpc_base))
+	        return -ENOMEM;
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
+					  node, &imx_gpc_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(gpc_base);
+		return -ENOMEM;
+	}
 
 	/* Initially mask all interrupts */
 	for (i = 0; i < IMR_NUM; i++)
 		writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
 
-	/* Register GPC as the secondary interrupt controller behind GIC */
-	gic_arch_extn.irq_mask = imx_gpc_irq_mask;

arch/arm/mach-imx/gpc.c void imx_gpc_hwirq_mask(unsigned int hwirq) · line 230

Quoted 10 lines
arch/arm/mach-imx/gpc.c +7 -2
-	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
-	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+	return 0;
 }
+
+/*
+ * We cannot use the IRQCHIP_DECLARE macro that lives in
+ * drivers/irqchip, so we're forced to roll our own. Not very nice.
+ */
+OF_DECLARE_2(irqchip, imx_gpc, "fsl,imx6q-gpc", imx_gpc_init);

The above seems to be a recurring pattern, so it might be a good idea to expose the irqchip header.

But in the case of the GPC I don't see anything after your patch that would make it tied into the arch. So can you just move this driver to the irqchip directory?

Regards,
Lucas

#25 lore raw

PATCH v4 14/21 ARM: imx6: convert GPC to stacked domains

Quoted 214 lines · Lucas Stach

Am Montag, den 19.01.2015, 09:44 +0000 schrieb Marc Zyngier:

Quoted 27 lines

IMX6 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the GPC block is actually the first interrupt controller in the chain, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

---
 arch/arm/boot/dts/imx6qdl.dtsi  |   7 ++-
 arch/arm/boot/dts/imx6sl.dtsi   |   6 +-
 arch/arm/boot/dts/imx6sx.dtsi   |   6 +-
 arch/arm/mach-imx/common.h      |   1 -
 arch/arm/mach-imx/gpc.c         | 127 ++++++++++++++++++++++++++++++++--------
 arch/arm/mach-imx/mach-imx6q.c  |   1 -
 arch/arm/mach-imx/mach-imx6sl.c |   1 -
 arch/arm/mach-imx/mach-imx6sx.c |   1 -
 8 files changed, 119 insertions(+), 31 deletions(-)

[...]

Quoted 184 lines
arch/arm/mach-imx/common.h +0 -1
@@ -102,7 +102,6 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 #endif
 void imx_src_init(void);
-void imx_gpc_init(void);
 void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
arch/arm/mach-imx/gpc.c +96 -20
index 5f3602e..838da3c 100644
@@ -22,6 +22,7 @@
 #define GPC_PGC_CPU_PDN		0x2a0
 
 #define IMR_NUM			4
+#define GPC_MAX_IRQS		(IMR_NUM * 32)
 
 static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
@@ -56,17 +57,17 @@ void imx_gpc_post_resume(void)
 
 static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-	unsigned int idx = d->hwirq / 32 - 1;
+	unsigned int idx = d->hwirq / 32;
 	u32 mask;
 
-	/* Sanity check for SPI irq */
-	if (d->hwirq < 32)
-		return -EINVAL;
-
 	mask = 1 << d->hwirq % 32;
 	gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
 				  gpc_wake_irqs[idx] & ~mask;
 
+	/*
+	 * Do *not* call into the parent, as the GIC doesn't have any
+	 * wake-up facility...
+	 */
 	return 0;
 }
 
@@ -96,7 +97,7 @@ void imx_gpc_hwirq_unmask(unsigned int hwirq)
 	void __iomem *reg;
 	u32 val;
 
-	reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+	reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
 	val = readl_relaxed(reg);
 	val &= ~(1 << hwirq % 32);
 	writel_relaxed(val, reg);
@@ -107,7 +108,7 @@ void imx_gpc_hwirq_mask(unsigned int hwirq)
 	void __iomem *reg;
 	u32 val;
 
-	reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+	reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
 	val = readl_relaxed(reg);
 	val |= 1 << (hwirq % 32);
 	writel_relaxed(val, reg);
@@ -115,37 +116,115 @@ void imx_gpc_hwirq_mask(unsigned int hwirq)
 
 static void imx_gpc_irq_unmask(struct irq_data *d)
 {
-	/* Sanity check for SPI irq */
-	if (d->hwirq < 32)
-		return;
-
 	imx_gpc_hwirq_unmask(d->hwirq);
+	irq_chip_unmask_parent(d);
 }
 
 static void imx_gpc_irq_mask(struct irq_data *d)
 {
-	/* Sanity check for SPI irq */
-	if (d->hwirq < 32)
-		return;
-
 	imx_gpc_hwirq_mask(d->hwirq);
+	irq_chip_mask_parent(d);
+}
+
+static struct irq_chip imx_gpc_chip = {
+	.name		= "GPC",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= imx_gpc_irq_mask,
+	.irq_unmask	= imx_gpc_irq_unmask,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= imx_gpc_irq_set_wake,
+};
+
+static int imx_gpc_domain_xlate(struct irq_domain *domain,
+				struct device_node *controller,
+				const u32 *intspec,
+				unsigned int intsize,
+				unsigned long *out_hwirq,
+				unsigned int *out_type)
+{
+	if (domain->of_node != controller)
+		return -EINVAL;	/* Shouldn't happen, really... */
+	if (intsize != 3)
+		return -EINVAL;	/* Not GIC compliant */
+	if (intspec[0] != 0)
+		return -EINVAL;	/* No PPI should point to this domain */
+
+	*out_hwirq = intspec[1];
+	*out_type = intspec[2];
+	return 0;
+}
+
+static int imx_gpc_domain_alloc(struct irq_domain *domain,
+				  unsigned int irq,
+				  unsigned int nr_irqs, void *data)
+{
+	struct of_phandle_args *args = data;
+	struct of_phandle_args parent_args;
+	irq_hw_number_t hwirq;
+	int i;
+
+	if (args->args_count != 3)
+		return -EINVAL;	/* Not GIC compliant */
+	if (args->args[0] != 0)
+		return -EINVAL;	/* No PPI should point to this domain */
+
+	hwirq = args->args[1];
+	if (hwirq >= GPC_MAX_IRQS)
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
+					      &imx_gpc_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
 }
 
-void __init imx_gpc_init(void)
+static struct irq_domain_ops imx_gpc_domain_ops = {
+	.xlate	= imx_gpc_domain_xlate,
+	.alloc	= imx_gpc_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
+static int __init imx_gpc_init(struct device_node *node,
+			       struct device_node *parent)
 {
-	struct device_node *np;
+	struct irq_domain *parent_domain, *domain;
 	int i;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
-	gpc_base = of_iomap(np, 0);
-	WARN_ON(!gpc_base);
+	if (!parent) {
+		pr_err("%s: no parent, giving up\n", node->full_name);
+		return -ENODEV;
+	}
+
+	parent_domain = irq_find_host(parent);
+	if (!parent_domain) {
+		pr_err("%s: unable to obtain parent domain\n", node->full_name);
+		return -ENXIO;
+	}
+
+	gpc_base = of_iomap(node, 0);
+	if (WARN_ON(!gpc_base))
+	        return -ENOMEM;
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
+					  node, &imx_gpc_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(gpc_base);
+		return -ENOMEM;
+	}
 
 	/* Initially mask all interrupts */
 	for (i = 0; i < IMR_NUM; i++)
 		writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
 
Quoted 15 lines

arch/arm/mach-imx/gpc.c void imx_gpc_hwirq_mask(unsigned int hwirq) · line 230

Quoted 12 lines
arch/arm/mach-imx/gpc.c +7 -4
-	/* Register GPC as the secondary interrupt controller behind GIC */
-	gic_arch_extn.irq_mask = imx_gpc_irq_mask;
-	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
-	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+	return 0;
 }
+
+/*
+ * We cannot use the IRQCHIP_DECLARE macro that lives in
+ * drivers/irqchip, so we're forced to roll our own. Not very nice.
+ */
+OF_DECLARE_2(irqchip, imx_gpc, "fsl,imx6q-gpc", imx_gpc_init);

The above seems to be a recurring pattern, so it might be a good idea to expose the irqchip header.

My theory is that by keeping it ugly, the maintainers will get the message and move the code around on their own. Probably wishful thinking, but hey...

Quoted 3 lines

But in the case of the GPC I don't see anything after your patch that would make it tied into the arch. So can you just move this driver to the irqchip directory?

At least imx_gpc_hwirq_[un]mask are directly used from the PM code, and I have no idea how this interacts with the rest of the platform.

It would be possible to force the creation of an irq mapped to hwirq #32 at boot time, and then use that to drive the mask/unmask using the standard kernel API, but that will also have an impact on the GIC masking, and someone needs to find out if that breaks anything.

Furthermore, I do not have access to the HW, so whoever cares about it should go ahead and fix it.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#26 lore raw

PATCH v4 14/21 ARM: imx6: convert GPC to stacked domains

In reply to Marc Zyngier
Quoted 13 lines · Marc Zyngier

IMX6 has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the GPC block is actually the first interrupt controller in the chain, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs won't even boot.

Quoted 3 lines
#27 lore raw

PATCH v4 15/21 ARM: exynos4/5: convert pmu wakeup to stacked domains

In reply to Marc Zyngier

Exynos has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the PMU block is actually the first interrupt controller in the chain for RTC, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs may not even boot.

Also, I stronly suspect that there is more than two wake-up interrupts on these platforms, but I leave it to the maintainers to fix their mess.

---
 arch/arm/boot/dts/exynos4.dtsi    |   4 ++
 arch/arm/boot/dts/exynos5250.dtsi |   4 ++
 arch/arm/boot/dts/exynos5420.dtsi |   4 ++
 arch/arm/mach-exynos/exynos.c     |  14 ++---
 arch/arm/mach-exynos/suspend.c    | 122 ++++++++++++++++++++++++++++++++++----
 5 files changed, 129 insertions(+), 19 deletions(-)
arch/arm/boot/dts/exynos4.dtsi +4 -0
index b8168f1..0e7d74e 100644
@@ -141,6 +141,9 @@
 	pmu_system_controller: system-controller at 10020000 {
 		compatible = "samsung,exynos4210-pmu", "syscon";
 		reg = <0x10020000 0x4000>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
 	};
 
 	dsi_0: dsi at 11C80000 {
@@ -253,6 +256,7 @@
 	rtc at 10070000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x10070000 0x100>;
+		interrupt-parent = <&pmu_system_controller>;
 		interrupts = <0 44 0>, <0 45 0>;
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
arch/arm/boot/dts/exynos5250.dtsi +4 -0
index 0a229fc..1dc5f6b 100644
@@ -194,6 +194,9 @@
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon at 10050000 {
@@ -230,6 +233,7 @@
 	rtc: rtc at 101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
arch/arm/boot/dts/exynos5420.dtsi +4 -0
index 517e50f..35ecd36 100644
@@ -309,6 +309,7 @@
 	rtc: rtc at 101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
@@ -748,6 +749,9 @@
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon at 10050000 {
arch/arm/mach-exynos/exynos.c +5 -9
index c13d083..e417fdc 100644
@@ -175,16 +175,15 @@ static void __init exynos_init_io(void)
 	exynos_map_io();
 }
 
+/*
+ * Apparently, these SoCs are not able to wake-up from suspend using
+ * the PMU. Too bad. Should they suddenly become capable of such a
+ * feat, the matches below should be moved to suspend.c.
+ */
 static const struct of_device_id exynos_dt_pmu_match[] = {
 	{ .compatible = "samsung,exynos3250-pmu" },
-	{ .compatible = "samsung,exynos4210-pmu" },
-	{ .compatible = "samsung,exynos4212-pmu" },
-	{ .compatible = "samsung,exynos4412-pmu" },
-	{ .compatible = "samsung,exynos4415-pmu" },
-	{ .compatible = "samsung,exynos5250-pmu" },
 	{ .compatible = "samsung,exynos5260-pmu" },
 	{ .compatible = "samsung,exynos5410-pmu" },
-	{ .compatible = "samsung,exynos5420-pmu" },
 	{ /*sentinel*/ },
 };
 
@@ -195,9 +194,6 @@ static void exynos_map_pmu(void)
 	np = of_find_matching_node(NULL, exynos_dt_pmu_match);
 	if (np)
 		pmu_base_addr = of_iomap(np, 0);
-
-	if (!pmu_base_addr)
-		panic("failed to find exynos pmu register\n");
 }
 
 static void __init exynos_init_irq(void)
arch/arm/mach-exynos/suspend.c +112 -10

156 lines not on this page · raw message

Signature · 1 line
2.1.4
#28 lore raw

PATCH v4 15/21 ARM: exynos4/5: convert pmu wakeup to stacked domains

Hi Marc,

Quoted 13 lines · Marc Zyngier

Exynos has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the PMU block is actually the first interrupt controller in the chain for RTC, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs may not even boot.

Quoted 6 lines

Also, I stronly suspect that there is more than two wake-up interrupts on these platforms, but I leave it to the maintainers to fix their mess.

---

I tested this patch series on SMDK5250 board.

With the addition of "#interrupt-cells = <3>;"in PMU device node S2R is working on Exynos5250 based SMDK board.

Quoted 78 lines
  arch/arm/boot/dts/exynos4.dtsi    |   4 ++
  arch/arm/boot/dts/exynos5250.dtsi |   4 ++
  arch/arm/boot/dts/exynos5420.dtsi |   4 ++
  arch/arm/mach-exynos/exynos.c     |  14 ++---
  arch/arm/mach-exynos/suspend.c    | 122 ++++++++++++++++++++++++++++++++++----
  5 files changed, 129 insertions(+), 19 deletions(-)
arch/arm/boot/dts/exynos4.dtsi +4 -0
index b8168f1..0e7d74e 100644
@@ -141,6 +141,9 @@
  	pmu_system_controller: system-controller@10020000 {
  		compatible = "samsung,exynos4210-pmu", "syscon";
  		reg = <0x10020000 0x4000>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
  	};
 
  	dsi_0: dsi@11C80000 {
@@ -253,6 +256,7 @@
  	rtc@10070000 {
  		compatible = "samsung,s3c6410-rtc";
  		reg = <0x10070000 0x100>;
+		interrupt-parent = <&pmu_system_controller>;
  		interrupts = <0 44 0>, <0 45 0>;
  		clocks = <&clock CLK_RTC>;
  		clock-names = "rtc";
arch/arm/boot/dts/exynos5250.dtsi +4 -0
index 0a229fc..1dc5f6b 100644
@@ -194,6 +194,9 @@
  		clock-names = "clkout16";
  		clocks = <&clock CLK_FIN_PLL>;
  		#clock-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
  	};
 
  	sysreg_system_controller: syscon@10050000 {
@@ -230,6 +233,7 @@
  	rtc: rtc@101E0000 {
  		clocks = <&clock CLK_RTC>;
  		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
  		status = "disabled";
  	};
 
arch/arm/boot/dts/exynos5420.dtsi +4 -0
index 517e50f..35ecd36 100644
@@ -309,6 +309,7 @@
  	rtc: rtc@101E0000 {
  		clocks = <&clock CLK_RTC>;
  		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
  		status = "disabled";
  	};
 
@@ -748,6 +749,9 @@
  		clock-names = "clkout16";
  		clocks = <&clock CLK_FIN_PLL>;
  		#clock-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
  	};
 
  	sysreg_system_controller: syscon@10050000 {
arch/arm/mach-exynos/exynos.c +0 -0
index c13d083..e417fdc 100644

arch/arm/mach-exynos/exynos.c static void __init exynos_init_io(void) · line 184

Quoted 10 lines
arch/arm/mach-exynos/exynos.c +5 -0
@@ -175,16 +175,15 @@ static void __init exynos_init_io(void)
  	exynos_map_io();
  }
 
+/*
+ * Apparently, these SoCs are not able to wake-up from suspend using
+ * the PMU. Too bad. Should they suddenly become capable of such a
+ * feat, the matches below should be moved to suspend.c.
+ */
  static const struct of_device_id exynos_dt_pmu_match[] = {
  	{ .compatible = "samsung,exynos3250-pmu" },

As I know Exynos3250, S2R support has been added in kgene/for-next and should work as expected so we may need to do update "exynos_wkup_irq" for exynos3250 and remove it from this list, so that it's S2R should not break. I am adding concern engineer (+cc: Chanwoo Choi) in the loop.

arch/arm/mach-exynos/exynos.c static void __init exynos_init_io(void) · line 189

Quoted 11 lines
arch/arm/mach-exynos/exynos.c +0 -6
-	{ .compatible = "samsung,exynos4210-pmu" },
-	{ .compatible = "samsung,exynos4212-pmu" },
-	{ .compatible = "samsung,exynos4412-pmu" },
-	{ .compatible = "samsung,exynos4415-pmu" },
-	{ .compatible = "samsung,exynos5250-pmu" },
  	{ .compatible = "samsung,exynos5260-pmu" },
  	{ .compatible = "samsung,exynos5410-pmu" },
-	{ .compatible = "samsung,exynos5420-pmu" },
  	{ /*sentinel*/ },
  };
 

Thanks,
Pankaj Dubey

#29 lore raw

PATCH v4 15/21 ARM: exynos4/5: convert pmu wakeup to stacked domains

Hi Pankaj,

Quoted 20 lines · Pankaj Dubey

Hi Marc,

Quoted 17 lines · Marc Zyngier

Exynos has been (ab)using the gic_arch_extn to provide wakeup from suspend, and it makes a lot of sense to convert this code to use stacked domains instead.

This patch does just this, updating the DT files to actually reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not exposing the fact that the PMU block is actually the first interrupt controller in the chain for RTC, kernels with this patch applied wont have any suspend-resume facility when booted with old DTs, and old kernels with updated DTs may not even boot.

Also, I stronly suspect that there is more than two wake-up interrupts on these platforms, but I leave it to the maintainers to fix their mess.

Quoted 7 lines
Quoted 2 lines

---

I tested this patch series on SMDK5250 board.

With the addition of "#interrupt-cells = <3>;"in PMU device node S2R is working on Exynos5250 based SMDK board.

Thanks for letting me know. Can I add your Tested-by tag on this?

Quoted 86 lines
Quoted 86 lines
  arch/arm/boot/dts/exynos4.dtsi    |   4 ++
  arch/arm/boot/dts/exynos5250.dtsi |   4 ++
  arch/arm/boot/dts/exynos5420.dtsi |   4 ++
  arch/arm/mach-exynos/exynos.c     |  14 ++---
  arch/arm/mach-exynos/suspend.c    | 122 
++++++++++++++++++++++++++++++++++----
  5 files changed, 129 insertions(+), 19 deletions(-)
arch/arm/boot/dts/exynos4.dtsi +4 -0
index b8168f1..0e7d74e 100644
@@ -141,6 +141,9 @@
  	pmu_system_controller: system-controller at 10020000 {
  		compatible = "samsung,exynos4210-pmu", "syscon";
  		reg = <0x10020000 0x4000>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
  	};
 
  	dsi_0: dsi at 11C80000 {
@@ -253,6 +256,7 @@
  	rtc at 10070000 {
  		compatible = "samsung,s3c6410-rtc";
  		reg = <0x10070000 0x100>;
+		interrupt-parent = <&pmu_system_controller>;
  		interrupts = <0 44 0>, <0 45 0>;
  		clocks = <&clock CLK_RTC>;
  		clock-names = "rtc";
arch/arm/boot/dts/exynos5250.dtsi +4 -0
index 0a229fc..1dc5f6b 100644
@@ -194,6 +194,9 @@
  		clock-names = "clkout16";
  		clocks = <&clock CLK_FIN_PLL>;
  		#clock-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
  	};
 
  	sysreg_system_controller: syscon at 10050000 {
@@ -230,6 +233,7 @@
  	rtc: rtc at 101E0000 {
  		clocks = <&clock CLK_RTC>;
  		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
  		status = "disabled";
  	};
 
arch/arm/boot/dts/exynos5420.dtsi +4 -0
index 517e50f..35ecd36 100644
@@ -309,6 +309,7 @@
  	rtc: rtc at 101E0000 {
  		clocks = <&clock CLK_RTC>;
  		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
  		status = "disabled";
  	};
 
@@ -748,6 +749,9 @@
  		clock-names = "clkout16";
  		clocks = <&clock CLK_FIN_PLL>;
  		#clock-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
  	};
 
  	sysreg_system_controller: syscon at 10050000 {
arch/arm/mach-exynos/exynos.c +0 -0
index c13d083..e417fdc 100644
@@ -175,16 +175,15 @@ static void __init exynos_init_io(void)
  	exynos_map_io();
  }
 
Quoted 15 lines
Quoted 8 lines
arch/arm/mach-exynos/exynos.c +2 -0
+/*
+ * Apparently, these SoCs are not able to wake-up from suspend 

using
+ * the PMU. Too bad. Should they suddenly become capable of such a
+ * feat, the matches below should be moved to suspend.c.
+ */
static const struct of_device_id exynos_dt_pmu_match[] = {
{ .compatible = "samsung,exynos3250-pmu" },

As I know Exynos3250, S2R support has been added in kgene/for-next and should work as expected so we may need to do update "exynos_wkup_irq" for exynos3250 and remove it from this list, so that
it's S2R should not break. I am adding concern engineer (+cc: Chanwoo Choi) in the loop.

That would have to be an additional patch, unless we decide to delay this series.

Thanks,

         M.
Signature · 1 line
Fast, cheap, reliable. Pick two.
#30 lore raw

PATCH v4 16/21 DT: exynos: update PMU binding

In reply to Marc Zyngier

Document the fact that some Exynos PMUs are capable of acting as an interrupt controller.

---
 Documentation/devicetree/bindings/arm/samsung/pmu.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
Documentation/devicetree/bindings/arm/samsung/pmu.txt +13 -0
index 1e1979b..d698e74 100644
@@ -28,10 +28,23 @@ Properties:
  - clocks : list of phandles and specifiers to all input clocks listed in
 		clock-names property.
 
+Optional properties:
+
+Some PMUs are capable of behaving as an interrupt controller (mostly
+to wake up a suspended PMU). In which case, they can have the
+following properties:
+
+- interrupt-controller: indicate that said PMU is an interrupt controller
+
+- interrupt-parent: a phandle indicating which interrupt controller
+  this PMU signals interrupts to.
+
 Example :
 pmu_system_controller: system-controller at 10040000 {
 	compatible = "samsung,exynos5250-pmu", "syscon";
 	reg = <0x10040000 0x5000>;
+	interrupt-controller;
+	interrupt-parent = <&gic>;
 	#clock-cells = <1>;
 	clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
 			"clkout4", "clkout8", "clkout9";
Signature · 1 line
2.1.4
#31 lore raw

PATCH v4 16/21 DT: exynos: update PMU binding

Hi Marc,

Quoted 14 lines · Marc Zyngier

Document the fact that some Exynos PMUs are capable of acting as an interrupt controller.

---
  Documentation/devicetree/bindings/arm/samsung/pmu.txt | 13 +++++++++++++
  1 file changed, 13 insertions(+)
Documentation/devicetree/bindings/arm/samsung/pmu.txt +0 -0
index 1e1979b..d698e74 100644
@@ -28,10 +28,23 @@ Properties:
   - clocks : list of phandles and specifiers to all input clocks listed in

Documentation/devicetree/bindings/arm/samsung/pmu.txt Properties: · line 38

Quoted 10 lines
Documentation/devicetree/bindings/arm/samsung/pmu.txt +8 -0
  		clock-names property.
 
+Optional properties:
+
+Some PMUs are capable of behaving as an interrupt controller (mostly
+to wake up a suspended PMU). In which case, they can have the
+following properties:
+
+- interrupt-controller: indicate that said PMU is an interrupt controller
+

Need to add #interrupt-cells property here.

Documentation/devicetree/bindings/arm/samsung/pmu.txt Properties: · line 50

Quoted 13 lines
Documentation/devicetree/bindings/arm/samsung/pmu.txt +5 -0
+- interrupt-parent: a phandle indicating which interrupt controller
+  this PMU signals interrupts to.
+
  Example :
  pmu_system_controller: system-controller@10040000 {
  	compatible = "samsung,exynos5250-pmu", "syscon";
  	reg = <0x10040000 0x5000>;
+	interrupt-controller;
+	interrupt-parent = <&gic>;
  	#clock-cells = <1>;
  	clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
  			"clkout4", "clkout8", "clkout9";

Thanks,
Pankaj Dubey

#32 lore raw

PATCH v4 17/21 irqchip: gic: add an entry point to set up irqchip flags

In reply to Marc Zyngier

A common use of gic_arch_extn is to set up additional flags to the GIC irqchip. It looks like a benign enough hack that doesn't really require the users of that feature to be converted to stacked domains.

Add a gic_set_irqchip_flags() function that platform code can call instead of using the dreaded gic_arch_extn.

---
 drivers/irqchip/irq-gic.c       | 5 +++++
 include/linux/irqchip/arm-gic.h | 1 +
 2 files changed, 6 insertions(+)
drivers/irqchip/irq-gic.c +5 -0
index 9c30a76..23fe3be 100644
@@ -877,6 +877,11 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.xlate = gic_irq_domain_xlate,
 };
 
+void gic_set_irqchip_flags(unsigned long flags)
+{
+	gic_chip.flags |= flags;
+}
+
 void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 			   void __iomem *dist_base, void __iomem *cpu_base,
 			   u32 percpu_offset, struct device_node *node)
include/linux/irqchip/arm-gic.h +1 -0
index 3978c5b..36ec4ae 100644
@@ -97,6 +97,7 @@ struct device_node;
 
 extern struct irq_chip gic_arch_extn;
 
+void gic_set_irqchip_flags(unsigned long flags);
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
 		    u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
Signature · 1 line
2.1.4
#33 lore raw

PATCH v4 18/21 ARM: shmobile: remove use of gic_arch_extn.irq_set_wake

In reply to Marc Zyngier

shmobile only uses gic_arch_extn.irq_set_wake to prevent the GIC from returning -ENXIO when receiving a wake-up configuration request.

It is a lot simpler to tell the irq layer that we don't need any configuration by using the IRQCHIP_SKIP_SET_WAKE, thanks to the new gic_set_irqchip_flags function.

---
 arch/arm/mach-shmobile/intc-sh73a0.c   | 7 +------
 arch/arm/mach-shmobile/setup-r8a7779.c | 7 +------
 2 files changed, 2 insertions(+), 12 deletions(-)
arch/arm/mach-shmobile/intc-sh73a0.c +1 -6
index 9e36180..fd63ae6 100644
@@ -252,11 +252,6 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
-{
-	return 0; /* always allow wakeup */
-}
-
 #define PINTER0_PHYS 0xe69000a0
 #define PINTER1_PHYS 0xe69000a4
 #define PINTER0_VIRT IOMEM(0xe69000a0)
@@ -318,8 +313,8 @@ void __init sh73a0_init_irq(void)
 	void __iomem *gic_cpu_base = IOMEM(0xf0000100);
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
 
+	gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
 	gic_init(0, 29, gic_dist_base, gic_cpu_base);
-	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
 	register_intc_controller(&intcs_desc);
 	register_intc_controller(&intc_pint0_desc);
arch/arm/mach-shmobile/setup-r8a7779.c +1 -6
index 6156d17..989de2d 100644
@@ -713,14 +713,9 @@ void __init r8a7779_init_late(void)
 }
 
 #ifdef CONFIG_USE_OF
-static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
-{
-	return 0; /* always allow wakeup */
-}
-
 void __init r8a7779_init_irq_dt(void)
 {
-	gic_arch_extn.irq_set_wake = r8a7779_set_wake;
+	gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
 
 	irqchip_init();
 
Signature · 1 line
2.1.4
#34 lore raw

PATCH v4 19/21 ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags

In reply to Marc Zyngier

Instead of directly touching gic_arch_extn, which is about to be removed, use gic_set_irqchip_flags instead.

---
 arch/arm/mach-ux500/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-ux500/cpu.c +1 -1
index dbb2970..6ced0f6 100644
@@ -52,7 +52,7 @@ void ux500_restart(enum reboot_mode mode, const char *cmd)
 */
 void __init ux500_init_irq(void)
 {
-	gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+	gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND);
 	irqchip_init();
 
 	/*
Signature · 1 line
2.1.4
#35 lore raw

PATCH v4 20/21 ARM: zynq: switch from gic_arch_extn to gic_set_irqchip_flags

In reply to Marc Zyngier

Instead of directly touching gic_arch_extn, which is about to be removed, use gic_set_irqchip_flags instead.

---
 arch/arm/mach-zynq/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-zynq/common.c +1 -1
index 26f92c2..82734d5 100644
@@ -188,7 +188,7 @@ static void __init zynq_map_io(void)
 
 static void __init zynq_irq_init(void)
 {
-	gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+	gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND);
 	irqchip_init();
 }
 
Signature · 1 line
2.1.4
#36 lore raw

PATCH v4 21/21 irqchip: gic: Drop support for gic_arch_extn

In reply to Marc Zyngier

Now that the users of gic_arch_extn have been fixed, drop the "feature" for good. This leads to the removal of some now useless locking.

---
 drivers/irqchip/irq-gic.c       | 54 -----------------------------------------
 include/linux/irqchip/arm-gic.h |  2 --
 2 files changed, 56 deletions(-)
drivers/irqchip/irq-gic.c +0 -54
index 23fe3be..78d4dee 100644
@@ -80,19 +80,6 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 #define NR_GIC_CPU_IF 8
 static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
 
-/*
- * Supported arch specific GIC irq extension.
- * Default make them NULL.
- */
-struct irq_chip gic_arch_extn = {
-	.irq_eoi	= NULL,
-	.irq_mask	= NULL,
-	.irq_unmask	= NULL,
-	.irq_retrigger	= NULL,
-	.irq_set_type	= NULL,
-	.irq_set_wake	= NULL,
-};
-
 #ifndef MAX_GIC_NR
 #define MAX_GIC_NR	1
 #endif
@@ -155,32 +142,18 @@ static void gic_mask_irq(struct irq_data *d)
 {
 	u32 mask = 1 << (gic_irq(d) % 32);
 
-	raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
-	if (gic_arch_extn.irq_mask)
-		gic_arch_extn.irq_mask(d);
-	raw_spin_unlock(&irq_controller_lock);
 }
 
 static void gic_unmask_irq(struct irq_data *d)
 {
 	u32 mask = 1 << (gic_irq(d) % 32);
 
-	raw_spin_lock(&irq_controller_lock);
-	if (gic_arch_extn.irq_unmask)
-		gic_arch_extn.irq_unmask(d);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
-	raw_spin_unlock(&irq_controller_lock);
 }
 
 static void gic_eoi_irq(struct irq_data *d)
 {
-	if (gic_arch_extn.irq_eoi) {
-		raw_spin_lock(&irq_controller_lock);
-		gic_arch_extn.irq_eoi(d);
-		raw_spin_unlock(&irq_controller_lock);
-	}
-
 	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 }
 
@@ -196,23 +169,13 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
 		return -EINVAL;
 
-	raw_spin_lock(&irq_controller_lock);
-
-	if (gic_arch_extn.irq_set_type)
-		gic_arch_extn.irq_set_type(d, type);
-
 	gic_configure_irq(gicirq, type, base, NULL);
 
-	raw_spin_unlock(&irq_controller_lock);
-
 	return 0;
 }
 
 static int gic_retrigger(struct irq_data *d)
 {
-	if (gic_arch_extn.irq_retrigger)
-		return gic_arch_extn.irq_retrigger(d);
-
 	/* the genirq layer expects 0 if we can't retrigger in hardware */
 	return 0;
 }
@@ -244,21 +207,6 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 }
 #endif
 
-#ifdef CONFIG_PM
-static int gic_set_wake(struct irq_data *d, unsigned int on)
-{
-	int ret = -ENXIO;
-
-	if (gic_arch_extn.irq_set_wake)
-		ret = gic_arch_extn.irq_set_wake(d, on);
-
-	return ret;
-}
-
-#else
-#define gic_set_wake	NULL
-#endif
-
 static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 {
 	u32 irqstat, irqnr;
@@ -321,7 +269,6 @@ static struct irq_chip gic_chip = {
 #ifdef CONFIG_SMP
 	.irq_set_affinity	= gic_set_affinity,
 #endif
-	.irq_set_wake		= gic_set_wake,
 };
 
 void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
@@ -985,7 +932,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 		set_handle_irq(gic_handle_irq);
 	}
 
-	gic_chip.flags |= gic_arch_extn.flags;
 	gic_dist_init(gic);
 	gic_cpu_init(gic);
 	gic_pm_init(gic);
include/linux/irqchip/arm-gic.h +0 -2
index 36ec4ae..9de976b 100644
@@ -95,8 +95,6 @@
 
 struct device_node;
 
-extern struct irq_chip gic_arch_extn;
-
 void gic_set_irqchip_flags(unsigned long flags);
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
 		    u32 offset, struct device_node *);
Signature · 1 line
2.1.4