All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-07 17:42 ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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 landed in -next, 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 already broke it for the OMAP WUGEN block, we might as well do
  it again for the TI 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 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.

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

Comments welcome,

	 M.

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
  ARM: omap: convert wakeupgen to stacked domains
  DT: omap4/5: add binding for the wake-up generator
  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    |  39 +++
 .../interrupt-controller/ti,omap4-wugen-mpu        |  32 ++
 arch/arm/boot/dts/am4372.dtsi                      |  11 +-
 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                     |   3 +
 arch/arm/boot/dts/exynos5250.dtsi                  |   3 +
 arch/arm/boot/dts/exynos5420.dtsi                  |   3 +
 arch/arm/boot/dts/imx6qdl.dtsi                     |   6 +-
 arch/arm/boot/dts/imx6sl.dtsi                      |   5 +-
 arch/arm/boot/dts/imx6sx.dtsi                      |   5 +-
 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                       |  24 +-
 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                 |   5 -
 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                          | 208 +------------
 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                     | 202 +++++++------
 drivers/irqchip/irq-gic.c                          | 112 +------
 drivers/irqchip/irq-tegra.c                        | 335 +++++++++++++++++++++
 include/linux/irq.h                                |   1 +
 include/linux/irqchip/arm-gic.h                    |   9 +-
 include/linux/irqchip/irq-crossbar.h               |  11 -
 kernel/irq/chip.c                                  |  16 +
 55 files changed, 1053 insertions(+), 606 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

-- 
2.1.4

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-07 17:42 ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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 landed in -next, 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 already broke it for the OMAP WUGEN block, we might as well do
  it again for the TI 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 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.

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

Comments welcome,

	 M.

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
  ARM: omap: convert wakeupgen to stacked domains
  DT: omap4/5: add binding for the wake-up generator
  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    |  39 +++
 .../interrupt-controller/ti,omap4-wugen-mpu        |  32 ++
 arch/arm/boot/dts/am4372.dtsi                      |  11 +-
 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                     |   3 +
 arch/arm/boot/dts/exynos5250.dtsi                  |   3 +
 arch/arm/boot/dts/exynos5420.dtsi                  |   3 +
 arch/arm/boot/dts/imx6qdl.dtsi                     |   6 +-
 arch/arm/boot/dts/imx6sl.dtsi                      |   5 +-
 arch/arm/boot/dts/imx6sx.dtsi                      |   5 +-
 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                       |  24 +-
 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                 |   5 -
 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                          | 208 +------------
 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                     | 202 +++++++------
 drivers/irqchip/irq-gic.c                          | 112 +------
 drivers/irqchip/irq-tegra.c                        | 335 +++++++++++++++++++++
 include/linux/irq.h                                |   1 +
 include/linux/irqchip/arm-gic.h                    |   9 +-
 include/linux/irqchip/irq-crossbar.h               |  11 -
 kernel/irq/chip.c                                  |  16 +
 55 files changed, 1053 insertions(+), 606 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

-- 
2.1.4

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 01/21] ARM: tegra: irq: nuke leftovers from non-DT support
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-tegra/irq.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index ab95f53..7f87a50 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -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();
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 01/21] ARM: tegra: irq: nuke leftovers from non-DT support
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-tegra/irq.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index ab95f53..7f87a50 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -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();
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/Makefile    |   1 +
 drivers/irqchip/irq-tegra.c | 335 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 336 insertions(+)
 create mode 100644 drivers/irqchip/irq-tegra.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 9516a32..59f34be 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -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
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
new file mode 100644
index 0000000..b4fc2e3
--- /dev/null
+++ b/drivers/irqchip/irq-tegra.c
@@ -0,0 +1,335 @@
+/*
+ * Driver code for Tegra's Legacy Interrupt Controller
+ *
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * Heavily based on the original arch/arm/mach-tegra/irq.c code:
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * Copyright (C) 2010,2013, NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+
+#include "irqchip.h"
+
+#define ICTLR_CPU_IEP_VFIQ	0x08
+#define ICTLR_CPU_IEP_FIR	0x14
+#define ICTLR_CPU_IEP_FIR_SET	0x18
+#define ICTLR_CPU_IEP_FIR_CLR	0x1c
+
+#define ICTLR_CPU_IER		0x20
+#define ICTLR_CPU_IER_SET	0x24
+#define ICTLR_CPU_IER_CLR	0x28
+#define ICTLR_CPU_IEP_CLASS	0x2C
+
+#define ICTLR_COP_IER		0x30
+#define ICTLR_COP_IER_SET	0x34
+#define ICTLR_COP_IER_CLR	0x38
+#define ICTLR_COP_IEP_CLASS	0x3c
+
+#define TEGRA_MAX_NUM_ICTLRS	5
+
+static int num_ictlrs;
+
+struct tegra_ictlr_info {
+	void __iomem *ictlr_reg_base[TEGRA_MAX_NUM_ICTLRS];
+#ifdef CONFIG_PM_SLEEP
+	u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
+	u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
+	u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
+	u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
+
+	u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+#endif
+};
+
+static struct tegra_ictlr_info *tegra_ictlr_info;
+
+static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long reg)
+{
+	void __iomem *base = d->chip_data;
+	u32 mask;
+
+	mask = BIT(d->hwirq % 32);
+	writel_relaxed(mask, base + reg);
+}
+
+static void tegra_mask(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IER_CLR);
+	irq_chip_mask_parent(d);
+}
+
+static void tegra_unmask(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IER_SET);
+	irq_chip_unmask_parent(d);
+}
+
+static void tegra_eoi(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_CLR);
+	irq_chip_eoi_parent(d);
+}
+
+static int tegra_retrigger(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_SET);
+	return irq_chip_retrigger_hierarchy(d);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_set_wake(struct irq_data *d, unsigned int enable)
+{
+	u32 irq = d->hwirq;
+	u32 index, mask;
+
+	index = (irq / 32);
+	mask = BIT(irq % 32);
+	if (enable)
+		tegra_ictlr_info->ictlr_wake_mask[index] |= mask;
+	else
+		tegra_ictlr_info->ictlr_wake_mask[index] &= ~mask;
+
+	/*
+	 * Do *not* call into the parent, as the GIC doesn't have any
+	 * wake-up facility...
+	 */
+	return 0;
+}
+
+static int tegra_ictlr_suspend(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < num_ictlrs; i++) {
+		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
+		/* Save interrupt state */
+		tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+		tegra_ictlr_info->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+		tegra_ictlr_info->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+		tegra_ictlr_info->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+
+		/* Disable COP interrupts */
+		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+
+		/* Disable CPU interrupts */
+		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+
+		/* Enable the wakeup sources of ictlr */
+		writel_relaxed(tegra_ictlr_info->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+	}
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static void tegra_ictlr_resume(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < num_ictlrs; i++) {
+		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
+		writel_relaxed(tegra_ictlr_info->cpu_iep[i],
+			       ictlr + ICTLR_CPU_IEP_CLASS);
+		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel_relaxed(tegra_ictlr_info->cpu_ier[i],
+			       ictlr + ICTLR_CPU_IER_SET);
+		writel_relaxed(tegra_ictlr_info->cop_iep[i],
+			       ictlr + ICTLR_COP_IEP_CLASS);
+		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel_relaxed(tegra_ictlr_info->cop_ier[i],
+			       ictlr + ICTLR_COP_IER_SET);
+	}
+	local_irq_restore(flags);
+}
+
+static struct syscore_ops tegra_ictlr_syscore_ops = {
+	.suspend	= tegra_ictlr_suspend,
+	.resume		= tegra_ictlr_resume,
+};
+
+static int tegra_ictlr_syscore_init(void)
+{
+	register_syscore_ops(&tegra_ictlr_syscore_ops);
+
+	return 0;
+}
+#else
+#define tegra_set_wake	NULL
+static inline void tegra_ictlr_syscore_init(void) {}
+#endif
+
+static struct irq_chip tegra_ictlr_chip = {
+	.name		= "ICTLR",
+	.irq_eoi	= tegra_eoi,
+	.irq_mask	= tegra_mask,
+	.irq_unmask	= tegra_unmask,
+	.irq_retrigger	= tegra_retrigger,
+	.irq_set_wake	= tegra_set_wake,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static int tegra_ictlr_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 tegra_ictlr_domain_alloc(struct irq_domain *domain,
+				    unsigned int virq,
+				    unsigned int nr_irqs, void *data)
+{
+	struct of_phandle_args *args = data;
+	struct of_phandle_args parent_args;
+	struct tegra_ictlr_info *info = domain->host_data;
+	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 >= (num_ictlrs * 32))
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++) {
+		int ictlr = (hwirq + i) / 32;
+
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &tegra_ictlr_chip,
+					      &info->ictlr_reg_base[ictlr]);
+	}
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+
+static void tegra_ictlr_domain_free(struct irq_domain *domain,
+				    unsigned int virq,
+				    unsigned int nr_irqs)
+{
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+		irq_domain_reset_irq_data(d);
+	}
+}
+
+static struct irq_domain_ops tegra_ictlr_domain_ops = {
+	.xlate	= tegra_ictlr_domain_xlate,
+	.alloc	= tegra_ictlr_domain_alloc,
+	.free	= tegra_ictlr_domain_free,
+};
+
+static int __init tegra_ictlr_init(struct device_node *node,
+				   struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+	int err;
+	int i;
+
+	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;
+	}
+
+	tegra_ictlr_info = kzalloc(sizeof(*tegra_ictlr_info), GFP_KERNEL);
+	if (!tegra_ictlr_info)
+		return -ENOMEM;
+
+	for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
+		void __iomem *base;
+
+		base = of_iomap(node, i);
+		if (!base)
+			break;
+
+		tegra_ictlr_info->ictlr_reg_base[i] = base;
+
+		/* Disable all interrupts */
+		writel_relaxed(~0, base + ICTLR_CPU_IER_CLR);
+		/* All interrupts target IRQ */
+		writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
+
+		num_ictlrs++;
+	}
+
+	if (!num_ictlrs) {
+		pr_err("%s: no valid regions, giving up\n", node->full_name);
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
+					  node, &tegra_ictlr_domain_ops,
+					  tegra_ictlr_info);
+	if (!domain) {
+		pr_err("%s: failed to allocated domain\n", node->full_name);
+		err = -ENOMEM;
+		goto out_unmap;
+	}
+
+	tegra_ictlr_syscore_init();
+
+	pr_info("%s: %d interrupts forwarded to %s\n",
+		node->full_name, num_ictlrs * 32, parent->full_name);
+
+	return 0;
+
+out_unmap:
+	for (i = 0; i < num_ictlrs; i++)
+		iounmap(tegra_ictlr_info->ictlr_reg_base[i]);
+out_free:
+	kfree(tegra_ictlr_info);
+	return err;
+}
+
+IRQCHIP_DECLARE(tegra_ictlr, "nvidia,tegra-ictlr", tegra_ictlr_init);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/Makefile    |   1 +
 drivers/irqchip/irq-tegra.c | 335 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 336 insertions(+)
 create mode 100644 drivers/irqchip/irq-tegra.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 9516a32..59f34be 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -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
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
new file mode 100644
index 0000000..b4fc2e3
--- /dev/null
+++ b/drivers/irqchip/irq-tegra.c
@@ -0,0 +1,335 @@
+/*
+ * Driver code for Tegra's Legacy Interrupt Controller
+ *
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * Heavily based on the original arch/arm/mach-tegra/irq.c code:
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * Copyright (C) 2010,2013, NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+
+#include "irqchip.h"
+
+#define ICTLR_CPU_IEP_VFIQ	0x08
+#define ICTLR_CPU_IEP_FIR	0x14
+#define ICTLR_CPU_IEP_FIR_SET	0x18
+#define ICTLR_CPU_IEP_FIR_CLR	0x1c
+
+#define ICTLR_CPU_IER		0x20
+#define ICTLR_CPU_IER_SET	0x24
+#define ICTLR_CPU_IER_CLR	0x28
+#define ICTLR_CPU_IEP_CLASS	0x2C
+
+#define ICTLR_COP_IER		0x30
+#define ICTLR_COP_IER_SET	0x34
+#define ICTLR_COP_IER_CLR	0x38
+#define ICTLR_COP_IEP_CLASS	0x3c
+
+#define TEGRA_MAX_NUM_ICTLRS	5
+
+static int num_ictlrs;
+
+struct tegra_ictlr_info {
+	void __iomem *ictlr_reg_base[TEGRA_MAX_NUM_ICTLRS];
+#ifdef CONFIG_PM_SLEEP
+	u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
+	u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
+	u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
+	u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
+
+	u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+#endif
+};
+
+static struct tegra_ictlr_info *tegra_ictlr_info;
+
+static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long reg)
+{
+	void __iomem *base = d->chip_data;
+	u32 mask;
+
+	mask = BIT(d->hwirq % 32);
+	writel_relaxed(mask, base + reg);
+}
+
+static void tegra_mask(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IER_CLR);
+	irq_chip_mask_parent(d);
+}
+
+static void tegra_unmask(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IER_SET);
+	irq_chip_unmask_parent(d);
+}
+
+static void tegra_eoi(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_CLR);
+	irq_chip_eoi_parent(d);
+}
+
+static int tegra_retrigger(struct irq_data *d)
+{
+	tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_SET);
+	return irq_chip_retrigger_hierarchy(d);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_set_wake(struct irq_data *d, unsigned int enable)
+{
+	u32 irq = d->hwirq;
+	u32 index, mask;
+
+	index = (irq / 32);
+	mask = BIT(irq % 32);
+	if (enable)
+		tegra_ictlr_info->ictlr_wake_mask[index] |= mask;
+	else
+		tegra_ictlr_info->ictlr_wake_mask[index] &= ~mask;
+
+	/*
+	 * Do *not* call into the parent, as the GIC doesn't have any
+	 * wake-up facility...
+	 */
+	return 0;
+}
+
+static int tegra_ictlr_suspend(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < num_ictlrs; i++) {
+		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
+		/* Save interrupt state */
+		tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+		tegra_ictlr_info->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+		tegra_ictlr_info->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+		tegra_ictlr_info->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+
+		/* Disable COP interrupts */
+		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+
+		/* Disable CPU interrupts */
+		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+
+		/* Enable the wakeup sources of ictlr */
+		writel_relaxed(tegra_ictlr_info->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+	}
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static void tegra_ictlr_resume(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < num_ictlrs; i++) {
+		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
+		writel_relaxed(tegra_ictlr_info->cpu_iep[i],
+			       ictlr + ICTLR_CPU_IEP_CLASS);
+		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel_relaxed(tegra_ictlr_info->cpu_ier[i],
+			       ictlr + ICTLR_CPU_IER_SET);
+		writel_relaxed(tegra_ictlr_info->cop_iep[i],
+			       ictlr + ICTLR_COP_IEP_CLASS);
+		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel_relaxed(tegra_ictlr_info->cop_ier[i],
+			       ictlr + ICTLR_COP_IER_SET);
+	}
+	local_irq_restore(flags);
+}
+
+static struct syscore_ops tegra_ictlr_syscore_ops = {
+	.suspend	= tegra_ictlr_suspend,
+	.resume		= tegra_ictlr_resume,
+};
+
+static int tegra_ictlr_syscore_init(void)
+{
+	register_syscore_ops(&tegra_ictlr_syscore_ops);
+
+	return 0;
+}
+#else
+#define tegra_set_wake	NULL
+static inline void tegra_ictlr_syscore_init(void) {}
+#endif
+
+static struct irq_chip tegra_ictlr_chip = {
+	.name		= "ICTLR",
+	.irq_eoi	= tegra_eoi,
+	.irq_mask	= tegra_mask,
+	.irq_unmask	= tegra_unmask,
+	.irq_retrigger	= tegra_retrigger,
+	.irq_set_wake	= tegra_set_wake,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static int tegra_ictlr_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 tegra_ictlr_domain_alloc(struct irq_domain *domain,
+				    unsigned int virq,
+				    unsigned int nr_irqs, void *data)
+{
+	struct of_phandle_args *args = data;
+	struct of_phandle_args parent_args;
+	struct tegra_ictlr_info *info = domain->host_data;
+	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 >= (num_ictlrs * 32))
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++) {
+		int ictlr = (hwirq + i) / 32;
+
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &tegra_ictlr_chip,
+					      &info->ictlr_reg_base[ictlr]);
+	}
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+
+static void tegra_ictlr_domain_free(struct irq_domain *domain,
+				    unsigned int virq,
+				    unsigned int nr_irqs)
+{
+	int i;
+
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+		irq_domain_reset_irq_data(d);
+	}
+}
+
+static struct irq_domain_ops tegra_ictlr_domain_ops = {
+	.xlate	= tegra_ictlr_domain_xlate,
+	.alloc	= tegra_ictlr_domain_alloc,
+	.free	= tegra_ictlr_domain_free,
+};
+
+static int __init tegra_ictlr_init(struct device_node *node,
+				   struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+	int err;
+	int i;
+
+	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;
+	}
+
+	tegra_ictlr_info = kzalloc(sizeof(*tegra_ictlr_info), GFP_KERNEL);
+	if (!tegra_ictlr_info)
+		return -ENOMEM;
+
+	for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
+		void __iomem *base;
+
+		base = of_iomap(node, i);
+		if (!base)
+			break;
+
+		tegra_ictlr_info->ictlr_reg_base[i] = base;
+
+		/* Disable all interrupts */
+		writel_relaxed(~0, base + ICTLR_CPU_IER_CLR);
+		/* All interrupts target IRQ */
+		writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
+
+		num_ictlrs++;
+	}
+
+	if (!num_ictlrs) {
+		pr_err("%s: no valid regions, giving up\n", node->full_name);
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
+					  node, &tegra_ictlr_domain_ops,
+					  tegra_ictlr_info);
+	if (!domain) {
+		pr_err("%s: failed to allocated domain\n", node->full_name);
+		err = -ENOMEM;
+		goto out_unmap;
+	}
+
+	tegra_ictlr_syscore_init();
+
+	pr_info("%s: %d interrupts forwarded to %s\n",
+		node->full_name, num_ictlrs * 32, parent->full_name);
+
+	return 0;
+
+out_unmap:
+	for (i = 0; i < num_ictlrs; i++)
+		iounmap(tegra_ictlr_info->ictlr_reg_base[i]);
+out_free:
+	kfree(tegra_ictlr_info);
+	return err;
+}
+
+IRQCHIP_DECLARE(tegra_ictlr, "nvidia,tegra-ictlr", tegra_ictlr_init);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 03/21] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-tegra/irq.c   | 11 +++++++++++
 arch/arm/mach-tegra/tegra.c |  1 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 7f87a50..b37141d 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -255,11 +255,21 @@ 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,tegra-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 +293,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();
 }
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index ef016af..c33fba7 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -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)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 03/21] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-tegra/irq.c   | 11 +++++++++++
 arch/arm/mach-tegra/tegra.c |  1 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 7f87a50..b37141d 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -255,11 +255,21 @@ 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,tegra-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 +293,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();
 }
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index ef016af..c33fba7 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -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)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy interrupt controller
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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(-)

diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 4296b53..f70bed0 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -8,7 +8,7 @@
 
 / {
 	compatible = "nvidia,tegra114";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&ictlr>;
 
 	host1x@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>;
+	};
+
+	ictlr: interrupt-controller@60004000 {
+		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x60004000 64>,
+		      <0x60004100 64>,
+		      <0x60004200 64>,
+		      <0x60004300 64>,
+		      <0x60004400 64>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
 	};
 
 	timer@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>;
 	};
 };
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 4be06c6..6ed6ca0 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -10,7 +10,7 @@
 
 / {
 	compatible = "nvidia,tegra124";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&ictlr>;
 	#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@0,57000000 {
@@ -190,6 +191,18 @@
 		status = "disabled";
 	};
 
+	ictlr: interrupt-controller@60004000 {
+		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x0 0x60004000 0x0 0x40>,
+		      <0x0 0x60004100 0x0 0x40>,
+		      <0x0 0x60004200 0x0 0x40>,
+		      <0x0 0x60004300 0x0 0x40>,
+		      <0x0 0x60004400 0x0 0x40>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&gic>;
+	};
+
 	timer@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>;
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 8acf5d8..ab2f004 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -7,7 +7,7 @@
 
 / {
 	compatible = "nvidia,tegra20";
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&ictlr>;
 
 	host1x@50000000 {
 		compatible = "nvidia,tegra20-host1x", "simple-bus";
@@ -142,6 +142,7 @@
 
 	timer@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@50043000 {
@@ -165,6 +167,17 @@
 		cache-level = <2>;
 	};
 
+	ictlr: interrupt-controller@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>;
+	};
+
 	timer@60005000 {
 		compatible = "nvidia,tegra20-timer";
 		reg = <0x60005000 0x60>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 99475f6..c621e30 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -8,7 +8,7 @@
 
 / {
 	compatible = "nvidia,tegra30";
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&ictlr>;
 
 	pcie-controller@00003000 {
 		compatible = "nvidia,tegra30-pcie";
@@ -228,6 +228,7 @@
 	timer@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@50043000 {
@@ -250,6 +252,18 @@
 		cache-level = <2>;
 	};
 
+	ictlr: interrupt-controller@60004000 {
+		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x60004000 64>,
+		      <0x60004100 64>,
+		      <0x60004200 64>,
+		      <0x60004300 64>,
+		      <0x60004400 64>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+	};
+
 	timer@60005000 {
 		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
 		reg = <0x60005000 0x400>;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy interrupt controller
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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(-)

diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 4296b53..f70bed0 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -8,7 +8,7 @@
 
 / {
 	compatible = "nvidia,tegra114";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&ictlr>;
 
 	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>;
+	};
+
+	ictlr: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x60004000 64>,
+		      <0x60004100 64>,
+		      <0x60004200 64>,
+		      <0x60004300 64>,
+		      <0x60004400 64>;
+		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>;
 	};
 };
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 4be06c6..6ed6ca0 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -10,7 +10,7 @@
 
 / {
 	compatible = "nvidia,tegra124";
-	interrupt-parent = <&gic>;
+	interrupt-parent = <&ictlr>;
 	#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";
 	};
 
+	ictlr: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x0 0x60004000 0x0 0x40>,
+		      <0x0 0x60004100 0x0 0x40>,
+		      <0x0 0x60004200 0x0 0x40>,
+		      <0x0 0x60004300 0x0 0x40>,
+		      <0x0 0x60004400 0x0 0x40>;
+		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>;
 	};
 };
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 8acf5d8..ab2f004 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -7,7 +7,7 @@
 
 / {
 	compatible = "nvidia,tegra20";
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&ictlr>;
 
 	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>;
 	};
 
+	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>;
+	};
+
 	timer at 60005000 {
 		compatible = "nvidia,tegra20-timer";
 		reg = <0x60005000 0x60>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 99475f6..c621e30 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -8,7 +8,7 @@
 
 / {
 	compatible = "nvidia,tegra30";
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&ictlr>;
 
 	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>;
 	};
 
+	ictlr: interrupt-controller at 60004000 {
+		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x60004000 64>,
+		      <0x60004100 64>,
+		      <0x60004200 64>,
+		      <0x60004300 64>,
+		      <0x60004400 64>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+	};
+
 	timer at 60005000 {
 		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
 		reg = <0x60005000 0x400>;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 05/21] DT: tegra: add binding for the legacy interrupt controller
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 .../interrupt-controller/nvidia,tegra-ictlr.txt    | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
new file mode 100644
index 0000000..44fd873
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
@@ -0,0 +1,39 @@
+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
+refered to as "ictlr", hence the name of the binding.
+
+The HW block exposes a number of frames, each implementing a set of 32
+interrupts.
+
+Reguired properties:
+
+- compatible : should contain at least "nvidia,tegra-ictlr".
+- reg : Specifies base physical address and size of the registers.
+  Each frame must be described separately.
+- 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 explicitely forbiden.
+
+Example:
+
+	ictlr: interrupt-controller@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>;
+	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 05/21] DT: tegra: add binding for the legacy interrupt controller
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 .../interrupt-controller/nvidia,tegra-ictlr.txt    | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
new file mode 100644
index 0000000..44fd873
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
@@ -0,0 +1,39 @@
+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
+refered to as "ictlr", hence the name of the binding.
+
+The HW block exposes a number of frames, each implementing a set of 32
+interrupts.
+
+Reguired properties:
+
+- compatible : should contain at least "nvidia,tegra-ictlr".
+- reg : Specifies base physical address and size of the registers.
+  Each frame must be described separately.
+- 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 explicitely forbiden.
+
+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>;
+	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 06/21] ARM: tegra: remove old LIC support
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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(-)

diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index ee79808..81dc950 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -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
 
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index b37141d..a1befd3 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -30,43 +30,9 @@
 #include "board.h"
 #include "iomap.h"
 
-#define ICTLR_CPU_IEP_VFIQ	0x08
-#define ICTLR_CPU_IEP_FIR	0x14
-#define ICTLR_CPU_IEP_FIR_SET	0x18
-#define ICTLR_CPU_IEP_FIR_CLR	0x1c
-
-#define ICTLR_CPU_IER		0x20
-#define ICTLR_CPU_IER_SET	0x24
-#define ICTLR_CPU_IER_CLR	0x28
-#define ICTLR_CPU_IEP_CLASS	0x2C
-
-#define ICTLR_COP_IER		0x30
-#define ICTLR_COP_IER_SET	0x34
-#define ICTLR_COP_IER_CLR	0x38
-#define ICTLR_COP_IEP_CLASS	0x3c
-
-#define FIRST_LEGACY_IRQ 32
-#define TEGRA_MAX_NUM_ICTLRS	5
-
 #define SGI_MASK 0xFFFF
 
-static int num_ictlrs;
-
-static void __iomem *ictlr_reg_base[] = {
-	IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
-};
-
 #ifdef CONFIG_PM_SLEEP
-static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
-
-static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
 static void __iomem *tegra_gic_cpu_base;
 #endif
 
@@ -83,140 +49,7 @@ bool tegra_pending_sgi(void)
 	return false;
 }
 
-static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
-{
-	void __iomem *base;
-	u32 mask;
-
-	BUG_ON(irq < FIRST_LEGACY_IRQ ||
-		irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32);
-
-	base = ictlr_reg_base[(irq - FIRST_LEGACY_IRQ) / 32];
-	mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-
-	__raw_writel(mask, base + reg);
-}
-
-static void tegra_mask(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
-}
-
-static void tegra_unmask(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
-}
-
-static void tegra_ack(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static void tegra_eoi(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static int tegra_retrigger(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return 0;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
-
-	return 1;
-}
-
 #ifdef CONFIG_PM_SLEEP
-static int tegra_set_wake(struct irq_data *d, unsigned int enable)
-{
-	u32 irq = d->hwirq;
-	u32 index, mask;
-
-	if (irq < FIRST_LEGACY_IRQ ||
-		irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
-		return -EINVAL;
-
-	index = ((irq - FIRST_LEGACY_IRQ) / 32);
-	mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-	if (enable)
-		ictlr_wake_mask[index] |= mask;
-	else
-		ictlr_wake_mask[index] &= ~mask;
-
-	return 0;
-}
-
-static int tegra_legacy_irq_suspend(void)
-{
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	for (i = 0; i < num_ictlrs; i++) {
-		void __iomem *ictlr = ictlr_reg_base[i];
-		/* Save interrupt state */
-		cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
-		cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
-		cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
-		cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
-
-		/* Disable COP interrupts */
-		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-
-		/* Disable CPU interrupts */
-		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-
-		/* Enable the wakeup sources of ictlr */
-		writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
-	}
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static void tegra_legacy_irq_resume(void)
-{
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	for (i = 0; i < num_ictlrs; i++) {
-		void __iomem *ictlr = ictlr_reg_base[i];
-		writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
-		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-		writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
-		writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
-		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-		writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
-	}
-	local_irq_restore(flags);
-}
-
-static struct syscore_ops tegra_legacy_irq_syscore_ops = {
-	.suspend = tegra_legacy_irq_suspend,
-	.resume = tegra_legacy_irq_resume,
-};
-
-int tegra_legacy_irq_syscore_init(void)
-{
-	register_syscore_ops(&tegra_legacy_irq_syscore_ops);
-
-	return 0;
-}
-
 static int tegra_gic_notifier(struct notifier_block *self,
 			      unsigned long cmd, void *v)
 {
@@ -251,7 +84,6 @@ static void tegra114_gic_cpu_pm_registration(void)
 	cpu_pm_register_notifier(&tegra_gic_notifier_block);
 }
 #else
-#define tegra_set_wake NULL
 static void tegra114_gic_cpu_pm_registration(void) { }
 #endif
 
@@ -262,37 +94,8 @@ static const struct of_device_id tegra_ictlr_match[] __initconst = {
 
 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;
-
-	if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
-		WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.",
-			num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
-		num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
-	}
-
-	for (i = 0; i < num_ictlrs; i++) {
-		void __iomem *ictlr = ictlr_reg_base[i];
-		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
-		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
-	}
-
-	gic_arch_extn.irq_ack = tegra_ack;
-	gic_arch_extn.irq_eoi = tegra_eoi;
-	gic_arch_extn.irq_mask = tegra_mask;
-	gic_arch_extn.irq_unmask = tegra_unmask;
-	gic_arch_extn.irq_retrigger = tegra_retrigger;
-	gic_arch_extn.irq_set_wake = tegra_set_wake;
-	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
+	if (!of_find_matching_node(NULL, tegra_ictlr_match))
+		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
 
-skip_extn_setup:
 	tegra114_gic_cpu_pm_registration();
 }
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
index bc05ce5..5142649 100644
--- a/arch/arm/mach-tegra/irq.h
+++ b/arch/arm/mach-tegra/irq.h
@@ -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
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 06/21] ARM: tegra: remove old LIC support
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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(-)

diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index ee79808..81dc950 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -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
 
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index b37141d..a1befd3 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -30,43 +30,9 @@
 #include "board.h"
 #include "iomap.h"
 
-#define ICTLR_CPU_IEP_VFIQ	0x08
-#define ICTLR_CPU_IEP_FIR	0x14
-#define ICTLR_CPU_IEP_FIR_SET	0x18
-#define ICTLR_CPU_IEP_FIR_CLR	0x1c
-
-#define ICTLR_CPU_IER		0x20
-#define ICTLR_CPU_IER_SET	0x24
-#define ICTLR_CPU_IER_CLR	0x28
-#define ICTLR_CPU_IEP_CLASS	0x2C
-
-#define ICTLR_COP_IER		0x30
-#define ICTLR_COP_IER_SET	0x34
-#define ICTLR_COP_IER_CLR	0x38
-#define ICTLR_COP_IEP_CLASS	0x3c
-
-#define FIRST_LEGACY_IRQ 32
-#define TEGRA_MAX_NUM_ICTLRS	5
-
 #define SGI_MASK 0xFFFF
 
-static int num_ictlrs;
-
-static void __iomem *ictlr_reg_base[] = {
-	IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
-	IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
-};
-
 #ifdef CONFIG_PM_SLEEP
-static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
-
-static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
 static void __iomem *tegra_gic_cpu_base;
 #endif
 
@@ -83,140 +49,7 @@ bool tegra_pending_sgi(void)
 	return false;
 }
 
-static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
-{
-	void __iomem *base;
-	u32 mask;
-
-	BUG_ON(irq < FIRST_LEGACY_IRQ ||
-		irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32);
-
-	base = ictlr_reg_base[(irq - FIRST_LEGACY_IRQ) / 32];
-	mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-
-	__raw_writel(mask, base + reg);
-}
-
-static void tegra_mask(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
-}
-
-static void tegra_unmask(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
-}
-
-static void tegra_ack(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static void tegra_eoi(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static int tegra_retrigger(struct irq_data *d)
-{
-	if (d->hwirq < FIRST_LEGACY_IRQ)
-		return 0;
-
-	tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
-
-	return 1;
-}
-
 #ifdef CONFIG_PM_SLEEP
-static int tegra_set_wake(struct irq_data *d, unsigned int enable)
-{
-	u32 irq = d->hwirq;
-	u32 index, mask;
-
-	if (irq < FIRST_LEGACY_IRQ ||
-		irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
-		return -EINVAL;
-
-	index = ((irq - FIRST_LEGACY_IRQ) / 32);
-	mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-	if (enable)
-		ictlr_wake_mask[index] |= mask;
-	else
-		ictlr_wake_mask[index] &= ~mask;
-
-	return 0;
-}
-
-static int tegra_legacy_irq_suspend(void)
-{
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	for (i = 0; i < num_ictlrs; i++) {
-		void __iomem *ictlr = ictlr_reg_base[i];
-		/* Save interrupt state */
-		cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
-		cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
-		cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
-		cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
-
-		/* Disable COP interrupts */
-		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-
-		/* Disable CPU interrupts */
-		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-
-		/* Enable the wakeup sources of ictlr */
-		writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
-	}
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static void tegra_legacy_irq_resume(void)
-{
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	for (i = 0; i < num_ictlrs; i++) {
-		void __iomem *ictlr = ictlr_reg_base[i];
-		writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
-		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-		writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
-		writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
-		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-		writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
-	}
-	local_irq_restore(flags);
-}
-
-static struct syscore_ops tegra_legacy_irq_syscore_ops = {
-	.suspend = tegra_legacy_irq_suspend,
-	.resume = tegra_legacy_irq_resume,
-};
-
-int tegra_legacy_irq_syscore_init(void)
-{
-	register_syscore_ops(&tegra_legacy_irq_syscore_ops);
-
-	return 0;
-}
-
 static int tegra_gic_notifier(struct notifier_block *self,
 			      unsigned long cmd, void *v)
 {
@@ -251,7 +84,6 @@ static void tegra114_gic_cpu_pm_registration(void)
 	cpu_pm_register_notifier(&tegra_gic_notifier_block);
 }
 #else
-#define tegra_set_wake NULL
 static void tegra114_gic_cpu_pm_registration(void) { }
 #endif
 
@@ -262,37 +94,8 @@ static const struct of_device_id tegra_ictlr_match[] __initconst = {
 
 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;
-
-	if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
-		WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.",
-			num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
-		num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
-	}
-
-	for (i = 0; i < num_ictlrs; i++) {
-		void __iomem *ictlr = ictlr_reg_base[i];
-		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
-		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
-	}
-
-	gic_arch_extn.irq_ack = tegra_ack;
-	gic_arch_extn.irq_eoi = tegra_eoi;
-	gic_arch_extn.irq_mask = tegra_mask;
-	gic_arch_extn.irq_unmask = tegra_unmask;
-	gic_arch_extn.irq_retrigger = tegra_retrigger;
-	gic_arch_extn.irq_set_wake = tegra_set_wake;
-	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
+	if (!of_find_matching_node(NULL, tegra_ictlr_match))
+		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
 
-skip_extn_setup:
 	tegra114_gic_cpu_pm_registration();
 }
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
index bc05ce5..5142649 100644
--- a/arch/arm/mach-tegra/irq.h
+++ b/arch/arm/mach-tegra/irq.h
@@ -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
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irq.h |  1 +
 kernel/irq/chip.c   | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index d09ec7a..3057c48 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -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: */
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 6f1c7a5..eb9a4ea 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -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
 
 /**
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irq.h |  1 +
 kernel/irq/chip.c   | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index d09ec7a..3057c48 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -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: */
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 6f1c7a5..eb9a4ea 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -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
 
 /**
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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       | 202 ++++++++++++++++++++---------------
 include/linux/irqchip/irq-crossbar.h |  11 --
 8 files changed, 141 insertions(+), 122 deletions(-)
 delete mode 100644 include/linux/irqchip/irq-crossbar.h

diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 10b725c..048cfeb 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -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>;
 };
 
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 22771bc..59ec0e6 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -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@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@4ae06000 {
 			compatible = "ti,dra7-prm";
@@ -344,7 +344,7 @@
 		uart1: serial@4806a000 {
 			compatible = "ti,omap4-uart";
 			reg = <0x4806a000 0x100>;
-			interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 			status = "disabled";
@@ -355,7 +355,7 @@
 		uart2: serial@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@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@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@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@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@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@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@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@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@4a020000 {
+		crossbar_mpu: crossbar@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>;
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts
index 89085d0..298df33 100644
--- a/arch/arm/boot/dts/dra72-evm.dts
+++ b/arch/arm/boot/dts/dra72-evm.dts
@@ -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>;
 
diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi
index e5a3d23..e782bf1 100644
--- a/arch/arm/boot/dts/dra72x.dtsi
+++ b/arch/arm/boot/dts/dra72x.dtsi
@@ -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>;
 	};
 };
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 10173fa..0fc758d 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -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 {
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index b7cb44a..490d95e 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -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>
@@ -274,8 +273,5 @@ void __init omap_gic_of_init(void)
 
 skip_errata_init:
 	omap_wakeupgen_init();
-#ifdef CONFIG_IRQ_CROSSBAR
-	irqcrossbar_init();
-#endif
 	irqchip_init();
 }
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index bbbaf5d..f7daff0 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -11,11 +11,12 @@
  */
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/irqchip/irq-crossbar.h>
+
+#include "irqchip.h"
 
 #define IRQ_FREE	-1
 #define IRQ_RESERVED	-2
@@ -33,6 +34,7 @@
  * @write: register write function pointer
  */
 struct crossbar_device {
+	raw_spinlock_t lock;
 	uint int_max;
 	uint safe_map;
 	uint max_crossbar_sources;
@@ -44,72 +46,97 @@ struct crossbar_device {
 
 static struct crossbar_device *cb;
 
-static inline void crossbar_writel(int irq_no, int cb_no)
+static void crossbar_writel(int irq_no, int cb_no)
 {
 	writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline void crossbar_writew(int irq_no, int cb_no)
+static void crossbar_writew(int irq_no, int cb_no)
 {
 	writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline void crossbar_writeb(int irq_no, int cb_no)
+static void crossbar_writeb(int irq_no, int cb_no)
 {
 	writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline int get_prev_map_irq(int cb_no)
-{
-	int i;
-
-	for (i = cb->int_max - 1; i >= 0; i--)
-		if (cb->irq_map[i] == cb_no)
-			return i;
-
-	return -ENODEV;
-}
+static struct irq_chip crossbar_chip = {
+	.name		= "CBAR",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= irq_chip_mask_parent,
+	.irq_unmask	= irq_chip_unmask_parent,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= irq_chip_set_wake_parent,
+};
 
-static inline int allocate_free_irq(int cb_no)
+static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
+			    irq_hw_number_t hwirq)
 {
+	struct of_phandle_args args;
 	int i;
+	int err;
 
+	raw_spin_lock(&cb->lock);
 	for (i = cb->int_max - 1; i >= 0; i--) {
 		if (cb->irq_map[i] == IRQ_FREE) {
-			cb->irq_map[i] = cb_no;
-			return i;
+			cb->irq_map[i] = hwirq;
+			break;
 		}
 	}
+	raw_spin_unlock(&cb->lock);
 
-	return -ENODEV;
-}
+	if (i < 0)
+		return -ENODEV;
 
-static inline bool needs_crossbar_write(irq_hw_number_t hw)
-{
-	int cb_no;
+	args.np = domain->parent->of_node;
+	args.args_count = 3;
+	args.args[0] = 0;	/* SPI */
+	args.args[1] = i;
+	args.args[2] = IRQ_TYPE_LEVEL_HIGH;
 
-	if (hw > GIC_IRQ_START) {
-		cb_no = cb->irq_map[hw - GIC_IRQ_START];
-		if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
-			return true;
-	}
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	if (err)
+		cb->irq_map[i] = IRQ_FREE;
+	else
+		cb->write(i, hwirq);
 
-	return false;
+	return err;
 }
 
-static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
-			       irq_hw_number_t hw)
+static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
+				 unsigned int nr_irqs, void *data)
 {
-	if (needs_crossbar_write(hw))
-		cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+	struct of_phandle_args *args = data;
+	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 + nr_irqs) > cb->max_crossbar_sources)
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++) {
+		int err = allocate_gic_irq(d, virq + i, hwirq + i);
+		if (err)
+			return err;
+
+		irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i,
+					      &crossbar_chip, NULL);
+	}
 
 	return 0;
 }
 
 /**
- * crossbar_domain_unmap - unmap a crossbar<->irq connection
+ * crossbar_domain_free - unmap/free a crossbar<->irq connection
  * @d: domain of irq to unmap
- * @irq: virq number
+ * @virq: virq number
+ * @nr_irqs: number of irqs to free
  *
  * We do not maintain a use count of total number of map/unmap
  * calls for a particular irq to find out if a irq can be really
@@ -117,14 +144,19 @@ static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
  * after which irq is anyways unusable. So an explicit map has to be called
  * after that.
  */
-static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
+static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
+				 unsigned int nr_irqs)
 {
-	irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
+	int i;
 
-	if (needs_crossbar_write(hw)) {
-		cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
-		cb->write(hw - GIC_IRQ_START, cb->safe_map);
+	raw_spin_lock(&cb->lock);
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+		irq_domain_reset_irq_data(d);
+		cb->irq_map[d->hwirq] = IRQ_FREE;
+		cb->write(d->hwirq, cb->safe_map);
 	}
+	raw_spin_unlock(&cb->lock);
 }
 
 static int crossbar_domain_xlate(struct irq_domain *d,
@@ -133,44 +165,22 @@ static int crossbar_domain_xlate(struct irq_domain *d,
 				 unsigned long *out_hwirq,
 				 unsigned int *out_type)
 {
-	int ret;
-	int req_num = intspec[1];
-	int direct_map_num;
-
-	if (req_num >= cb->max_crossbar_sources) {
-		direct_map_num = req_num - cb->max_crossbar_sources;
-		if (direct_map_num < cb->int_max) {
-			ret = cb->irq_map[direct_map_num];
-			if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
-				/* We use the interrupt num as h/w irq num */
-				ret = direct_map_num;
-				goto found;
-			}
-		}
-
-		pr_err("%s: requested crossbar number %d > max %d\n",
-		       __func__, req_num, cb->max_crossbar_sources);
-		return -EINVAL;
-	}
-
-	ret = get_prev_map_irq(req_num);
-	if (ret >= 0)
-		goto found;
-
-	ret = allocate_free_irq(req_num);
-
-	if (ret < 0)
-		return ret;
-
-found:
-	*out_hwirq = ret + GIC_IRQ_START;
+	if (d->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 const struct irq_domain_ops routable_irq_domain_ops = {
-	.map = crossbar_domain_map,
-	.unmap = crossbar_domain_unmap,
-	.xlate = crossbar_domain_xlate
+static const struct irq_domain_ops crossbar_domain_ops = {
+	.alloc	= crossbar_domain_alloc,
+	.free	= crossbar_domain_free,
+	.xlate	= crossbar_domain_xlate,
 };
 
 static int __init crossbar_of_init(struct device_node *node)
@@ -293,7 +303,8 @@ static int __init crossbar_of_init(struct device_node *node)
 		cb->write(i, cb->safe_map);
 	}
 
-	register_routable_domain_ops(&routable_irq_domain_ops);
+	raw_spin_lock_init(&cb->lock);
+
 	return 0;
 
 err_reg_offset:
@@ -309,18 +320,37 @@ err_cb:
 	return ret;
 }
 
-static const struct of_device_id crossbar_match[] __initconst = {
-	{ .compatible = "ti,irq-crossbar" },
-	{}
-};
-
-int __init irqcrossbar_init(void)
+static int __init irqcrossbar_init(struct device_node *node,
+				   struct device_node *parent)
 {
-	struct device_node *np;
-	np = of_find_matching_node(NULL, crossbar_match);
-	if (!np)
+	struct irq_domain *parent_domain, *domain;
+	int err;
+
+	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;
+	}
+
+	err = crossbar_of_init(node);
+	if (err)
+		return err;
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0,
+					  cb->max_crossbar_sources,
+					  node, &crossbar_domain_ops,
+					  NULL);
+	if (!domain) {
+		pr_err("%s: failed to allocated domain\n", node->full_name);
+		return -ENOMEM;
+	}
 
-	crossbar_of_init(np);
 	return 0;
 }
+
+IRQCHIP_DECLARE(ti_irqcrossbar, "ti,irq-crossbar", irqcrossbar_init);
diff --git a/include/linux/irqchip/irq-crossbar.h b/include/linux/irqchip/irq-crossbar.h
deleted file mode 100644
index e5537b8..0000000
--- a/include/linux/irqchip/irq-crossbar.h
+++ /dev/null
@@ -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);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 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       | 202 ++++++++++++++++++++---------------
 include/linux/irqchip/irq-crossbar.h |  11 --
 8 files changed, 141 insertions(+), 122 deletions(-)
 delete mode 100644 include/linux/irqchip/irq-crossbar.h

diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 10b725c..048cfeb 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -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>;
 };
 
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 22771bc..59ec0e6 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -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 = <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>;
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts
index 89085d0..298df33 100644
--- a/arch/arm/boot/dts/dra72-evm.dts
+++ b/arch/arm/boot/dts/dra72-evm.dts
@@ -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>;
 
diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi
index e5a3d23..e782bf1 100644
--- a/arch/arm/boot/dts/dra72x.dtsi
+++ b/arch/arm/boot/dts/dra72x.dtsi
@@ -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>;
 	};
 };
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 10173fa..0fc758d 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -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 {
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index b7cb44a..490d95e 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -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>
@@ -274,8 +273,5 @@ void __init omap_gic_of_init(void)
 
 skip_errata_init:
 	omap_wakeupgen_init();
-#ifdef CONFIG_IRQ_CROSSBAR
-	irqcrossbar_init();
-#endif
 	irqchip_init();
 }
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index bbbaf5d..f7daff0 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -11,11 +11,12 @@
  */
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/irqchip/irq-crossbar.h>
+
+#include "irqchip.h"
 
 #define IRQ_FREE	-1
 #define IRQ_RESERVED	-2
@@ -33,6 +34,7 @@
  * @write: register write function pointer
  */
 struct crossbar_device {
+	raw_spinlock_t lock;
 	uint int_max;
 	uint safe_map;
 	uint max_crossbar_sources;
@@ -44,72 +46,97 @@ struct crossbar_device {
 
 static struct crossbar_device *cb;
 
-static inline void crossbar_writel(int irq_no, int cb_no)
+static void crossbar_writel(int irq_no, int cb_no)
 {
 	writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline void crossbar_writew(int irq_no, int cb_no)
+static void crossbar_writew(int irq_no, int cb_no)
 {
 	writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline void crossbar_writeb(int irq_no, int cb_no)
+static void crossbar_writeb(int irq_no, int cb_no)
 {
 	writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
 }
 
-static inline int get_prev_map_irq(int cb_no)
-{
-	int i;
-
-	for (i = cb->int_max - 1; i >= 0; i--)
-		if (cb->irq_map[i] == cb_no)
-			return i;
-
-	return -ENODEV;
-}
+static struct irq_chip crossbar_chip = {
+	.name		= "CBAR",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= irq_chip_mask_parent,
+	.irq_unmask	= irq_chip_unmask_parent,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= irq_chip_set_wake_parent,
+};
 
-static inline int allocate_free_irq(int cb_no)
+static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
+			    irq_hw_number_t hwirq)
 {
+	struct of_phandle_args args;
 	int i;
+	int err;
 
+	raw_spin_lock(&cb->lock);
 	for (i = cb->int_max - 1; i >= 0; i--) {
 		if (cb->irq_map[i] == IRQ_FREE) {
-			cb->irq_map[i] = cb_no;
-			return i;
+			cb->irq_map[i] = hwirq;
+			break;
 		}
 	}
+	raw_spin_unlock(&cb->lock);
 
-	return -ENODEV;
-}
+	if (i < 0)
+		return -ENODEV;
 
-static inline bool needs_crossbar_write(irq_hw_number_t hw)
-{
-	int cb_no;
+	args.np = domain->parent->of_node;
+	args.args_count = 3;
+	args.args[0] = 0;	/* SPI */
+	args.args[1] = i;
+	args.args[2] = IRQ_TYPE_LEVEL_HIGH;
 
-	if (hw > GIC_IRQ_START) {
-		cb_no = cb->irq_map[hw - GIC_IRQ_START];
-		if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
-			return true;
-	}
+	err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
+	if (err)
+		cb->irq_map[i] = IRQ_FREE;
+	else
+		cb->write(i, hwirq);
 
-	return false;
+	return err;
 }
 
-static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
-			       irq_hw_number_t hw)
+static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
+				 unsigned int nr_irqs, void *data)
 {
-	if (needs_crossbar_write(hw))
-		cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
+	struct of_phandle_args *args = data;
+	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 + nr_irqs) > cb->max_crossbar_sources)
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++) {
+		int err = allocate_gic_irq(d, virq + i, hwirq + i);
+		if (err)
+			return err;
+
+		irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i,
+					      &crossbar_chip, NULL);
+	}
 
 	return 0;
 }
 
 /**
- * crossbar_domain_unmap - unmap a crossbar<->irq connection
+ * crossbar_domain_free - unmap/free a crossbar<->irq connection
  * @d: domain of irq to unmap
- * @irq: virq number
+ * @virq: virq number
+ * @nr_irqs: number of irqs to free
  *
  * We do not maintain a use count of total number of map/unmap
  * calls for a particular irq to find out if a irq can be really
@@ -117,14 +144,19 @@ static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
  * after which irq is anyways unusable. So an explicit map has to be called
  * after that.
  */
-static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
+static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
+				 unsigned int nr_irqs)
 {
-	irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
+	int i;
 
-	if (needs_crossbar_write(hw)) {
-		cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
-		cb->write(hw - GIC_IRQ_START, cb->safe_map);
+	raw_spin_lock(&cb->lock);
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+		irq_domain_reset_irq_data(d);
+		cb->irq_map[d->hwirq] = IRQ_FREE;
+		cb->write(d->hwirq, cb->safe_map);
 	}
+	raw_spin_unlock(&cb->lock);
 }
 
 static int crossbar_domain_xlate(struct irq_domain *d,
@@ -133,44 +165,22 @@ static int crossbar_domain_xlate(struct irq_domain *d,
 				 unsigned long *out_hwirq,
 				 unsigned int *out_type)
 {
-	int ret;
-	int req_num = intspec[1];
-	int direct_map_num;
-
-	if (req_num >= cb->max_crossbar_sources) {
-		direct_map_num = req_num - cb->max_crossbar_sources;
-		if (direct_map_num < cb->int_max) {
-			ret = cb->irq_map[direct_map_num];
-			if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
-				/* We use the interrupt num as h/w irq num */
-				ret = direct_map_num;
-				goto found;
-			}
-		}
-
-		pr_err("%s: requested crossbar number %d > max %d\n",
-		       __func__, req_num, cb->max_crossbar_sources);
-		return -EINVAL;
-	}
-
-	ret = get_prev_map_irq(req_num);
-	if (ret >= 0)
-		goto found;
-
-	ret = allocate_free_irq(req_num);
-
-	if (ret < 0)
-		return ret;
-
-found:
-	*out_hwirq = ret + GIC_IRQ_START;
+	if (d->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 const struct irq_domain_ops routable_irq_domain_ops = {
-	.map = crossbar_domain_map,
-	.unmap = crossbar_domain_unmap,
-	.xlate = crossbar_domain_xlate
+static const struct irq_domain_ops crossbar_domain_ops = {
+	.alloc	= crossbar_domain_alloc,
+	.free	= crossbar_domain_free,
+	.xlate	= crossbar_domain_xlate,
 };
 
 static int __init crossbar_of_init(struct device_node *node)
@@ -293,7 +303,8 @@ static int __init crossbar_of_init(struct device_node *node)
 		cb->write(i, cb->safe_map);
 	}
 
-	register_routable_domain_ops(&routable_irq_domain_ops);
+	raw_spin_lock_init(&cb->lock);
+
 	return 0;
 
 err_reg_offset:
@@ -309,18 +320,37 @@ err_cb:
 	return ret;
 }
 
-static const struct of_device_id crossbar_match[] __initconst = {
-	{ .compatible = "ti,irq-crossbar" },
-	{}
-};
-
-int __init irqcrossbar_init(void)
+static int __init irqcrossbar_init(struct device_node *node,
+				   struct device_node *parent)
 {
-	struct device_node *np;
-	np = of_find_matching_node(NULL, crossbar_match);
-	if (!np)
+	struct irq_domain *parent_domain, *domain;
+	int err;
+
+	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;
+	}
+
+	err = crossbar_of_init(node);
+	if (err)
+		return err;
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0,
+					  cb->max_crossbar_sources,
+					  node, &crossbar_domain_ops,
+					  NULL);
+	if (!domain) {
+		pr_err("%s: failed to allocated domain\n", node->full_name);
+		return -ENOMEM;
+	}
 
-	crossbar_of_init(np);
 	return 0;
 }
+
+IRQCHIP_DECLARE(ti_irqcrossbar, "ti,irq-crossbar", irqcrossbar_init);
diff --git a/include/linux/irqchip/irq-crossbar.h b/include/linux/irqchip/irq-crossbar.h
deleted file mode 100644
index e5537b8..0000000
--- a/include/linux/irqchip/irq-crossbar.h
+++ /dev/null
@@ -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);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 09/21] DT: update ti,irq-crossbar binding
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

Make it look like a real interrupt controller.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 .../devicetree/bindings/arm/omap/crossbar.txt          | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
index 4139db3..a9b28d7 100644
--- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt
+++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
@@ -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@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@0x4a023000 {
@@ -55,9 +53,3 @@ Example:
 		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
 		...
 	};
-
-	device_y@0x4a033000 {
-		/* Direct mapped GIC SPI 1 used */
-		interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>;
-		...
-	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 09/21] DT: update ti,irq-crossbar binding
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

Make it look like a real interrupt controller.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 .../devicetree/bindings/arm/omap/crossbar.txt          | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
index 4139db3..a9b28d7 100644
--- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt
+++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt
@@ -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>;
-		...
-	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 10/21] irqchip: GIC: get rid of routable domain
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 59 ++++-------------------------------------
 include/linux/irqchip/arm-gic.h |  6 -----
 2 files changed, 5 insertions(+), 60 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d617ee5..9c30a76 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -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.
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 71d706d..3978c5b 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -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
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 10/21] irqchip: GIC: get rid of routable domain
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 59 ++++-------------------------------------
 include/linux/irqchip/arm-gic.h |  6 -----
 2 files changed, 5 insertions(+), 60 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d617ee5..9c30a76 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -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.
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 71d706d..3978c5b 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -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
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 11/21] DT: arm,gic: kill arm,routable-irqs
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

Nobody will regret it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/devicetree/bindings/arm/gic.txt | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 8112d0c..631cb71 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -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@fff11000 {
@@ -64,7 +59,6 @@ Example:
 		#interrupt-cells = <3>;
 		#address-cells = <1>;
 		interrupt-controller;
-		arm,routable-irqs = <160>;
 		reg = <0xfff11000 0x1000>,
 		      <0xfff10100 0x100>;
 	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 11/21] DT: arm,gic: kill arm,routable-irqs
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

Nobody will regret it.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/devicetree/bindings/arm/gic.txt | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 8112d0c..631cb71 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -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>;
 	};
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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@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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/am4372.dtsi             |  11 ++-
 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              |  24 ++++--
 arch/arm/mach-omap2/omap-wakeupgen.c      | 125 +++++++++++++++++++++++-------
 arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
 arch/arm/mach-omap2/omap4-common.c        |   1 -
 15 files changed, 154 insertions(+), 65 deletions(-)

diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index b62a1cd..9d672a7 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -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@48281000 {
+		compatible = "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
 	};
 
 	l2-cache-controller@48242000 {
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 59ec0e6..a5741ae 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -64,6 +64,14 @@
 		interrupt-parent = <&gic>;
 	};
 
+	wakeupgen: interrupt-controller@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@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>;
diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi
index e782bf1..f7fb0d0 100644
--- a/arch/arm/boot/dts/dra72x.dtsi
+++ b/arch/arm/boot/dts/dra72x.dtsi
@@ -25,7 +25,7 @@
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupt-parent = <&gic>;
+		interrupt-parent = <&wakeupgen>;
 		interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 0fc758d..00eeed7 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -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>;
 	};
diff --git a/arch/arm/boot/dts/omap4-duovero.dtsi b/arch/arm/boot/dts/omap4-duovero.dtsi
index e860ccd..f2a94fa 100644
--- a/arch/arm/boot/dts/omap4-duovero.dtsi
+++ b/arch/arm/boot/dts/omap4-duovero.dtsi
@@ -173,14 +173,12 @@
 	twl: twl@48 {
 		reg = <0x48>;
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;		/* IRQ_SYS_1N cascaded to gic */
-		interrupt-parent = <&gic>;
 	};
 
 	twl6040: twl@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>;
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index 1505135..7c15fb2 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -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@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>;
 };
 
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 3e1da43..8aca8da 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -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@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>;
diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
index 062701e..a4f1ba2 100644
--- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi
+++ b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
@@ -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@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>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 074147c..7cb5236 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -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@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@48281000 {
+		compatible = "ti,omap4-wugen-mpu";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48281000 0x1000>;
+		interrupt-parent = <&gic>;
 	};
 
 	/*
@@ -319,7 +329,7 @@
 		uart2: serial@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@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@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>;
 		};
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts
index b54b271..61ad2ea 100644
--- a/arch/arm/boot/dts/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -412,7 +412,6 @@
 	palmas: palmas@48 {
 		compatible = "ti,palmas";
 		interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-		interrupt-parent = <&gic>;
 		reg = <0x48>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
index 159720d..74777a6 100644
--- a/arch/arm/boot/dts/omap5-uevm.dts
+++ b/arch/arm/boot/dts/omap5-uevm.dts
@@ -311,7 +311,6 @@
 	palmas: palmas@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>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index b321fdf..f9c75c7 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -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@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@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@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@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@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@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@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>;
 		};
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index f961c46..fde487d 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -20,11 +20,12 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/cpu_pm.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include "omap-wakeupgen.h"
 #include "omap-secure.h"
@@ -78,29 +79,12 @@ static inline void sar_writel(u32 val, u32 offset, u8 idx)
 
 static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index)
 {
-	unsigned int spi_irq;
-
-	/*
-	 * PPIs and SGIs are not supported.
-	 */
-	if (irq < OMAP44XX_IRQ_GIC_START)
-		return -EINVAL;
-
-	/*
-	 * Subtract the GIC offset.
-	 */
-	spi_irq = irq - OMAP44XX_IRQ_GIC_START;
-	if (spi_irq > MAX_IRQS) {
-		pr_err("omap wakeupGen: Invalid IRQ%d\n", irq);
-		return -EINVAL;
-	}
-
 	/*
 	 * Each WakeupGen register controls 32 interrupt.
 	 * i.e. 1 bit per SPI IRQ
 	 */
-	*reg_index = spi_irq >> 5;
-	*bit_posn = spi_irq %= 32;
+	*reg_index = irq >> 5;
+	*bit_posn = irq %= 32;
 
 	return 0;
 }
@@ -141,6 +125,7 @@ static void wakeupgen_mask(struct irq_data *d)
 	raw_spin_lock_irqsave(&wakeupgen_lock, flags);
 	_wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]);
 	raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+	irq_chip_mask_parent(d);
 }
 
 /*
@@ -153,6 +138,7 @@ static void wakeupgen_unmask(struct irq_data *d)
 	raw_spin_lock_irqsave(&wakeupgen_lock, flags);
 	_wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]);
 	raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+	irq_chip_unmask_parent(d);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -400,15 +386,88 @@ int omap_secure_apis_support(void)
 	return omap_secure_apis;
 }
 
+static struct irq_chip wakeupgen_chip = {
+	.name		= "WUGEN",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= wakeupgen_mask,
+	.irq_unmask	= wakeupgen_unmask,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.flags		= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static int wakeupgen_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 wakeupgen_domain_alloc(struct irq_domain *domain,
+				  unsigned int virq,
+				  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 >= MAX_IRQS)
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &wakeupgen_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops wakeupgen_domain_ops = {
+	.xlate	= wakeupgen_domain_xlate,
+	.alloc	= wakeupgen_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
 /*
  * Initialise the wakeupgen module.
  */
-int __init omap_wakeupgen_init(void)
+static int __init wakeupgen_init(struct device_node *node,
+				 struct device_node *parent)
 {
+	struct irq_domain *parent_domain, *domain;
 	int i;
 	unsigned int boot_cpu = smp_processor_id();
 	u32 val;
 
+	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;
+	}
 	/* Not supported on OMAP4 ES1.0 silicon */
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
 		WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
@@ -416,7 +475,7 @@ int __init omap_wakeupgen_init(void)
 	}
 
 	/* Static mapping, never released */
-	wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
+	wakeupgen_base = of_iomap(node, 0);
 	if (WARN_ON(!wakeupgen_base))
 		return -ENOMEM;
 
@@ -429,6 +488,14 @@ int __init omap_wakeupgen_init(void)
 		max_irqs = AM43XX_IRQS;
 	}
 
+	domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
+					  node, &wakeupgen_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(wakeupgen_base);
+		return -ENOMEM;
+	}
+
 	/* Clear all IRQ bitmasks at wakeupGen level */
 	for (i = 0; i < irq_banks; i++) {
 		wakeupgen_writel(0, i, CPU0_ID);
@@ -437,14 +504,6 @@ int __init omap_wakeupgen_init(void)
 	}
 
 	/*
-	 * Override GIC architecture specific functions to add
-	 * OMAP WakeupGen interrupt controller along with GIC
-	 */
-	gic_arch_extn.irq_mask = wakeupgen_mask;
-	gic_arch_extn.irq_unmask = wakeupgen_unmask;
-	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
-
-	/*
 	 * FIXME: Add support to set_smp_affinity() once the core
 	 * GIC code has necessary hooks in place.
 	 */
@@ -474,3 +533,9 @@ int __init omap_wakeupgen_init(void)
 
 	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, ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init);
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.h b/arch/arm/mach-omap2/omap-wakeupgen.h
index b3c8ecc..a3491ad 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.h
+++ b/arch/arm/mach-omap2/omap-wakeupgen.h
@@ -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
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 490d95e..9f29831 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -272,6 +272,5 @@ void __init omap_gic_of_init(void)
 	WARN_ON(!twd_base);
 
 skip_errata_init:
-	omap_wakeupgen_init();
 	irqchip_init();
 }
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/am4372.dtsi             |  11 ++-
 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              |  24 ++++--
 arch/arm/mach-omap2/omap-wakeupgen.c      | 125 +++++++++++++++++++++++-------
 arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
 arch/arm/mach-omap2/omap4-common.c        |   1 -
 15 files changed, 154 insertions(+), 65 deletions(-)

diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index b62a1cd..9d672a7 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -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 {
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 59ec0e6..a5741ae 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi
index e782bf1..f7fb0d0 100644
--- a/arch/arm/boot/dts/dra72x.dtsi
+++ b/arch/arm/boot/dts/dra72x.dtsi
@@ -25,7 +25,7 @@
 
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
-		interrupt-parent = <&gic>;
+		interrupt-parent = <&wakeupgen>;
 		interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 0fc758d..00eeed7 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -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>;
 	};
diff --git a/arch/arm/boot/dts/omap4-duovero.dtsi b/arch/arm/boot/dts/omap4-duovero.dtsi
index e860ccd..f2a94fa 100644
--- a/arch/arm/boot/dts/omap4-duovero.dtsi
+++ b/arch/arm/boot/dts/omap4-duovero.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index 1505135..7c15fb2 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -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>;
 };
 
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 3e1da43..8aca8da 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -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>;
diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
index 062701e..a4f1ba2 100644
--- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi
+++ b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
@@ -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>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 074147c..7cb5236 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -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>;
 		};
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts
index b54b271..61ad2ea 100644
--- a/arch/arm/boot/dts/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -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>;
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
index 159720d..74777a6 100644
--- a/arch/arm/boot/dts/omap5-uevm.dts
+++ b/arch/arm/boot/dts/omap5-uevm.dts
@@ -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>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index b321fdf..f9c75c7 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -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>;
 		};
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index f961c46..fde487d 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -20,11 +20,12 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/cpu_pm.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include "omap-wakeupgen.h"
 #include "omap-secure.h"
@@ -78,29 +79,12 @@ static inline void sar_writel(u32 val, u32 offset, u8 idx)
 
 static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index)
 {
-	unsigned int spi_irq;
-
-	/*
-	 * PPIs and SGIs are not supported.
-	 */
-	if (irq < OMAP44XX_IRQ_GIC_START)
-		return -EINVAL;
-
-	/*
-	 * Subtract the GIC offset.
-	 */
-	spi_irq = irq - OMAP44XX_IRQ_GIC_START;
-	if (spi_irq > MAX_IRQS) {
-		pr_err("omap wakeupGen: Invalid IRQ%d\n", irq);
-		return -EINVAL;
-	}
-
 	/*
 	 * Each WakeupGen register controls 32 interrupt.
 	 * i.e. 1 bit per SPI IRQ
 	 */
-	*reg_index = spi_irq >> 5;
-	*bit_posn = spi_irq %= 32;
+	*reg_index = irq >> 5;
+	*bit_posn = irq %= 32;
 
 	return 0;
 }
@@ -141,6 +125,7 @@ static void wakeupgen_mask(struct irq_data *d)
 	raw_spin_lock_irqsave(&wakeupgen_lock, flags);
 	_wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]);
 	raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+	irq_chip_mask_parent(d);
 }
 
 /*
@@ -153,6 +138,7 @@ static void wakeupgen_unmask(struct irq_data *d)
 	raw_spin_lock_irqsave(&wakeupgen_lock, flags);
 	_wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]);
 	raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+	irq_chip_unmask_parent(d);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -400,15 +386,88 @@ int omap_secure_apis_support(void)
 	return omap_secure_apis;
 }
 
+static struct irq_chip wakeupgen_chip = {
+	.name		= "WUGEN",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= wakeupgen_mask,
+	.irq_unmask	= wakeupgen_unmask,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.flags		= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static int wakeupgen_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 wakeupgen_domain_alloc(struct irq_domain *domain,
+				  unsigned int virq,
+				  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 >= MAX_IRQS)
+		return -EINVAL;	/* Can't deal with this */
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &wakeupgen_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops wakeupgen_domain_ops = {
+	.xlate	= wakeupgen_domain_xlate,
+	.alloc	= wakeupgen_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
 /*
  * Initialise the wakeupgen module.
  */
-int __init omap_wakeupgen_init(void)
+static int __init wakeupgen_init(struct device_node *node,
+				 struct device_node *parent)
 {
+	struct irq_domain *parent_domain, *domain;
 	int i;
 	unsigned int boot_cpu = smp_processor_id();
 	u32 val;
 
+	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;
+	}
 	/* Not supported on OMAP4 ES1.0 silicon */
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
 		WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
@@ -416,7 +475,7 @@ int __init omap_wakeupgen_init(void)
 	}
 
 	/* Static mapping, never released */
-	wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
+	wakeupgen_base = of_iomap(node, 0);
 	if (WARN_ON(!wakeupgen_base))
 		return -ENOMEM;
 
@@ -429,6 +488,14 @@ int __init omap_wakeupgen_init(void)
 		max_irqs = AM43XX_IRQS;
 	}
 
+	domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
+					  node, &wakeupgen_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(wakeupgen_base);
+		return -ENOMEM;
+	}
+
 	/* Clear all IRQ bitmasks at wakeupGen level */
 	for (i = 0; i < irq_banks; i++) {
 		wakeupgen_writel(0, i, CPU0_ID);
@@ -437,14 +504,6 @@ int __init omap_wakeupgen_init(void)
 	}
 
 	/*
-	 * Override GIC architecture specific functions to add
-	 * OMAP WakeupGen interrupt controller along with GIC
-	 */
-	gic_arch_extn.irq_mask = wakeupgen_mask;
-	gic_arch_extn.irq_unmask = wakeupgen_unmask;
-	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
-
-	/*
 	 * FIXME: Add support to set_smp_affinity() once the core
 	 * GIC code has necessary hooks in place.
 	 */
@@ -474,3 +533,9 @@ int __init omap_wakeupgen_init(void)
 
 	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, ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init);
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.h b/arch/arm/mach-omap2/omap-wakeupgen.h
index b3c8ecc..a3491ad 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.h
+++ b/arch/arm/mach-omap2/omap-wakeupgen.h
@@ -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
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 490d95e..9f29831 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -272,6 +272,5 @@ void __init omap_gic_of_init(void)
 	WARN_ON(!twd_base);
 
 skip_errata_init:
-	omap_wakeupgen_init();
 	irqchip_init();
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up generator
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 .../interrupt-controller/ti,omap4-wugen-mpu        | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
new file mode 100644
index 0000000..16149d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
@@ -0,0 +1,32 @@
+TI OMAP4 Wake-up Generator
+
+All TI OMAP4/5 (and their derivatives) an interrupt controllerthat
+routes interrupts to the GIC, and also serves as a wakeup source. It
+is also refered to as "WUGEN-MPU", hence the name of the binding.
+
+Reguired properties:
+
+- compatible : should contain at least "ti,omap4-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 ictlr as an interrupt parent. SGIs and PPIs
+  are explicitely forbiden.
+
+Example:
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
+       };
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up generator
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 .../interrupt-controller/ti,omap4-wugen-mpu        | 32 ++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
new file mode 100644
index 0000000..16149d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
@@ -0,0 +1,32 @@
+TI OMAP4 Wake-up Generator
+
+All TI OMAP4/5 (and their derivatives) an interrupt controllerthat
+routes interrupts to the GIC, and also serves as a wakeup source. It
+is also refered to as "WUGEN-MPU", hence the name of the binding.
+
+Reguired properties:
+
+- compatible : should contain at least "ti,omap4-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 ictlr as an interrupt parent. SGIs and PPIs
+  are explicitely 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>;
+       };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
 arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
 arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
 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, 116 insertions(+), 31 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 4fc03b7..c16d428 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -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@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,10 @@
 			gpc: gpc@020dc000 {
 				compatible = "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
 				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			gpr: iomuxc-gpr@020e0000 {
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 36ab8e0..35099b7 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -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@00900000 {
@@ -603,7 +604,9 @@
 			gpc: gpc@020dc000 {
 				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
 				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			gpr: iomuxc-gpr@020e0000 {
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 7a24fee..c476e67 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -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,9 @@
 			gpc: gpc@020dc000 {
 				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
 				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			iomuxc: iomuxc@020e0000 {
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cfcdb62..7052302 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -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);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 5f3602e..240109b 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -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 virq,
+				  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, virq + i, hwirq + i,
+					      &imx_gpc_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, 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;
-	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);
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 5057d61..bbe6ff8 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -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();
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 24bfaaf..d39c274 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -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();
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 7a96c65..72fa22d 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -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();
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
 arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
 arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
 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, 116 insertions(+), 31 deletions(-)

diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 4fc03b7..c16d428 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -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,10 @@
 			gpc: gpc at 020dc000 {
 				compatible = "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
 				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			gpr: iomuxc-gpr at 020e0000 {
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 36ab8e0..35099b7 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -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,9 @@
 			gpc: gpc at 020dc000 {
 				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
 				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			gpr: iomuxc-gpr at 020e0000 {
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 7a24fee..c476e67 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -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,9 @@
 			gpc: gpc at 020dc000 {
 				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
 				reg = <0x020dc000 0x4000>;
+				interrupt-controller;
 				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&intc>;
 			};
 
 			iomuxc: iomuxc at 020e0000 {
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index cfcdb62..7052302 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -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);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 5f3602e..240109b 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -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 virq,
+				  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, virq + i, hwirq + i,
+					      &imx_gpc_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, 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;
-	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);
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 5057d61..bbe6ff8 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -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();
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 24bfaaf..d39c274 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -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();
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 7a96c65..72fa22d 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -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();
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 15/21] ARM: exynos4/5: convert pmu wakeup to stacked domains
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/exynos4.dtsi    |   3 +
 arch/arm/boot/dts/exynos5250.dtsi |   3 +
 arch/arm/boot/dts/exynos5420.dtsi |   3 +
 arch/arm/mach-exynos/exynos.c     |  14 ++---
 arch/arm/mach-exynos/suspend.c    | 122 ++++++++++++++++++++++++++++++++++----
 5 files changed, 126 insertions(+), 19 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index b8168f1..adc189f 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -141,6 +141,8 @@
 	pmu_system_controller: system-controller@10020000 {
 		compatible = "samsung,exynos4210-pmu", "syscon";
 		reg = <0x10020000 0x4000>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	dsi_0: dsi@11C80000 {
@@ -253,6 +255,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";
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 0a229fc..c31007c 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -194,6 +194,8 @@
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon@10050000 {
@@ -230,6 +232,7 @@
 	rtc: rtc@101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 517e50f..1946c76c 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -309,6 +309,7 @@
 	rtc: rtc@101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
@@ -748,6 +749,8 @@
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon@10050000 {
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index c13d083..e417fdc 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -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)
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index f8e7dcd..24fc7f8 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -18,7 +18,9 @@
 #include <linux/syscore_ops.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/err.h>
 #include <linux/regulator/machine.h>
 
@@ -44,8 +46,8 @@
 #define EXYNOS5420_CPU_STATE	0x28
 
 /**
- * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
- * @hwirq: Hardware IRQ signal of the GIC
+ * struct exynos_wkup_irq - PMU IRQ to mask mapping
+ * @hwirq: Hardware IRQ signal of the PMU
  * @mask: Mask in PMU wake-up mask register
  */
 struct exynos_wkup_irq {
@@ -92,14 +94,14 @@ static unsigned int exynos_pmu_spare3;
 static u32 exynos_irqwake_intmask = 0xffffffff;
 
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
-	{ 76, BIT(1) }, /* RTC alarm */
-	{ 77, BIT(2) }, /* RTC tick */
+	{ 44, BIT(1) }, /* RTC alarm */
+	{ 45, BIT(2) }, /* RTC tick */
 	{ /* sentinel */ },
 };
 
 static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
-	{ 75, BIT(1) }, /* RTC alarm */
-	{ 76, BIT(2) }, /* RTC tick */
+	{ 43, BIT(1) }, /* RTC alarm */
+	{ 44, BIT(2) }, /* RTC tick */
 	{ /* sentinel */ },
 };
 
@@ -153,6 +155,109 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
 	return -ENOENT;
 }
 
+static struct irq_chip exynos_pmu_chip = {
+	.name		= "PMU",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= irq_chip_mask_parent,
+	.irq_unmask	= irq_chip_unmask_parent,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= exynos_irq_set_wake,
+};
+
+static int exynos_pmu_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 exynos_pmu_domain_alloc(struct irq_domain *domain,
+				   unsigned int virq,
+				   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];
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &exynos_pmu_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops exynos_pmu_domain_ops = {
+	.xlate	= exynos_pmu_domain_xlate,
+	.alloc	= exynos_pmu_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
+static int __init exynos_pmu_irq_init(struct device_node *node,
+				      struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+
+	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;
+	}
+
+	pmu_base_addr = of_iomap(node, 0);
+
+	if (!pmu_base_addr) {
+		pr_err("%s: failed to find exynos pmu register\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
+					  node, &exynos_pmu_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(pmu_base_addr);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+#define EXYNOS_PMU_IRQ(symbol,name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+
+EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu");
+EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu");
+EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu");
+EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu");
+EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu");
+EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu");
+
 static int exynos_cpu_do_idle(void)
 {
 	/* issue the standby signal into the pm unit. */
@@ -550,9 +655,6 @@ void __init exynos_pm_init(void)
 	}
 	pm_data = (struct exynos_pm_data *) match->data;
 
-	/* Platform-specific GIC callback */
-	gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
-
 	/* All wakeup disable */
 	tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
 	tmp |= pm_data->wake_disable_mask;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 15/21] ARM: exynos4/5: convert pmu wakeup to stacked domains
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/exynos4.dtsi    |   3 +
 arch/arm/boot/dts/exynos5250.dtsi |   3 +
 arch/arm/boot/dts/exynos5420.dtsi |   3 +
 arch/arm/mach-exynos/exynos.c     |  14 ++---
 arch/arm/mach-exynos/suspend.c    | 122 ++++++++++++++++++++++++++++++++++----
 5 files changed, 126 insertions(+), 19 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index b8168f1..adc189f 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -141,6 +141,8 @@
 	pmu_system_controller: system-controller at 10020000 {
 		compatible = "samsung,exynos4210-pmu", "syscon";
 		reg = <0x10020000 0x4000>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	dsi_0: dsi at 11C80000 {
@@ -253,6 +255,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";
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 0a229fc..c31007c 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -194,6 +194,8 @@
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon at 10050000 {
@@ -230,6 +232,7 @@
 	rtc: rtc at 101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 517e50f..1946c76c 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -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,8 @@
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon at 10050000 {
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index c13d083..e417fdc 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -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)
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index f8e7dcd..24fc7f8 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -18,7 +18,9 @@
 #include <linux/syscore_ops.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/err.h>
 #include <linux/regulator/machine.h>
 
@@ -44,8 +46,8 @@
 #define EXYNOS5420_CPU_STATE	0x28
 
 /**
- * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
- * @hwirq: Hardware IRQ signal of the GIC
+ * struct exynos_wkup_irq - PMU IRQ to mask mapping
+ * @hwirq: Hardware IRQ signal of the PMU
  * @mask: Mask in PMU wake-up mask register
  */
 struct exynos_wkup_irq {
@@ -92,14 +94,14 @@ static unsigned int exynos_pmu_spare3;
 static u32 exynos_irqwake_intmask = 0xffffffff;
 
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
-	{ 76, BIT(1) }, /* RTC alarm */
-	{ 77, BIT(2) }, /* RTC tick */
+	{ 44, BIT(1) }, /* RTC alarm */
+	{ 45, BIT(2) }, /* RTC tick */
 	{ /* sentinel */ },
 };
 
 static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
-	{ 75, BIT(1) }, /* RTC alarm */
-	{ 76, BIT(2) }, /* RTC tick */
+	{ 43, BIT(1) }, /* RTC alarm */
+	{ 44, BIT(2) }, /* RTC tick */
 	{ /* sentinel */ },
 };
 
@@ -153,6 +155,109 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
 	return -ENOENT;
 }
 
+static struct irq_chip exynos_pmu_chip = {
+	.name		= "PMU",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= irq_chip_mask_parent,
+	.irq_unmask	= irq_chip_unmask_parent,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= exynos_irq_set_wake,
+};
+
+static int exynos_pmu_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 exynos_pmu_domain_alloc(struct irq_domain *domain,
+				   unsigned int virq,
+				   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];
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &exynos_pmu_chip, NULL);
+
+	parent_args = *args;
+	parent_args.np = domain->parent->of_node;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops exynos_pmu_domain_ops = {
+	.xlate	= exynos_pmu_domain_xlate,
+	.alloc	= exynos_pmu_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
+static int __init exynos_pmu_irq_init(struct device_node *node,
+				      struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+
+	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;
+	}
+
+	pmu_base_addr = of_iomap(node, 0);
+
+	if (!pmu_base_addr) {
+		pr_err("%s: failed to find exynos pmu register\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
+					  node, &exynos_pmu_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(pmu_base_addr);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+#define EXYNOS_PMU_IRQ(symbol,name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+
+EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu");
+EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu");
+EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu");
+EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu");
+EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu");
+EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu");
+
 static int exynos_cpu_do_idle(void)
 {
 	/* issue the standby signal into the pm unit. */
@@ -550,9 +655,6 @@ void __init exynos_pm_init(void)
 	}
 	pm_data = (struct exynos_pm_data *) match->data;
 
-	/* Platform-specific GIC callback */
-	gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
-
 	/* All wakeup disable */
 	tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
 	tmp |= pm_data->wake_disable_mask;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 16/21] DT: exynos: update PMU binding
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/devicetree/bindings/arm/samsung/pmu.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
index 1e1979b..d698e74 100644
--- a/Documentation/devicetree/bindings/arm/samsung/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
@@ -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@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";
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 16/21] DT: exynos: update PMU binding
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/devicetree/bindings/arm/samsung/pmu.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
index 1e1979b..d698e74 100644
--- a/Documentation/devicetree/bindings/arm/samsung/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt
@@ -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";
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 17/21] irqchip: gic: add an entry point to set up irqchip flags
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 5 +++++
 include/linux/irqchip/arm-gic.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 9c30a76..23fe3be 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -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)
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 3978c5b..36ec4ae 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -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);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 17/21] irqchip: gic: add an entry point to set up irqchip flags
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 5 +++++
 include/linux/irqchip/arm-gic.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 9c30a76..23fe3be 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -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)
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 3978c5b..36ec4ae 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -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);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 18/21] ARM: shmobile: remove use of gic_arch_extn.irq_set_wake
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: Simon Horman, linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Acked-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-shmobile/intc-sh73a0.c   | 7 +------
 arch/arm/mach-shmobile/setup-r8a7779.c | 7 +------
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 9e36180..fd63ae6 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -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);
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index 6156d17..989de2d 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -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();
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 18/21] ARM: shmobile: remove use of gic_arch_extn.irq_set_wake
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Acked-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-shmobile/intc-sh73a0.c   | 7 +------
 arch/arm/mach-shmobile/setup-r8a7779.c | 7 +------
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 9e36180..fd63ae6 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -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);
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index 6156d17..989de2d 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -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();
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 19/21] ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-ux500/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index dbb2970..6ced0f6 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -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();
 
 	/*
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 19/21] ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-ux500/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index dbb2970..6ced0f6 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -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();
 
 	/*
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 20/21] ARM: zynq: switch from gic_arch_extn to gic_set_irqchip_flags
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-zynq/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 26f92c2..82734d5 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -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();
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 20/21] ARM: zynq: switch from gic_arch_extn to gic_set_irqchip_flags
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mach-zynq/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 26f92c2..82734d5 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -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();
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 21/21] irqchip: gic: Drop support for gic_arch_extn
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 17:42   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 54 -----------------------------------------
 include/linux/irqchip/arm-gic.h |  2 --
 2 files changed, 56 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 23fe3be..78d4dee 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -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);
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 36ec4ae..9de976b 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -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 *);
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 21/21] irqchip: gic: Drop support for gic_arch_extn
@ 2015-01-07 17:42   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-07 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic.c       | 54 -----------------------------------------
 include/linux/irqchip/arm-gic.h |  2 --
 2 files changed, 56 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 23fe3be..78d4dee 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -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);
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 36ec4ae..9de976b 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -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 *);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-07 18:45   ` santosh shilimkar
  -1 siblings, 0 replies; 106+ messages in thread
From: santosh shilimkar @ 2015-01-07 18:45 UTC (permalink / raw)
  To: Marc Zyngier, Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-arm-kernel, linux-samsung-soc, linux-omap

Marc,

On 1/7/2015 9:42 AM, Marc Zyngier wrote:
> 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 landed in -next, 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 already broke it for the OMAP WUGEN block, we might as well do
>    it again for the TI 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 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.
>
> 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
>
> Comments welcome,
>
> 	 M.
>
> 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
>    ARM: omap: convert wakeupgen to stacked domains
>    DT: omap4/5: add binding for the wake-up generator
>    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
>
Thanks a lot for killing those gic_arch_extn and cross-bar with
newly added stacked domains. It cleans up the GIC code for better.
Feel free to add my ack if you need one.

Acked-by: Santosh Shilimkar <ssantosh@kernel.org>

Regards,
Snatosh

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-07 18:45   ` santosh shilimkar
  0 siblings, 0 replies; 106+ messages in thread
From: santosh shilimkar @ 2015-01-07 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

Marc,

On 1/7/2015 9:42 AM, Marc Zyngier wrote:
> 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 landed in -next, 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 already broke it for the OMAP WUGEN block, we might as well do
>    it again for the TI 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 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.
>
> 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
>
> Comments welcome,
>
> 	 M.
>
> 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
>    ARM: omap: convert wakeupgen to stacked domains
>    DT: omap4/5: add binding for the wake-up generator
>    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
>
Thanks a lot for killing those gic_arch_extn and cross-bar with
newly added stacked domains. It cleans up the GIC code for better.
Feel free to add my ack if you need one.

Acked-by: Santosh Shilimkar <ssantosh@kernel.org>

Regards,
Snatosh

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-08  3:31   ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08  3:31 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> As for the patches, they are on top of 3.19-rc3.
Applied the 21 patches and gave a quick dry run on various boards
BASE = v3.19-rc3 + 1 uImage+dtb patch for 
IRQ = v3.19-rc3 + irq series

NOTE: I am yet to dig in deeper to figure out which platform may have
valid regressions etc. will do that tomorrow. meanwhile, some raw test
results below:
+++v3.19-rc3 - BOOT TEST+++
boot
 1:                     am335x-evm: BOOT: PASS: http://slexy.org/raw/s2IOPX99Ty
 2:                      am335x-sk: BOOT: FAIL: http://slexy.org/raw/s2dzt0lTF7
 3:                     am3517-evm: BOOT: PASS: http://slexy.org/raw/s23yAMKuRx
 4:                      am37x-evm: BOOT: PASS: http://slexy.org/raw/s20vsYwsYQ
 5:                      am437x-sk: BOOT: PASS: http://slexy.org/raw/s2QgujFs6l
 6:                    am43xx-epos: BOOT: PASS: http://slexy.org/raw/s2QHVg9XcB
 7:                   am43xx-gpevm: BOOT: PASS: http://slexy.org/raw/s2Ep5DEQuk
 8:    BeagleBoard-X15(am57xx-evm): BOOT: PASS: http://slexy.org/raw/s20STBNTs9
 9:                 BeagleBoard-XM: BOOT: PASS: http://slexy.org/raw/s2UhG6u7yM
10:            beagleboard-vanilla: BOOT: PASS: http://slexy.org/raw/s2QB7ECFKw
11:               beaglebone-black: BOOT: PASS: http://slexy.org/raw/s20iAe7yTa
12:                     beaglebone: BOOT: PASS: http://slexy.org/raw/s20Uui1gkn
13:                     craneboard: BOOT: PASS: http://slexy.org/raw/s21DcY6gn4
14:                     dra72x-evm: BOOT: PASS: http://slexy.org/raw/s2qj7IvmaV
15:                     dra7xx-evm: BOOT: PASS: http://slexy.org/raw/s20lLxN8bR
16:         OMAP3430-Labrador(LDP): BOOT: PASS: http://slexy.org/raw/s20GmT9ASX
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s2riSEzfea
18:                      omap5-evm: BOOT: PASS: http://slexy.org/raw/s21adCD3Js
19:                  pandaboard-es: BOOT: PASS: http://slexy.org/raw/s21Am3vEzM
20:             pandaboard-vanilla: BOOT: PASS: http://slexy.org/raw/s2XLmW2ONB
21:                        sdp2430: BOOT: PASS: http://slexy.org/raw/s21ehzlzyv
22:                        sdp3430: BOOT: PASS: http://slexy.org/raw/s24gh1VUnl
23:                        sdp4430: BOOT: PASS: http://slexy.org/raw/s2HfgkFfOx
TOTAL = 23 boards, Booted Boards = 21, No Boot boards = 2
+++ IRQ - BOOT TEST+++
boot
 1:                     am335x-evm: BOOT: PASS: http://slexy.org/raw/s21411sejg
 2:                      am335x-sk: BOOT: PASS: http://slexy.org/raw/s209N4Tu4E
 3:                     am3517-evm: BOOT: PASS: http://slexy.org/raw/s2Shbhciy8
 4:                      am37x-evm: BOOT: PASS: http://slexy.org/raw/s20wfqH0Wo
 5:                      am437x-sk: BOOT: PASS: http://slexy.org/raw/s21uAXcB12
 6:                    am43xx-epos: BOOT: PASS: http://slexy.org/raw/s26MGCZz0i
 7:                   am43xx-gpevm: BOOT: PASS: http://slexy.org/raw/s2c8IGmWfB
 8:    BeagleBoard-X15(am57xx-evm): BOOT: FAIL: http://slexy.org/raw/s2u1yV4hHK
 9:                 BeagleBoard-XM: BOOT: PASS: http://slexy.org/raw/s20zzOBKWJ
10:            beagleboard-vanilla: BOOT: PASS: http://slexy.org/raw/s2wffxWVGa
11:               beaglebone-black: BOOT: PASS: http://slexy.org/raw/s2Yshc0Vkw
12:                     beaglebone: BOOT: PASS: http://slexy.org/raw/s2Ki0ohBVf
13:                     craneboard: BOOT: PASS: http://slexy.org/raw/s2GVlDWkzP
14:                     dra72x-evm: BOOT: PASS: http://slexy.org/raw/s2dfZIVZ42
15:                     dra7xx-evm: BOOT: PASS: http://slexy.org/raw/s25UqvqVna
16:         OMAP3430-Labrador(LDP): BOOT: PASS: http://slexy.org/raw/s20plEBPRB
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s20zeM6YUP
18:                      omap5-evm: BOOT: PASS: http://slexy.org/raw/s2JOb4VEGJ
19:                  pandaboard-es: BOOT: PASS: http://slexy.org/raw/s20jCqY4OV
20:             pandaboard-vanilla: BOOT: PASS: http://slexy.org/raw/s21TuquMeN
21:                        sdp2430: BOOT: PASS: http://slexy.org/raw/s20z1S6w1a
22:                        sdp3430: BOOT: PASS: http://slexy.org/raw/s20SJo6BqV
23:                        sdp4430: BOOT: PASS: http://slexy.org/raw/s204Bn9azX
TOTAL = 23 boards, Booted Boards = 21, No Boot boards = 2
+++v3.19-rc3 - POWER TEST+++
power
 1:                     am335x-evm: BOOT: PASS: err=10 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s20t02tklu
 2:                      am335x-sk: BOOT: FAIL: http://slexy.org/raw/s2HX7WisAk
 3:                     am3517-evm: BOOT: FAIL: http://slexy.org/raw/s2mdCPTUBw
 4:                      am37x-evm: BOOT: FAIL: http://slexy.org/raw/s2beWlmPMy
 5:                      am437x-sk: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2Z0QTrATC
 6:                    am43xx-epos: BOOT: PASS: crit=2 err=15 warn=26, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s21VqMaKE5
 7:                   am43xx-gpevm: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s28zvJSBnv
 8:    BeagleBoard-X15(am57xx-evm): BOOT: PASS: err=20 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2754wOSyR
 9:                 BeagleBoard-XM: BOOT: PASS: err=9 warn=19, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s21yJVYSQX
10:            beagleboard-vanilla: BOOT: PASS: err=9 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s2ePKa43mj
11:               beaglebone-black: BOOT: PASS: err=8 warn=25, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2gFTc8yGz
12:                     beaglebone: BOOT: PASS: err=9 warn=20, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2c9LVVWez
13:                     craneboard: BOOT: PASS: err=20 warn=60, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s210m3vNqa
14:                     dra72x-evm: BOOT: PASS: crit=2 err=14 warn=27, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2nCfZhtlX
15:                     dra7xx-evm: BOOT: PASS: err=11 warn=31, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2Ikj5xQNE
16:         OMAP3430-Labrador(LDP): BOOT: PASS: err=7 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s2tfdy65xq
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s21ByECFQh
18:                      omap5-evm: BOOT: PASS: err=15 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s21Jd8hDT3
19:                  pandaboard-es: BOOT: PASS: err=20 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s20fKLg0PV
20:             pandaboard-vanilla: BOOT: PASS: err=20 warn=31, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s207BtiFCQ
21:                        sdp2430: BOOT: FAIL: http://slexy.org/raw/s2016uSIuh
22:                        sdp3430: BOOT: PASS: err=22 warn=28, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s205w47Ubl
23:                        sdp4430: BOOT: PASS: err=21 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s23YNhbaUe
TOTAL = 23 boards, Booted Boards = 18, No Boot boards = 5
TOTAL CPUFREQ enabled boards = 13.  CPUFREQ functional boards = 13, CPUFREQ failed boards = 0
TOTAL CPUIdle enabled boards = 7.  CPUIdle functional boards = 3, CPUIdle failed boards = 4
+++ IRQ - POWER TEST+++
power
 1:                     am335x-evm: BOOT: PASS: err=10 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2luRdrwTo
 2:                      am335x-sk: BOOT: PASS: err=8 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s20rhziuEz
 3:                     am3517-evm: BOOT: FAIL: http://slexy.org/raw/s20yHRtY5f
 4:                      am37x-evm: BOOT: FAIL: http://slexy.org/raw/s2eh5wioQj
 5:                      am437x-sk: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s213VjGWo1
 6:                    am43xx-epos: BOOT: PASS: crit=2 err=15 warn=26, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s20JCs4KKY
 7:                   am43xx-gpevm: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s20RScmcvK
 8:    BeagleBoard-X15(am57xx-evm): BOOT: FAIL: http://slexy.org/raw/s2155P8obZ
 9:                 BeagleBoard-XM: BOOT: PASS: err=9 warn=19, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s2018sfpgM
10:            beagleboard-vanilla: BOOT: PASS: err=9 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s28pJudRI4
11:               beaglebone-black: BOOT: PASS: err=8 warn=25, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2VNAfNqxl
12:                     beaglebone: BOOT: PASS: err=9 warn=20, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s20Ep0UYpp
13:                     craneboard: BOOT: PASS: err=20 warn=60, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2qyzBJXF1
14:                     dra72x-evm: BOOT: PASS: crit=2 err=14 warn=27, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2czDXEdYH
15:                     dra7xx-evm: BOOT: PASS: err=11 warn=31, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2029U2gMt
16:         OMAP3430-Labrador(LDP): BOOT: PASS: err=7 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s20pTYJKV4
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s2kKNGkdK8
18:                      omap5-evm: BOOT: PASS: err=15 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2FpijcXbP
19:                  pandaboard-es: BOOT: PASS: err=20 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s2i1S7kdqK
20:             pandaboard-vanilla: BOOT: PASS: err=20 warn=31, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s21v9TjuAr
21:                        sdp2430: BOOT: FAIL: http://slexy.org/raw/s207WeE74f
22:                        sdp3430: BOOT: PASS: err=22 warn=28, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s21OSk7p87
23:                        sdp4430: BOOT: PASS: err=21 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s2z01QnTgx
TOTAL = 23 boards, Booted Boards = 18, No Boot boards = 5
TOTAL CPUFREQ enabled boards = 13.  CPUFREQ functional boards = 13, CPUFREQ failed boards = 0
TOTAL CPUIdle enabled boards = 7.  CPUIdle functional boards = 3, CPUIdle failed boards = 4

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-08  3:31   ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08  3:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> As for the patches, they are on top of 3.19-rc3.
Applied the 21 patches and gave a quick dry run on various boards
BASE = v3.19-rc3 + 1 uImage+dtb patch for 
IRQ = v3.19-rc3 + irq series

NOTE: I am yet to dig in deeper to figure out which platform may have
valid regressions etc. will do that tomorrow. meanwhile, some raw test
results below:
+++v3.19-rc3 - BOOT TEST+++
boot
 1:                     am335x-evm: BOOT: PASS: http://slexy.org/raw/s2IOPX99Ty
 2:                      am335x-sk: BOOT: FAIL: http://slexy.org/raw/s2dzt0lTF7
 3:                     am3517-evm: BOOT: PASS: http://slexy.org/raw/s23yAMKuRx
 4:                      am37x-evm: BOOT: PASS: http://slexy.org/raw/s20vsYwsYQ
 5:                      am437x-sk: BOOT: PASS: http://slexy.org/raw/s2QgujFs6l
 6:                    am43xx-epos: BOOT: PASS: http://slexy.org/raw/s2QHVg9XcB
 7:                   am43xx-gpevm: BOOT: PASS: http://slexy.org/raw/s2Ep5DEQuk
 8:    BeagleBoard-X15(am57xx-evm): BOOT: PASS: http://slexy.org/raw/s20STBNTs9
 9:                 BeagleBoard-XM: BOOT: PASS: http://slexy.org/raw/s2UhG6u7yM
10:            beagleboard-vanilla: BOOT: PASS: http://slexy.org/raw/s2QB7ECFKw
11:               beaglebone-black: BOOT: PASS: http://slexy.org/raw/s20iAe7yTa
12:                     beaglebone: BOOT: PASS: http://slexy.org/raw/s20Uui1gkn
13:                     craneboard: BOOT: PASS: http://slexy.org/raw/s21DcY6gn4
14:                     dra72x-evm: BOOT: PASS: http://slexy.org/raw/s2qj7IvmaV
15:                     dra7xx-evm: BOOT: PASS: http://slexy.org/raw/s20lLxN8bR
16:         OMAP3430-Labrador(LDP): BOOT: PASS: http://slexy.org/raw/s20GmT9ASX
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s2riSEzfea
18:                      omap5-evm: BOOT: PASS: http://slexy.org/raw/s21adCD3Js
19:                  pandaboard-es: BOOT: PASS: http://slexy.org/raw/s21Am3vEzM
20:             pandaboard-vanilla: BOOT: PASS: http://slexy.org/raw/s2XLmW2ONB
21:                        sdp2430: BOOT: PASS: http://slexy.org/raw/s21ehzlzyv
22:                        sdp3430: BOOT: PASS: http://slexy.org/raw/s24gh1VUnl
23:                        sdp4430: BOOT: PASS: http://slexy.org/raw/s2HfgkFfOx
TOTAL = 23 boards, Booted Boards = 21, No Boot boards = 2
+++ IRQ - BOOT TEST+++
boot
 1:                     am335x-evm: BOOT: PASS: http://slexy.org/raw/s21411sejg
 2:                      am335x-sk: BOOT: PASS: http://slexy.org/raw/s209N4Tu4E
 3:                     am3517-evm: BOOT: PASS: http://slexy.org/raw/s2Shbhciy8
 4:                      am37x-evm: BOOT: PASS: http://slexy.org/raw/s20wfqH0Wo
 5:                      am437x-sk: BOOT: PASS: http://slexy.org/raw/s21uAXcB12
 6:                    am43xx-epos: BOOT: PASS: http://slexy.org/raw/s26MGCZz0i
 7:                   am43xx-gpevm: BOOT: PASS: http://slexy.org/raw/s2c8IGmWfB
 8:    BeagleBoard-X15(am57xx-evm): BOOT: FAIL: http://slexy.org/raw/s2u1yV4hHK
 9:                 BeagleBoard-XM: BOOT: PASS: http://slexy.org/raw/s20zzOBKWJ
10:            beagleboard-vanilla: BOOT: PASS: http://slexy.org/raw/s2wffxWVGa
11:               beaglebone-black: BOOT: PASS: http://slexy.org/raw/s2Yshc0Vkw
12:                     beaglebone: BOOT: PASS: http://slexy.org/raw/s2Ki0ohBVf
13:                     craneboard: BOOT: PASS: http://slexy.org/raw/s2GVlDWkzP
14:                     dra72x-evm: BOOT: PASS: http://slexy.org/raw/s2dfZIVZ42
15:                     dra7xx-evm: BOOT: PASS: http://slexy.org/raw/s25UqvqVna
16:         OMAP3430-Labrador(LDP): BOOT: PASS: http://slexy.org/raw/s20plEBPRB
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s20zeM6YUP
18:                      omap5-evm: BOOT: PASS: http://slexy.org/raw/s2JOb4VEGJ
19:                  pandaboard-es: BOOT: PASS: http://slexy.org/raw/s20jCqY4OV
20:             pandaboard-vanilla: BOOT: PASS: http://slexy.org/raw/s21TuquMeN
21:                        sdp2430: BOOT: PASS: http://slexy.org/raw/s20z1S6w1a
22:                        sdp3430: BOOT: PASS: http://slexy.org/raw/s20SJo6BqV
23:                        sdp4430: BOOT: PASS: http://slexy.org/raw/s204Bn9azX
TOTAL = 23 boards, Booted Boards = 21, No Boot boards = 2
+++v3.19-rc3 - POWER TEST+++
power
 1:                     am335x-evm: BOOT: PASS: err=10 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s20t02tklu
 2:                      am335x-sk: BOOT: FAIL: http://slexy.org/raw/s2HX7WisAk
 3:                     am3517-evm: BOOT: FAIL: http://slexy.org/raw/s2mdCPTUBw
 4:                      am37x-evm: BOOT: FAIL: http://slexy.org/raw/s2beWlmPMy
 5:                      am437x-sk: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2Z0QTrATC
 6:                    am43xx-epos: BOOT: PASS: crit=2 err=15 warn=26, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s21VqMaKE5
 7:                   am43xx-gpevm: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s28zvJSBnv
 8:    BeagleBoard-X15(am57xx-evm): BOOT: PASS: err=20 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2754wOSyR
 9:                 BeagleBoard-XM: BOOT: PASS: err=9 warn=19, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s21yJVYSQX
10:            beagleboard-vanilla: BOOT: PASS: err=9 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s2ePKa43mj
11:               beaglebone-black: BOOT: PASS: err=8 warn=25, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2gFTc8yGz
12:                     beaglebone: BOOT: PASS: err=9 warn=20, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2c9LVVWez
13:                     craneboard: BOOT: PASS: err=20 warn=60, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s210m3vNqa
14:                     dra72x-evm: BOOT: PASS: crit=2 err=14 warn=27, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2nCfZhtlX
15:                     dra7xx-evm: BOOT: PASS: err=11 warn=31, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2Ikj5xQNE
16:         OMAP3430-Labrador(LDP): BOOT: PASS: err=7 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s2tfdy65xq
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s21ByECFQh
18:                      omap5-evm: BOOT: PASS: err=15 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s21Jd8hDT3
19:                  pandaboard-es: BOOT: PASS: err=20 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s20fKLg0PV
20:             pandaboard-vanilla: BOOT: PASS: err=20 warn=31, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s207BtiFCQ
21:                        sdp2430: BOOT: FAIL: http://slexy.org/raw/s2016uSIuh
22:                        sdp3430: BOOT: PASS: err=22 warn=28, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s205w47Ubl
23:                        sdp4430: BOOT: PASS: err=21 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s23YNhbaUe
TOTAL = 23 boards, Booted Boards = 18, No Boot boards = 5
TOTAL CPUFREQ enabled boards = 13.  CPUFREQ functional boards = 13, CPUFREQ failed boards = 0
TOTAL CPUIdle enabled boards = 7.  CPUIdle functional boards = 3, CPUIdle failed boards = 4
+++ IRQ - POWER TEST+++
power
 1:                     am335x-evm: BOOT: PASS: err=10 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2luRdrwTo
 2:                      am335x-sk: BOOT: PASS: err=8 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s20rhziuEz
 3:                     am3517-evm: BOOT: FAIL: http://slexy.org/raw/s20yHRtY5f
 4:                      am37x-evm: BOOT: FAIL: http://slexy.org/raw/s2eh5wioQj
 5:                      am437x-sk: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s213VjGWo1
 6:                    am43xx-epos: BOOT: PASS: crit=2 err=15 warn=26, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s20JCs4KKY
 7:                   am43xx-gpevm: BOOT: PASS: crit=2 err=12 warn=25, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s20RScmcvK
 8:    BeagleBoard-X15(am57xx-evm): BOOT: FAIL: http://slexy.org/raw/s2155P8obZ
 9:                 BeagleBoard-XM: BOOT: PASS: err=9 warn=19, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s2018sfpgM
10:            beagleboard-vanilla: BOOT: PASS: err=9 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s28pJudRI4
11:               beaglebone-black: BOOT: PASS: err=8 warn=25, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2VNAfNqxl
12:                     beaglebone: BOOT: PASS: err=9 warn=20, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s20Ep0UYpp
13:                     craneboard: BOOT: PASS: err=20 warn=60, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2qyzBJXF1
14:                     dra72x-evm: BOOT: PASS: crit=2 err=14 warn=27, CPUFreq: N/A, CPUIdle: N/A: http://slexy.org/raw/s2czDXEdYH
15:                     dra7xx-evm: BOOT: PASS: err=11 warn=31, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2029U2gMt
16:         OMAP3430-Labrador(LDP): BOOT: PASS: err=7 warn=25, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s20pTYJKV4
17:                           n900: BOOT: FAIL: http://slexy.org/raw/s2kKNGkdK8
18:                      omap5-evm: BOOT: PASS: err=15 warn=24, CPUFreq: PASS, CPUIdle: N/A: http://slexy.org/raw/s2FpijcXbP
19:                  pandaboard-es: BOOT: PASS: err=20 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s2i1S7kdqK
20:             pandaboard-vanilla: BOOT: PASS: err=20 warn=31, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s21v9TjuAr
21:                        sdp2430: BOOT: FAIL: http://slexy.org/raw/s207WeE74f
22:                        sdp3430: BOOT: PASS: err=22 warn=28, CPUFreq: PASS, CPUIdle: FAIL: http://slexy.org/raw/s21OSk7p87
23:                        sdp4430: BOOT: PASS: err=21 warn=33, CPUFreq: PASS, CPUIdle: PASS: http://slexy.org/raw/s2z01QnTgx
TOTAL = 23 boards, Booted Boards = 18, No Boot boards = 5
TOTAL CPUFREQ enabled boards = 13.  CPUFREQ functional boards = 13, CPUFREQ failed boards = 0
TOTAL CPUIdle enabled boards = 7.  CPUIdle functional boards = 3, CPUIdle failed boards = 4

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 01/21] ARM: tegra: irq: nuke leftovers from non-DT support
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08  8:56     ` Thierry Reding
  -1 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08  8:56 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Alexandre Courbot, Benoit Cousson, Tony Lindgren,
	Nishanth Menon, Santosh Shilimkar, Shawn Guo, Sascha Hauer,
	Kukjin Kim, Simon Horman, Magnus Damm, Linus Walleij,
	Michal Simek, Rob Herring, Mark Rutland, Jason Cooper,
	Thomas Gleixner, linux-arm-kernel, linux-samsung-soc, linux-omap

[-- Attachment #1: Type: text/plain, Size: 364 bytes --]

On Wed, Jan 07, 2015 at 05:42:36PM +0000, Marc Zyngier wrote:
> The GIC is now always initialized from DT on tegra, and there is
> no point in keeping non-DT init code.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mach-tegra/irq.c | 8 --------
>  1 file changed, 8 deletions(-)

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 01/21] ARM: tegra: irq: nuke leftovers from non-DT support
@ 2015-01-08  8:56     ` Thierry Reding
  0 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08  8:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 07, 2015 at 05:42:36PM +0000, Marc Zyngier wrote:
> The GIC is now always initialized from DT on tegra, and there is
> no point in keeping non-DT init code.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mach-tegra/irq.c | 8 --------
>  1 file changed, 8 deletions(-)

Acked-by: Thierry Reding <treding@nvidia.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150108/127112d7/attachment.sig>

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 10:13     ` Thierry Reding
  -1 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:13 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Alexandre Courbot, Benoit Cousson, Tony Lindgren,
	Nishanth Menon, Santosh Shilimkar, Shawn Guo, Sascha Hauer,
	Kukjin Kim, Simon Horman, Magnus Damm, Linus Walleij,
	Michal Simek, Rob Herring, Mark Rutland, Jason Cooper,
	Thomas Gleixner, linux-arm-kernel, linux-samsung-soc, linux-omap

[-- Attachment #1: Type: text/plain, Size: 9534 bytes --]

On Wed, Jan 07, 2015 at 05:42:37PM +0000, Marc Zyngier wrote:
> 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

Nit: s/irq/IRQ/

> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  drivers/irqchip/Makefile    |   1 +
>  drivers/irqchip/irq-tegra.c | 335 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 336 insertions(+)
>  create mode 100644 drivers/irqchip/irq-tegra.c

This matches largely what I have in a local patch (modulo the stacked
domains vs. gic_arch_extn). A few comments below.

> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 9516a32..59f34be 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -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

Should these be sorted alphabetically?

> diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
[...]
> +#define TEGRA_MAX_NUM_ICTLRS	5
> +
> +static int num_ictlrs;

This could be unsigned int.

> +struct tegra_ictlr_info {
> +	void __iomem *ictlr_reg_base[TEGRA_MAX_NUM_ICTLRS];

Maybe only "reg_base" or "base". The ictlr_ prefix is redundant.

> +#ifdef CONFIG_PM_SLEEP
> +	u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
> +	u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
> +	u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
> +	u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
> +
> +	u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];

Same here.

> +#endif
> +};
> +
> +static struct tegra_ictlr_info *tegra_ictlr_info;

This variable name could be shorter, say "lic", to make some of the code
below more terse.

> +static int tegra_ictlr_suspend(void)
> +{
> +	unsigned long flags;
> +	int i;

This could be unsigned int, too.

[...]
> +static void tegra_ictlr_resume(void)
> +{
> +	unsigned long flags;
> +	int i;

And here.

> +static struct syscore_ops tegra_ictlr_syscore_ops = {
> +	.suspend	= tegra_ictlr_suspend,
> +	.resume		= tegra_ictlr_resume,
> +};
> +
> +static int tegra_ictlr_syscore_init(void)
> +{
> +	register_syscore_ops(&tegra_ictlr_syscore_ops);
> +
> +	return 0;
> +}
> +#else
> +#define tegra_set_wake	NULL
> +static inline void tegra_ictlr_syscore_init(void) {}
> +#endif

Both prototypes for tegra_ictlr_syscore_init() should match here. Since
it never fails, returning void for both should be fine.

> +static struct irq_chip tegra_ictlr_chip = {
> +	.name		= "ICTLR",

Maybe name it "LIC" since that's the more common name for it?

> +static int tegra_ictlr_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)

Maybe use GIC_SPI from dt-bindings/interrupt-controller/arm-gic.h here?
To match the DTS content?

> +static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
> +				    unsigned int virq,
> +				    unsigned int nr_irqs, void *data)
> +{
> +	struct of_phandle_args *args = data;
> +	struct of_phandle_args parent_args;
> +	struct tegra_ictlr_info *info = domain->host_data;
> +	irq_hw_number_t hwirq;
> +	int i;

unsigned int?

> +
> +	if (args->args_count != 3)
> +		return -EINVAL;	/* Not GIC compliant */
> +	if (args->args[0] != 0)

GIC_SPI?

> +	hwirq = args->args[1];
> +	if (hwirq >= (num_ictlrs * 32))
> +		return -EINVAL;	/* Can't deal with this */

Not sure if that comment is necessary here. It's fairly obvious why this
is an error. But it doesn't hurt, so if you prefer to leave it, that's
fine with me.

> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		int ictlr = (hwirq + i) / 32;

irq_hw_number_t? Or unsigned int?

> +
> +		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
> +					      &tegra_ictlr_chip,
> +					      &info->ictlr_reg_base[ictlr]);
> +	}
> +
> +	parent_args = *args;
> +	parent_args.np = domain->parent->of_node;
> +	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
> +}
> +
> +

There's an extra blank line here.

> +static void tegra_ictlr_domain_free(struct irq_domain *domain,
> +				    unsigned int virq,
> +				    unsigned int nr_irqs)
> +{
> +	int i;

unsigned int?

> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
> +		irq_domain_reset_irq_data(d);
> +	}
> +}

Aren't you missing a call to irq_domain_free_irqs_parent() here? If so,
why not use irq_domain_free_irqs_common() instead?

> +static struct irq_domain_ops tegra_ictlr_domain_ops = {

static const?

> +	.xlate	= tegra_ictlr_domain_xlate,
> +	.alloc	= tegra_ictlr_domain_alloc,
> +	.free	= tegra_ictlr_domain_free,
> +};
> +
> +static int __init tegra_ictlr_init(struct device_node *node,
> +				   struct device_node *parent)
> +{
> +	struct irq_domain *parent_domain, *domain;
> +	int err;
> +	int i;

unsigned int?

> +
> +	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;
> +	}
> +
> +	tegra_ictlr_info = kzalloc(sizeof(*tegra_ictlr_info), GFP_KERNEL);
> +	if (!tegra_ictlr_info)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
> +		void __iomem *base;
> +
> +		base = of_iomap(node, i);
> +		if (!base)
> +			break;
> +
> +		tegra_ictlr_info->ictlr_reg_base[i] = base;
> +
> +		/* Disable all interrupts */
> +		writel_relaxed(~0, base + ICTLR_CPU_IER_CLR);

I think you used ~0ul elsewhere, so maybe make this (or the other
instances) consistent?

> +		/* All interrupts target IRQ */
> +		writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
> +
> +		num_ictlrs++;
> +	}
> +
> +	if (!num_ictlrs) {
> +		pr_err("%s: no valid regions, giving up\n", node->full_name);
> +		err = -ENOMEM;
> +		goto out_free;
> +	}

The local patch that I have does this slightly differently. We have a
tiny table of struct of_device_ids that contains the number of interrupt
controllers to expect for a given compatible (see also below). The code
then checks that the node indeed has valid reg entries for each of the
controllers. So this could be something like:

	struct tegra_ictlr_soc {
		unsigned int num_ictlrs;
	};

	static const struct tegra_ictlr_soc tegra20_ictlr_soc = {
		.num_ictlrs = 4,
	};

	static const struct tegra_ictlr_soc tegra30_ictlr_soc = {
		.num_ictlrs = 5,
	};

	static const struct of_device_id ictlr_matches[] = {
		{ .compatible = "nvidia,tegra30-ictlr", .data = &tegra30_ictlr_soc },
		{ .compatible = "nvidia,tegra20-ictlr", .data = &tegra20_ictlr_soc },
		{ }
	};

And in tegra_ictrl_init():

	const struct of_device_id *match;

	match = of_match_node(ictlr_matches, node);
	if (!match)
		return -ENODEV;

	soc = match->data;

	...

	WARN(num_ictlrs != soc->num_ictlrs,
	     "Found %u interrupt controllers in DT; expected %u.\n",
	     num_ictlrs, soc->num_ictlrs);

> +
> +	domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
> +					  node, &tegra_ictlr_domain_ops,
> +					  tegra_ictlr_info);

Do we need to add a select IRQ_DOMAIN_HIERARCHY somewhere for this to
compile? I guess it's already implied by the select ARM_GIC from
ARCH_TEGRA, so maybe we don't have to be explicit.

> +	if (!domain) {
> +		pr_err("%s: failed to allocated domain\n", node->full_name);
> +		err = -ENOMEM;
> +		goto out_unmap;
> +	}
> +
> +	tegra_ictlr_syscore_init();
> +
> +	pr_info("%s: %d interrupts forwarded to %s\n",
> +		node->full_name, num_ictlrs * 32, parent->full_name);
> +
> +	return 0;
> +
> +out_unmap:
> +	for (i = 0; i < num_ictlrs; i++)
> +		iounmap(tegra_ictlr_info->ictlr_reg_base[i]);
> +out_free:
> +	kfree(tegra_ictlr_info);
> +	return err;
> +}
> +
> +IRQCHIP_DECLARE(tegra_ictlr, "nvidia,tegra-ictlr", tegra_ictlr_init);

In general we name compatible values after the first generation of the
SoC that introduced them. For the LIC this would be:

	compatible = "nvidia,tegra20-ictlr";
	
With Tegra30 the number of interrupt controllers was increased to 5, so
it needs a new compatible:

	compatible = "nvidia,tegra30-ictlr";

Subsequent generations remain compatible with this variant, but they
traditionally get their own compatible, so for Tegra114 we'd get:

	compatible = "nvidia,tegra114-ictlr", "nvidia,tegra30-ictlr";

And similar for Tegra124. So I think the IRQCHIP_DECLARE should match on
"nvidia,tegra20-ictlr" instead. For the same reason we should have a
second entry for the "nvidia,tegra30-ictlr" compatible.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
@ 2015-01-08 10:13     ` Thierry Reding
  0 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 07, 2015 at 05:42:37PM +0000, Marc Zyngier wrote:
> 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

Nit: s/irq/IRQ/

> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  drivers/irqchip/Makefile    |   1 +
>  drivers/irqchip/irq-tegra.c | 335 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 336 insertions(+)
>  create mode 100644 drivers/irqchip/irq-tegra.c

This matches largely what I have in a local patch (modulo the stacked
domains vs. gic_arch_extn). A few comments below.

> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 9516a32..59f34be 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -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

Should these be sorted alphabetically?

> diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
[...]
> +#define TEGRA_MAX_NUM_ICTLRS	5
> +
> +static int num_ictlrs;

This could be unsigned int.

> +struct tegra_ictlr_info {
> +	void __iomem *ictlr_reg_base[TEGRA_MAX_NUM_ICTLRS];

Maybe only "reg_base" or "base". The ictlr_ prefix is redundant.

> +#ifdef CONFIG_PM_SLEEP
> +	u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
> +	u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
> +	u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
> +	u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
> +
> +	u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];

Same here.

> +#endif
> +};
> +
> +static struct tegra_ictlr_info *tegra_ictlr_info;

This variable name could be shorter, say "lic", to make some of the code
below more terse.

> +static int tegra_ictlr_suspend(void)
> +{
> +	unsigned long flags;
> +	int i;

This could be unsigned int, too.

[...]
> +static void tegra_ictlr_resume(void)
> +{
> +	unsigned long flags;
> +	int i;

And here.

> +static struct syscore_ops tegra_ictlr_syscore_ops = {
> +	.suspend	= tegra_ictlr_suspend,
> +	.resume		= tegra_ictlr_resume,
> +};
> +
> +static int tegra_ictlr_syscore_init(void)
> +{
> +	register_syscore_ops(&tegra_ictlr_syscore_ops);
> +
> +	return 0;
> +}
> +#else
> +#define tegra_set_wake	NULL
> +static inline void tegra_ictlr_syscore_init(void) {}
> +#endif

Both prototypes for tegra_ictlr_syscore_init() should match here. Since
it never fails, returning void for both should be fine.

> +static struct irq_chip tegra_ictlr_chip = {
> +	.name		= "ICTLR",

Maybe name it "LIC" since that's the more common name for it?

> +static int tegra_ictlr_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)

Maybe use GIC_SPI from dt-bindings/interrupt-controller/arm-gic.h here?
To match the DTS content?

> +static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
> +				    unsigned int virq,
> +				    unsigned int nr_irqs, void *data)
> +{
> +	struct of_phandle_args *args = data;
> +	struct of_phandle_args parent_args;
> +	struct tegra_ictlr_info *info = domain->host_data;
> +	irq_hw_number_t hwirq;
> +	int i;

unsigned int?

> +
> +	if (args->args_count != 3)
> +		return -EINVAL;	/* Not GIC compliant */
> +	if (args->args[0] != 0)

GIC_SPI?

> +	hwirq = args->args[1];
> +	if (hwirq >= (num_ictlrs * 32))
> +		return -EINVAL;	/* Can't deal with this */

Not sure if that comment is necessary here. It's fairly obvious why this
is an error. But it doesn't hurt, so if you prefer to leave it, that's
fine with me.

> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		int ictlr = (hwirq + i) / 32;

irq_hw_number_t? Or unsigned int?

> +
> +		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
> +					      &tegra_ictlr_chip,
> +					      &info->ictlr_reg_base[ictlr]);
> +	}
> +
> +	parent_args = *args;
> +	parent_args.np = domain->parent->of_node;
> +	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
> +}
> +
> +

There's an extra blank line here.

> +static void tegra_ictlr_domain_free(struct irq_domain *domain,
> +				    unsigned int virq,
> +				    unsigned int nr_irqs)
> +{
> +	int i;

unsigned int?

> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
> +		irq_domain_reset_irq_data(d);
> +	}
> +}

Aren't you missing a call to irq_domain_free_irqs_parent() here? If so,
why not use irq_domain_free_irqs_common() instead?

> +static struct irq_domain_ops tegra_ictlr_domain_ops = {

static const?

> +	.xlate	= tegra_ictlr_domain_xlate,
> +	.alloc	= tegra_ictlr_domain_alloc,
> +	.free	= tegra_ictlr_domain_free,
> +};
> +
> +static int __init tegra_ictlr_init(struct device_node *node,
> +				   struct device_node *parent)
> +{
> +	struct irq_domain *parent_domain, *domain;
> +	int err;
> +	int i;

unsigned int?

> +
> +	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;
> +	}
> +
> +	tegra_ictlr_info = kzalloc(sizeof(*tegra_ictlr_info), GFP_KERNEL);
> +	if (!tegra_ictlr_info)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
> +		void __iomem *base;
> +
> +		base = of_iomap(node, i);
> +		if (!base)
> +			break;
> +
> +		tegra_ictlr_info->ictlr_reg_base[i] = base;
> +
> +		/* Disable all interrupts */
> +		writel_relaxed(~0, base + ICTLR_CPU_IER_CLR);

I think you used ~0ul elsewhere, so maybe make this (or the other
instances) consistent?

> +		/* All interrupts target IRQ */
> +		writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
> +
> +		num_ictlrs++;
> +	}
> +
> +	if (!num_ictlrs) {
> +		pr_err("%s: no valid regions, giving up\n", node->full_name);
> +		err = -ENOMEM;
> +		goto out_free;
> +	}

The local patch that I have does this slightly differently. We have a
tiny table of struct of_device_ids that contains the number of interrupt
controllers to expect for a given compatible (see also below). The code
then checks that the node indeed has valid reg entries for each of the
controllers. So this could be something like:

	struct tegra_ictlr_soc {
		unsigned int num_ictlrs;
	};

	static const struct tegra_ictlr_soc tegra20_ictlr_soc = {
		.num_ictlrs = 4,
	};

	static const struct tegra_ictlr_soc tegra30_ictlr_soc = {
		.num_ictlrs = 5,
	};

	static const struct of_device_id ictlr_matches[] = {
		{ .compatible = "nvidia,tegra30-ictlr", .data = &tegra30_ictlr_soc },
		{ .compatible = "nvidia,tegra20-ictlr", .data = &tegra20_ictlr_soc },
		{ }
	};

And in tegra_ictrl_init():

	const struct of_device_id *match;

	match = of_match_node(ictlr_matches, node);
	if (!match)
		return -ENODEV;

	soc = match->data;

	...

	WARN(num_ictlrs != soc->num_ictlrs,
	     "Found %u interrupt controllers in DT; expected %u.\n",
	     num_ictlrs, soc->num_ictlrs);

> +
> +	domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
> +					  node, &tegra_ictlr_domain_ops,
> +					  tegra_ictlr_info);

Do we need to add a select IRQ_DOMAIN_HIERARCHY somewhere for this to
compile? I guess it's already implied by the select ARM_GIC from
ARCH_TEGRA, so maybe we don't have to be explicit.

> +	if (!domain) {
> +		pr_err("%s: failed to allocated domain\n", node->full_name);
> +		err = -ENOMEM;
> +		goto out_unmap;
> +	}
> +
> +	tegra_ictlr_syscore_init();
> +
> +	pr_info("%s: %d interrupts forwarded to %s\n",
> +		node->full_name, num_ictlrs * 32, parent->full_name);
> +
> +	return 0;
> +
> +out_unmap:
> +	for (i = 0; i < num_ictlrs; i++)
> +		iounmap(tegra_ictlr_info->ictlr_reg_base[i]);
> +out_free:
> +	kfree(tegra_ictlr_info);
> +	return err;
> +}
> +
> +IRQCHIP_DECLARE(tegra_ictlr, "nvidia,tegra-ictlr", tegra_ictlr_init);

In general we name compatible values after the first generation of the
SoC that introduced them. For the LIC this would be:

	compatible = "nvidia,tegra20-ictlr";
	
With Tegra30 the number of interrupt controllers was increased to 5, so
it needs a new compatible:

	compatible = "nvidia,tegra30-ictlr";

Subsequent generations remain compatible with this variant, but they
traditionally get their own compatible, so for Tegra114 we'd get:

	compatible = "nvidia,tegra114-ictlr", "nvidia,tegra30-ictlr";

And similar for Tegra124. So I think the IRQCHIP_DECLARE should match on
"nvidia,tegra20-ictlr" instead. For the same reason we should have a
second entry for the "nvidia,tegra30-ictlr" compatible.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150108/028f9853/attachment.sig>

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 03/21] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 10:16     ` Thierry Reding
  -1 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:16 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Alexandre Courbot, Benoit Cousson, Tony Lindgren,
	Nishanth Menon, Santosh Shilimkar, Shawn Guo, Sascha Hauer,
	Kukjin Kim, Simon Horman, Magnus Damm, Linus Walleij,
	Michal Simek, Rob Herring, Mark Rutland, Jason Cooper,
	Thomas Gleixner, linux-arm-kernel, linux-samsung-soc, linux-omap

[-- Attachment #1: Type: text/plain, Size: 1143 bytes --]

On Wed, Jan 07, 2015 at 05:42:38PM +0000, Marc Zyngier wrote:
> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mach-tegra/irq.c   | 11 +++++++++++
>  arch/arm/mach-tegra/tegra.c |  1 -
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
> index 7f87a50..b37141d 100644
> --- a/arch/arm/mach-tegra/irq.c
> +++ b/arch/arm/mach-tegra/irq.c
> @@ -255,11 +255,21 @@ 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,tegra-ictlr" },

Like I said elsewhere, I think this should be "nvidia,tegra20-ictlr" and
there should be another entry for "nvidia,tegra30-ictlr".

Otherwise looks good, so with that fixed:

Acked-by: Thierry Reding <treding@nvidia.com>

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 03/21] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
@ 2015-01-08 10:16     ` Thierry Reding
  0 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 07, 2015 at 05:42:38PM +0000, Marc Zyngier wrote:
> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/mach-tegra/irq.c   | 11 +++++++++++
>  arch/arm/mach-tegra/tegra.c |  1 -
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
> index 7f87a50..b37141d 100644
> --- a/arch/arm/mach-tegra/irq.c
> +++ b/arch/arm/mach-tegra/irq.c
> @@ -255,11 +255,21 @@ 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,tegra-ictlr" },

Like I said elsewhere, I think this should be "nvidia,tegra20-ictlr" and
there should be another entry for "nvidia,tegra30-ictlr".

Otherwise looks good, so with that fixed:

Acked-by: Thierry Reding <treding@nvidia.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150108/778ef8b2/attachment.sig>

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy interrupt controller
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 10:41     ` Thierry Reding
  -1 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:41 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Alexandre Courbot, Benoit Cousson, Tony Lindgren,
	Nishanth Menon, Santosh Shilimkar, Shawn Guo, Sascha Hauer,
	Kukjin Kim, Simon Horman, Magnus Damm, Linus Walleij,
	Michal Simek, Rob Herring, Mark Rutland, Jason Cooper,
	Thomas Gleixner, linux-arm-kernel, linux-samsung-soc, linux-omap

[-- Attachment #1: Type: text/plain, Size: 6432 bytes --]

On Wed, Jan 07, 2015 at 05:42:39PM +0000, Marc Zyngier wrote:
> Describe the legacy interrupt controller in every tegra DTSI files,
> and make it the parent of most interrupts.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  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(-)
> 
> diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
> index 4296b53..f70bed0 100644
> --- a/arch/arm/boot/dts/tegra114.dtsi
> +++ b/arch/arm/boot/dts/tegra114.dtsi
> @@ -8,7 +8,7 @@
>  
>  / {
>  	compatible = "nvidia,tegra114";
> -	interrupt-parent = <&gic>;
> +	interrupt-parent = <&ictlr>;

Maybe name the label "lic" because that's the more common name for this
controller? Same for the other DTSI files.

> @@ -134,6 +134,19 @@
>  		      <0x50046000 0x2000>;
>  		interrupts = <GIC_PPI 9
>  			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
> +		interrupt-parent = <&gic>;

Is this allowed? It makes the GIC its own parent. I guess we need it to
stop a loop from GIC -> LIC -> GIC, but it doesn't look quite right.

> +	};
> +
> +	ictlr: interrupt-controller@60004000 {
> +		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";

As previously discussed, I think the second string should be
"nvidia,tegra30-ictlr".

> +		reg = <0x60004000 64>,

I think the first entry should be 256 bytes long since there's another
block of 192 bytes of registers that's part of the interrupt controller,
albeit maybe not related to the functionality of the interrupt chip. But
they're still part of the same hardware block.

> +		      <0x60004100 64>,

According to the TRM there are 4 more registers in this block, so this
should be 80 in size.

> +		      <0x60004200 64>,
> +		      <0x60004300 64>,
> +		      <0x60004400 64>;

I'd prefer all of these to be hexadecimal.

> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		interrupt-parent = <&gic>;
>  	};
>  
>  	timer@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>;

Why does this get to have a non-default parent?

>  	};
>  };
> diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
[...]
> @@ -190,6 +191,18 @@
>  		status = "disabled";
>  	};
>  
> +	ictlr: interrupt-controller@60004000 {
> +		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";

Same as for Tegra114.

> +		reg = <0x0 0x60004000 0x0 0x40>,
> +		      <0x0 0x60004100 0x0 0x40>,
> +		      <0x0 0x60004200 0x0 0x40>,
> +		      <0x0 0x60004300 0x0 0x40>,
> +		      <0x0 0x60004400 0x0 0x40>;

According to the TRM, entries 1-4 should be 0x100 bytes. Even the first
entry could be 0x100 bytes long since there are additional registers in
there. While they may not be directly relevant to the interrupt chip, I
think it would make sense to include them here because they are part of
the same hardware block.

> diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
> index 8acf5d8..ab2f004 100644
> --- a/arch/arm/boot/dts/tegra20.dtsi
> +++ b/arch/arm/boot/dts/tegra20.dtsi
> @@ -7,7 +7,7 @@
>  
>  / {
>  	compatible = "nvidia,tegra20";
> -	interrupt-parent = <&intc>;
> +	interrupt-parent = <&ictlr>;

I wonder if we shouldn't rename the intc label to gic for consistency.
Could be in a follow-up patch though, and something that I can easily do
after this patch set.

>  
>  	host1x@50000000 {
>  		compatible = "nvidia,tegra20-host1x", "simple-bus";
> @@ -142,6 +142,7 @@
>  
>  	timer@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@50043000 {
> @@ -165,6 +167,17 @@
>  		cache-level = <2>;
>  	};
>  
> +	ictlr: interrupt-controller@60004000 {
> +		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";

As discussed previously, I think the second compatible should be
dropped.

> +		reg = <0x60004000 64>,
> +		      <0x60004100 64>,
> +		      <0x60004200 64>,
> +		      <0x60004300 64>;

Same comments as for Tegra114, except the quinary controller which
doesn't exist on Tegra20.

> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		interrupt-parent = <&intc>;
> +	};
> +
>  	timer@60005000 {
>  		compatible = "nvidia,tegra20-timer";
>  		reg = <0x60005000 0x60>;

Why doesn't the Tegra timer get to keep the GIC as parent like for
Tegra114 and Tegra124? Instead I see that the Cortex-A9 TWD timer gets
to keep the parent instead.

> diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
[...]
> @@ -228,6 +228,7 @@
>  	timer@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@50043000 {
> @@ -250,6 +252,18 @@
>  		cache-level = <2>;
>  	};
>  
> +	ictlr: interrupt-controller@60004000 {
> +		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";

Should be "nvidia,tegra30-ictlr" only.

> +		reg = <0x60004000 64>,
> +		      <0x60004100 64>,
> +		      <0x60004200 64>,
> +		      <0x60004300 64>,
> +		      <0x60004400 64>;
> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		interrupt-parent = <&intc>;
> +	};

This should be the same as for Tegra114.

> +
>  	timer@60005000 {
>  		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
>  		reg = <0x60005000 0x400>;

Like for Tegra20, the Tegra timer is now switched to the LIC as parent.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy interrupt controller
@ 2015-01-08 10:41     ` Thierry Reding
  0 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 07, 2015 at 05:42:39PM +0000, Marc Zyngier wrote:
> Describe the legacy interrupt controller in every tegra DTSI files,
> and make it the parent of most interrupts.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  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(-)
> 
> diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
> index 4296b53..f70bed0 100644
> --- a/arch/arm/boot/dts/tegra114.dtsi
> +++ b/arch/arm/boot/dts/tegra114.dtsi
> @@ -8,7 +8,7 @@
>  
>  / {
>  	compatible = "nvidia,tegra114";
> -	interrupt-parent = <&gic>;
> +	interrupt-parent = <&ictlr>;

Maybe name the label "lic" because that's the more common name for this
controller? Same for the other DTSI files.

> @@ -134,6 +134,19 @@
>  		      <0x50046000 0x2000>;
>  		interrupts = <GIC_PPI 9
>  			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
> +		interrupt-parent = <&gic>;

Is this allowed? It makes the GIC its own parent. I guess we need it to
stop a loop from GIC -> LIC -> GIC, but it doesn't look quite right.

> +	};
> +
> +	ictlr: interrupt-controller at 60004000 {
> +		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";

As previously discussed, I think the second string should be
"nvidia,tegra30-ictlr".

> +		reg = <0x60004000 64>,

I think the first entry should be 256 bytes long since there's another
block of 192 bytes of registers that's part of the interrupt controller,
albeit maybe not related to the functionality of the interrupt chip. But
they're still part of the same hardware block.

> +		      <0x60004100 64>,

According to the TRM there are 4 more registers in this block, so this
should be 80 in size.

> +		      <0x60004200 64>,
> +		      <0x60004300 64>,
> +		      <0x60004400 64>;

I'd prefer all of these to be hexadecimal.

> +		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>;

Why does this get to have a non-default parent?

>  	};
>  };
> diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
[...]
> @@ -190,6 +191,18 @@
>  		status = "disabled";
>  	};
>  
> +	ictlr: interrupt-controller at 60004000 {
> +		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";

Same as for Tegra114.

> +		reg = <0x0 0x60004000 0x0 0x40>,
> +		      <0x0 0x60004100 0x0 0x40>,
> +		      <0x0 0x60004200 0x0 0x40>,
> +		      <0x0 0x60004300 0x0 0x40>,
> +		      <0x0 0x60004400 0x0 0x40>;

According to the TRM, entries 1-4 should be 0x100 bytes. Even the first
entry could be 0x100 bytes long since there are additional registers in
there. While they may not be directly relevant to the interrupt chip, I
think it would make sense to include them here because they are part of
the same hardware block.

> diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
> index 8acf5d8..ab2f004 100644
> --- a/arch/arm/boot/dts/tegra20.dtsi
> +++ b/arch/arm/boot/dts/tegra20.dtsi
> @@ -7,7 +7,7 @@
>  
>  / {
>  	compatible = "nvidia,tegra20";
> -	interrupt-parent = <&intc>;
> +	interrupt-parent = <&ictlr>;

I wonder if we shouldn't rename the intc label to gic for consistency.
Could be in a follow-up patch though, and something that I can easily do
after this patch set.

>  
>  	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>;
>  	};
>  
> +	ictlr: interrupt-controller at 60004000 {
> +		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";

As discussed previously, I think the second compatible should be
dropped.

> +		reg = <0x60004000 64>,
> +		      <0x60004100 64>,
> +		      <0x60004200 64>,
> +		      <0x60004300 64>;

Same comments as for Tegra114, except the quinary controller which
doesn't exist on Tegra20.

> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		interrupt-parent = <&intc>;
> +	};
> +
>  	timer at 60005000 {
>  		compatible = "nvidia,tegra20-timer";
>  		reg = <0x60005000 0x60>;

Why doesn't the Tegra timer get to keep the GIC as parent like for
Tegra114 and Tegra124? Instead I see that the Cortex-A9 TWD timer gets
to keep the parent instead.

> diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
[...]
> @@ -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>;
>  	};
>  
> +	ictlr: interrupt-controller at 60004000 {
> +		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";

Should be "nvidia,tegra30-ictlr" only.

> +		reg = <0x60004000 64>,
> +		      <0x60004100 64>,
> +		      <0x60004200 64>,
> +		      <0x60004300 64>,
> +		      <0x60004400 64>;
> +		interrupt-controller;
> +		#interrupt-cells = <3>;
> +		interrupt-parent = <&intc>;
> +	};

This should be the same as for Tegra114.

> +
>  	timer at 60005000 {
>  		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
>  		reg = <0x60005000 0x400>;

Like for Tegra20, the Tegra timer is now switched to the LIC as parent.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150108/6da51cd8/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 05/21] DT: tegra: add binding for the legacy interrupt controller
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 10:51     ` Thierry Reding
  -1 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:51 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Alexandre Courbot, Benoit Cousson, Tony Lindgren,
	Nishanth Menon, Santosh Shilimkar, Shawn Guo, Sascha Hauer,
	Kukjin Kim, Simon Horman, Magnus Damm, Linus Walleij,
	Michal Simek, Rob Herring, Mark Rutland, Jason Cooper,
	Thomas Gleixner, linux-arm-kernel, linux-samsung-soc, linux-omap

[-- Attachment #1: Type: text/plain, Size: 2390 bytes --]

On Wed, Jan 07, 2015 at 05:42:40PM +0000, Marc Zyngier wrote:
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  .../interrupt-controller/nvidia,tegra-ictlr.txt    | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> new file mode 100644
> index 0000000..44fd873
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> @@ -0,0 +1,39 @@
> +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
> +refered to as "ictlr", hence the name of the binding.
> +
> +The HW block exposes a number of frames, each implementing a set of 32
> +interrupts.

I don't think I've ever seen them referred to as "frames". They are
technically separate instances of the same controller. Maybe:

	"The HW block exposes a number of controllers, ..."

?

> +
> +Reguired properties:
> +
> +- compatible : should contain at least "nvidia,tegra-ictlr".

As previously discussed I think this should be something along the lines
of:

	should be one of:
	- "nvidia,tegra20-ictlr"
	- "nvidia,tegra30-ictlr"

Or similar. In the past, we've used "nvidia,tegra<chip>-foo" to wildcard
the compatible string so that we don't have to modify the documentation
for every new chip. The above has the disadvantage that it omits that we
should always provide a most specific compatible string, too, so maybe
something like the following would be even better:

	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 frame must be described separately.

"Each controller must be described separately."? Also maybe mention that
this Tegra20 has 4 of them, whereas Tegra30 and later have 5? That way
people will know how many entries are required.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 05/21] DT: tegra: add binding for the legacy interrupt controller
@ 2015-01-08 10:51     ` Thierry Reding
  0 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 07, 2015 at 05:42:40PM +0000, Marc Zyngier wrote:
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  .../interrupt-controller/nvidia,tegra-ictlr.txt    | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> new file mode 100644
> index 0000000..44fd873
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> @@ -0,0 +1,39 @@
> +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
> +refered to as "ictlr", hence the name of the binding.
> +
> +The HW block exposes a number of frames, each implementing a set of 32
> +interrupts.

I don't think I've ever seen them referred to as "frames". They are
technically separate instances of the same controller. Maybe:

	"The HW block exposes a number of controllers, ..."

?

> +
> +Reguired properties:
> +
> +- compatible : should contain at least "nvidia,tegra-ictlr".

As previously discussed I think this should be something along the lines
of:

	should be one of:
	- "nvidia,tegra20-ictlr"
	- "nvidia,tegra30-ictlr"

Or similar. In the past, we've used "nvidia,tegra<chip>-foo" to wildcard
the compatible string so that we don't have to modify the documentation
for every new chip. The above has the disadvantage that it omits that we
should always provide a most specific compatible string, too, so maybe
something like the following would be even better:

	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 frame must be described separately.

"Each controller must be described separately."? Also maybe mention that
this Tegra20 has 4 of them, whereas Tegra30 and later have 5? That way
people will know how many entries are required.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150108/ac662c63/attachment.sig>

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 06/21] ARM: tegra: remove old LIC support
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 11:29     ` Thierry Reding
  -1 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 11:29 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Alexandre Courbot, Benoit Cousson, Tony Lindgren,
	Nishanth Menon, Santosh Shilimkar, Shawn Guo, Sascha Hauer,
	Kukjin Kim, Simon Horman, Magnus Damm, Linus Walleij,
	Michal Simek, Rob Herring, Mark Rutland, Jason Cooper,
	Thomas Gleixner, linux-arm-kernel, linux-samsung-soc, linux-omap

[-- Attachment #1: Type: text/plain, Size: 1946 bytes --]

On Wed, Jan 07, 2015 at 05:42:41PM +0000, Marc Zyngier wrote:
[...]
> diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
[...]
>  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;
> -
> -	if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
> -		WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.",
> -			num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
> -		num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
> -	}
> -
> -	for (i = 0; i < num_ictlrs; i++) {
> -		void __iomem *ictlr = ictlr_reg_base[i];
> -		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
> -		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
> -	}
> -
> -	gic_arch_extn.irq_ack = tegra_ack;
> -	gic_arch_extn.irq_eoi = tegra_eoi;
> -	gic_arch_extn.irq_mask = tegra_mask;
> -	gic_arch_extn.irq_unmask = tegra_unmask;
> -	gic_arch_extn.irq_retrigger = tegra_retrigger;
> -	gic_arch_extn.irq_set_wake = tegra_set_wake;
> -	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
> +	if (!of_find_matching_node(NULL, tegra_ictlr_match))
> +		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");

I'm not very happy about the ABI breakage here, but I also realize that
we need this change to properly describe the hardware. To make it more
obvious that people really should update their DTBs, maybe turn this
into a WARN()?

> -skip_extn_setup:
>  	tegra114_gic_cpu_pm_registration();

I'm not intimately familiar with the GIC, but is this really SoC
specific? Doesn't anybody else need this? Comparing to the GIC spec the
write of 0x1e0 to the GIC_CPU_CTRL register (which I assume corresponds
to GICC_CTLR in the spec), this simply disables the IRQ and FIQ bypass
signals for both group 0 and group 1.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 06/21] ARM: tegra: remove old LIC support
@ 2015-01-08 11:29     ` Thierry Reding
  0 siblings, 0 replies; 106+ messages in thread
From: Thierry Reding @ 2015-01-08 11:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 07, 2015 at 05:42:41PM +0000, Marc Zyngier wrote:
[...]
> diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
[...]
>  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;
> -
> -	if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
> -		WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.",
> -			num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
> -		num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
> -	}
> -
> -	for (i = 0; i < num_ictlrs; i++) {
> -		void __iomem *ictlr = ictlr_reg_base[i];
> -		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
> -		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
> -	}
> -
> -	gic_arch_extn.irq_ack = tegra_ack;
> -	gic_arch_extn.irq_eoi = tegra_eoi;
> -	gic_arch_extn.irq_mask = tegra_mask;
> -	gic_arch_extn.irq_unmask = tegra_unmask;
> -	gic_arch_extn.irq_retrigger = tegra_retrigger;
> -	gic_arch_extn.irq_set_wake = tegra_set_wake;
> -	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
> +	if (!of_find_matching_node(NULL, tegra_ictlr_match))
> +		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");

I'm not very happy about the ABI breakage here, but I also realize that
we need this change to properly describe the hardware. To make it more
obvious that people really should update their DTBs, maybe turn this
into a WARN()?

> -skip_extn_setup:
>  	tegra114_gic_cpu_pm_registration();

I'm not intimately familiar with the GIC, but is this really SoC
specific? Doesn't anybody else need this? Comparing to the GIC spec the
write of 0x1e0 to the GIC_CPU_CTRL register (which I assume corresponds
to GICC_CTLR in the spec), this simply disables the IRQ and FIQ bypass
signals for both group 0 and group 1.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150108/d70c076b/attachment.sig>

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 14:39     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 14:39 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
[..]
> diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
> index 10b725c..048cfeb 100644
> --- a/arch/arm/boot/dts/dra7-evm.dts
> +++ b/arch/arm/boot/dts/dra7-evm.dts
> @@ -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>;
^^ interrrupt-extended for uart1 here
[..]

> diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
[...]
> @@ -344,7 +344,7 @@
>  		uart1: serial@4806a000 {
>  			compatible = "ti,omap4-uart";
>  			reg = <0x4806a000 0x100>;
> -			interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
> +			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
^^ implies we will have both interrupts and interrupts-extended
properties for uart1 in dra7-evm.dtb

Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
does not make it clear as to what the priority will be when both
properties are present.

[...]
Also, for 3.19-rc3, Missing the following causing x15 to fail boot.

diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index 49edbda68cd5..c2241c2e5d9d 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -335,7 +335,6 @@
 	mcp_rtc: rtc@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";
-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
@ 2015-01-08 14:39     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 14:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
[..]
> diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
> index 10b725c..048cfeb 100644
> --- a/arch/arm/boot/dts/dra7-evm.dts
> +++ b/arch/arm/boot/dts/dra7-evm.dts
> @@ -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>;
^^ interrrupt-extended for uart1 here
[..]

> diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
[...]
> @@ -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 = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
^^ implies we will have both interrupts and interrupts-extended
properties for uart1 in dra7-evm.dtb

Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
does not make it clear as to what the priority will be when both
properties are present.

[...]
Also, for 3.19-rc3, Missing the following causing x15 to fail boot.

diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index 49edbda68cd5..c2241c2e5d9d 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -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";
-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 15:06     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:06 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Thomas Gleixner, Shawn Guo, linux-arm-kernel, Jason Cooper

On 17:42-20150107, Marc Zyngier wrote:
> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---

Saw a few checkpatch warnings as below: all of them seem minors.

@@ -0,0 +1,35 @@
+WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
+#36: 
+new file mode 100644
+WARNING: line over 80 characters
+#169: FILE: drivers/irqchip/irq-tegra.c:129:
++		tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+WARNING: line over 80 characters
+#170: FILE: drivers/irqchip/irq-tegra.c:130:
++		tegra_ictlr_info->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+WARNING: line over 80 characters
+#171: FILE: drivers/irqchip/irq-tegra.c:131:
++		tegra_ictlr_info->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+WARNING: line over 80 characters
+#172: FILE: drivers/irqchip/irq-tegra.c:132:
++		tegra_ictlr_info->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+WARNING: line over 80 characters
+#181: FILE: drivers/irqchip/irq-tegra.c:141:
++		writel_relaxed(tegra_ictlr_info->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+WARNING: Missing a blank line after declarations
+#196: FILE: drivers/irqchip/irq-tegra.c:156:
++		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
++		writel_relaxed(tegra_ictlr_info->cpu_iep[i],
+WARNING: line over 80 characters
+#284: FILE: drivers/irqchip/irq-tegra.c:244:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+CHECK: Please don't use multiple blank lines
+#287: FILE: drivers/irqchip/irq-tegra.c:247:
++
++
+WARNING: Missing a blank line after declarations
+#296: FILE: drivers/irqchip/irq-tegra.c:256:
++		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
++		irq_domain_reset_irq_data(d);
`
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
@ 2015-01-08 15:06     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---

Saw a few checkpatch warnings as below: all of them seem minors.

@@ -0,0 +1,35 @@
+WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
+#36: 
+new file mode 100644
+WARNING: line over 80 characters
+#169: FILE: drivers/irqchip/irq-tegra.c:129:
++		tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+WARNING: line over 80 characters
+#170: FILE: drivers/irqchip/irq-tegra.c:130:
++		tegra_ictlr_info->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+WARNING: line over 80 characters
+#171: FILE: drivers/irqchip/irq-tegra.c:131:
++		tegra_ictlr_info->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+WARNING: line over 80 characters
+#172: FILE: drivers/irqchip/irq-tegra.c:132:
++		tegra_ictlr_info->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+WARNING: line over 80 characters
+#181: FILE: drivers/irqchip/irq-tegra.c:141:
++		writel_relaxed(tegra_ictlr_info->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+WARNING: Missing a blank line after declarations
+#196: FILE: drivers/irqchip/irq-tegra.c:156:
++		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
++		writel_relaxed(tegra_ictlr_info->cpu_iep[i],
+WARNING: line over 80 characters
+#284: FILE: drivers/irqchip/irq-tegra.c:244:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+CHECK: Please don't use multiple blank lines
+#287: FILE: drivers/irqchip/irq-tegra.c:247:
++
++
+WARNING: Missing a blank line after declarations
+#296: FILE: drivers/irqchip/irq-tegra.c:256:
++		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
++		irq_domain_reset_irq_data(d);
`
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 05/21] DT: tegra: add binding for the legacy interrupt controller
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 15:12     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:12 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  .../interrupt-controller/nvidia,tegra-ictlr.txt    | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> new file mode 100644
> index 0000000..44fd873
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> @@ -0,0 +1,39 @@
> +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
> +refered to as "ictlr", hence the name of the binding.
> +
> +The HW block exposes a number of frames, each implementing a set of 32
> +interrupts.
> +
> +Reguired properties:
> +
> +- compatible : should contain at least "nvidia,tegra-ictlr".

perhaps list the specific versions here..?

+WARNING: DT compatible string "nvidia,tegra114-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#39: FILE: arch/arm/boot/dts/tegra114.dtsi:141:
++		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#39: FILE: arch/arm/boot/dts/tegra114.dtsi:141:
++		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra124-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#84: FILE: arch/arm/boot/dts/tegra124.dtsi:195:
++		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#84: FILE: arch/arm/boot/dts/tegra124.dtsi:195:
++		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra20-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#139: FILE: arch/arm/boot/dts/tegra20.dtsi:171:
++		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#139: FILE: arch/arm/boot/dts/tegra20.dtsi:171:
++		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra30-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#186: FILE: arch/arm/boot/dts/tegra30.dtsi:256:
++		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#186: FILE: arch/arm/boot/dts/tegra30.dtsi:256:
++		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
> +- reg : Specifies base physical address and size of the registers.
> +  Each frame must be described separately.
> +- 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 explicitely forbiden.
> +
> +Example:
> +
> +	ictlr: interrupt-controller@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>;
> +	};
> -- 
> 2.1.4

Might be good to have this patch before patch #3, since the binding
defined here is implemented in #3 and used in #4. also:

+WARNING: 'refered' may be misspelled - perhaps 'referred'?
+#23: FILE: Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt:5:
++refered to as "ictlr", hence the name of the binding.
+WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
+#44: FILE: Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt:26:
++  are explicitely forbiden.
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 05/21] DT: tegra: add binding for the legacy interrupt controller
@ 2015-01-08 15:12     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  .../interrupt-controller/nvidia,tegra-ictlr.txt    | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> new file mode 100644
> index 0000000..44fd873
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
> @@ -0,0 +1,39 @@
> +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
> +refered to as "ictlr", hence the name of the binding.
> +
> +The HW block exposes a number of frames, each implementing a set of 32
> +interrupts.
> +
> +Reguired properties:
> +
> +- compatible : should contain at least "nvidia,tegra-ictlr".

perhaps list the specific versions here..?

+WARNING: DT compatible string "nvidia,tegra114-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#39: FILE: arch/arm/boot/dts/tegra114.dtsi:141:
++		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#39: FILE: arch/arm/boot/dts/tegra114.dtsi:141:
++		compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra124-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#84: FILE: arch/arm/boot/dts/tegra124.dtsi:195:
++		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#84: FILE: arch/arm/boot/dts/tegra124.dtsi:195:
++		compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra20-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#139: FILE: arch/arm/boot/dts/tegra20.dtsi:171:
++		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#139: FILE: arch/arm/boot/dts/tegra20.dtsi:171:
++		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra30-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#186: FILE: arch/arm/boot/dts/tegra30.dtsi:256:
++		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
+WARNING: DT compatible string "nvidia,tegra-ictlr" appears un-documented -- check ./Documentation/devicetree/bindings/
+#186: FILE: arch/arm/boot/dts/tegra30.dtsi:256:
++		compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
> +- reg : Specifies base physical address and size of the registers.
> +  Each frame must be described separately.
> +- 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 explicitely forbiden.
> +
> +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>;
> +	};
> -- 
> 2.1.4

Might be good to have this patch before patch #3, since the binding
defined here is implemented in #3 and used in #4. also:

+WARNING: 'refered' may be misspelled - perhaps 'referred'?
+#23: FILE: Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt:5:
++refered to as "ictlr", hence the name of the binding.
+WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
+#44: FILE: Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt:26:
++  are explicitely forbiden.
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 15:15     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:15 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> This proves to be usefull with stacked domains, when the current
			^^ useful ?
minor:
+WARNING: 'usefull' may be misspelled - perhaps 'useful'?
+#6: 
+This proves to be usefull with stacked domains, when the current
+CHECK: extern prototypes should be avoided in .h files
+#23: FILE: include/linux/irq.h:463:
++extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent
@ 2015-01-08 15:15     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> This proves to be usefull with stacked domains, when the current
			^^ useful ?
minor:
+WARNING: 'usefull' may be misspelled - perhaps 'useful'?
+#6: 
+This proves to be usefull with stacked domains, when the current
+CHECK: extern prototypes should be avoided in .h files
+#23: FILE: include/linux/irq.h:463:
++extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 15:20     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:20 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
a few more minor comments follow:

[..]
> --- a/drivers/irqchip/irq-crossbar.c
> +++ b/drivers/irqchip/irq-crossbar.c
[..]
> @@ -33,6 +34,7 @@
>   * @write: register write function pointer
>   */
>  struct crossbar_device {
> +	raw_spinlock_t lock;

^^ kernel doc missing.

[...]
> +static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
> +				 unsigned int nr_irqs, void *data)
>  {
> -	if (needs_crossbar_write(hw))
> -		cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
> +	struct of_phandle_args *args = data;
> +	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 + nr_irqs) > cb->max_crossbar_sources)
> +		return -EINVAL;	/* Can't deal with this */
> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		int err = allocate_gic_irq(d, virq + i, hwirq + i);

^^ add a blank line here?

> +		if (err)
> +			return err;
> +
> +		irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i,
> +					      &crossbar_chip, NULL);
> +	}
>  
>  	return 0;
>  }
>  
>  /**
> - * crossbar_domain_unmap - unmap a crossbar<->irq connection
> + * crossbar_domain_free - unmap/free a crossbar<->irq connection
>   * @d: domain of irq to unmap

      ^^ should be @domain?

> - * @irq: virq number
> + * @virq: virq number
> + * @nr_irqs: number of irqs to free
>   *
>   * We do not maintain a use count of total number of map/unmap
>   * calls for a particular irq to find out if a irq can be really
> @@ -117,14 +144,19 @@ static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
>   * after which irq is anyways unusable. So an explicit map has to be called
>   * after that.
>   */
> -static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
> +static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
> +				 unsigned int nr_irqs)
>  {
> -	irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
> +	int i;
>  
> -	if (needs_crossbar_write(hw)) {
> -		cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
> -		cb->write(hw - GIC_IRQ_START, cb->safe_map);
> +	raw_spin_lock(&cb->lock);
> +	for (i = 0; i < nr_irqs; i++) {
> +		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);

^^ Add a blank line here.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
@ 2015-01-08 15:20     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 15:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
a few more minor comments follow:

[..]
> --- a/drivers/irqchip/irq-crossbar.c
> +++ b/drivers/irqchip/irq-crossbar.c
[..]
> @@ -33,6 +34,7 @@
>   * @write: register write function pointer
>   */
>  struct crossbar_device {
> +	raw_spinlock_t lock;

^^ kernel doc missing.

[...]
> +static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
> +				 unsigned int nr_irqs, void *data)
>  {
> -	if (needs_crossbar_write(hw))
> -		cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);
> +	struct of_phandle_args *args = data;
> +	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 + nr_irqs) > cb->max_crossbar_sources)
> +		return -EINVAL;	/* Can't deal with this */
> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		int err = allocate_gic_irq(d, virq + i, hwirq + i);

^^ add a blank line here?

> +		if (err)
> +			return err;
> +
> +		irq_domain_set_hwirq_and_chip(d, virq + i, hwirq + i,
> +					      &crossbar_chip, NULL);
> +	}
>  
>  	return 0;
>  }
>  
>  /**
> - * crossbar_domain_unmap - unmap a crossbar<->irq connection
> + * crossbar_domain_free - unmap/free a crossbar<->irq connection
>   * @d: domain of irq to unmap

      ^^ should be @domain?

> - * @irq: virq number
> + * @virq: virq number
> + * @nr_irqs: number of irqs to free
>   *
>   * We do not maintain a use count of total number of map/unmap
>   * calls for a particular irq to find out if a irq can be really
> @@ -117,14 +144,19 @@ static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
>   * after which irq is anyways unusable. So an explicit map has to be called
>   * after that.
>   */
> -static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
> +static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
> +				 unsigned int nr_irqs)
>  {
> -	irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;
> +	int i;
>  
> -	if (needs_crossbar_write(hw)) {
> -		cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
> -		cb->write(hw - GIC_IRQ_START, cb->safe_map);
> +	raw_spin_lock(&cb->lock);
> +	for (i = 0; i < nr_irqs; i++) {
> +		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);

^^ Add a blank line here.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 10/21] irqchip: GIC: get rid of routable domain
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 16:13     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:13 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> The only user of the so called "routable domain" functionnality
minor:
s/functionnality/functionality?

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 10/21] irqchip: GIC: get rid of routable domain
@ 2015-01-08 16:13     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> The only user of the so called "routable domain" functionnality
minor:
s/functionnality/functionality?

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 16:44     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:44 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> 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@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
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/boot/dts/am4372.dtsi             |  11 ++-
>  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              |  24 ++++--
>  arch/arm/mach-omap2/omap-wakeupgen.c      | 125 +++++++++++++++++++++++-------
>  arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
>  arch/arm/mach-omap2/omap4-common.c        |   1 -
>  15 files changed, 154 insertions(+), 65 deletions(-)

	we may need the following changes as well:

diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 7eaae4cf9f89..69f2313a49d1 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -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>;
 
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index 53bbfc90b26a..029badefad3d 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -334,7 +334,6 @@
 	tps@24 {
 		compatible = "ti,tps65218";
 		reg = <0x24>;
-		interrupt-parent = <&gic>;
 		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 662261d6b2ca..2d26bc11bad6 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -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>;
 
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index 49edbda68cd5..c2241c2e5d9d 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -335,7 +335,6 @@
 	mcp_rtc: rtc@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";
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index f9c75c782c48..b056156e2a7a 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -893,14 +893,12 @@
 			usbhsohci: ohci@4a064800 {
 				compatible = "ti,ohci-omap3";
 				reg = <0x4a064800 0x400>;
-				interrupt-parent = <&gic>;
 				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			usbhsehci: ehci@4a064c00 {
 				compatible = "ti,ehci-omap";
 				reg = <0x4a064c00 0x400>;
-				interrupt-parent = <&gic>;
 				interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};

Also saw the following checkpatch warnings at this point - but, I
suppose they were pre-existing.

@@ -0,0 +1,26 @@
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#95: FILE: arch/arm/boot/dts/am4372.dtsi:55:
++		compatible = "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap5-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#112: FILE: arch/arm/boot/dts/dra7.dtsi:68:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#112: FILE: arch/arm/boot/dts/dra7.dtsi:68:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: line over 80 characters
+#127: FILE: arch/arm/boot/dts/dra7.dtsi:103:
++				      <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#320: FILE: arch/arm/boot/dts/omap4.dtsi:78:
++		compatible = "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap5-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#416: FILE: arch/arm/boot/dts/omap5.dtsi:103:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#416: FILE: arch/arm/boot/dts/omap5.dtsi:103:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: line over 80 characters
+#600: FILE: arch/arm/mach-omap2/omap-wakeupgen.c:441:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains
@ 2015-01-08 16:44     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> 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
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/boot/dts/am4372.dtsi             |  11 ++-
>  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              |  24 ++++--
>  arch/arm/mach-omap2/omap-wakeupgen.c      | 125 +++++++++++++++++++++++-------
>  arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
>  arch/arm/mach-omap2/omap4-common.c        |   1 -
>  15 files changed, 154 insertions(+), 65 deletions(-)

	we may need the following changes as well:

diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 7eaae4cf9f89..69f2313a49d1 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -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>;
 
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index 53bbfc90b26a..029badefad3d 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -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>;
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 662261d6b2ca..2d26bc11bad6 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -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>;
 
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index 49edbda68cd5..c2241c2e5d9d 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -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";
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index f9c75c782c48..b056156e2a7a 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -893,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>;
 			};
 		};

Also saw the following checkpatch warnings at this point - but, I
suppose they were pre-existing.

@@ -0,0 +1,26 @@
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#95: FILE: arch/arm/boot/dts/am4372.dtsi:55:
++		compatible = "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap5-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#112: FILE: arch/arm/boot/dts/dra7.dtsi:68:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#112: FILE: arch/arm/boot/dts/dra7.dtsi:68:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: line over 80 characters
+#127: FILE: arch/arm/boot/dts/dra7.dtsi:103:
++				      <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#320: FILE: arch/arm/boot/dts/omap4.dtsi:78:
++		compatible = "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap5-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#416: FILE: arch/arm/boot/dts/omap5.dtsi:103:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: DT compatible string "ti,omap4-wugen-mpu" appears un-documented -- check ./Documentation/devicetree/bindings/
+#416: FILE: arch/arm/boot/dts/omap5.dtsi:103:
++		compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+WARNING: line over 80 characters
+#600: FILE: arch/arm/mach-omap2/omap-wakeupgen.c:441:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
-- 
Regards,
Nishanth Menon

^ permalink raw reply related	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up generator
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 16:52     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:52 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Thomas Gleixner, Shawn Guo, linux-arm-kernel, Jason Cooper

On 17:42-20150107, Marc Zyngier wrote:
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  .../interrupt-controller/ti,omap4-wugen-mpu        | 32 ++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
> new file mode 100644
> index 0000000..16149d9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
> @@ -0,0 +1,32 @@
> +TI OMAP4 Wake-up Generator
> +
> +All TI OMAP4/5 (and their derivatives) an interrupt controllerthat
controller that
> +routes interrupts to the GIC, and also serves as a wakeup source. It
> +is also refered to as "WUGEN-MPU", hence the name of the binding.
> +
> +Reguired properties:
> +
> +- compatible : should contain at least "ti,omap4-wugen-mpu"
Could we also document ti,omap5-wugen-mpu. In addition, if you could
make this patch prior to patch #12, it helps the checkpatch at the very
least ;)

also saw a few checkpatch warnings:
+WARNING: 'refered' may be misspelled - perhaps 'referred'?
+#22: FILE: Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:5:
++is also refered to as "WUGEN-MPU", hence the name of the binding.
+WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
+#39: FILE: Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:22:
++  are explicitely forbiden.

> +- 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 ictlr as an interrupt parent. SGIs and PPIs

I think you mean interrupt controller and not nvidia ictlr here.. :)

> +  are explicitely forbiden.
> +
> +Example:
> +
> +       wakeupgen: interrupt-controller@48281000 {
> +               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
> +               interrupt-controller;
> +               #interrupt-cells = <3>;
> +               reg = <0x48281000 0x1000>;
> +               interrupt-parent = <&gic>;
> +       };
> -- 
> 2.1.4
> 

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up generator
@ 2015-01-08 16:52     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  .../interrupt-controller/ti,omap4-wugen-mpu        | 32 ++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
> new file mode 100644
> index 0000000..16149d9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
> @@ -0,0 +1,32 @@
> +TI OMAP4 Wake-up Generator
> +
> +All TI OMAP4/5 (and their derivatives) an interrupt controllerthat
controller that
> +routes interrupts to the GIC, and also serves as a wakeup source. It
> +is also refered to as "WUGEN-MPU", hence the name of the binding.
> +
> +Reguired properties:
> +
> +- compatible : should contain at least "ti,omap4-wugen-mpu"
Could we also document ti,omap5-wugen-mpu. In addition, if you could
make this patch prior to patch #12, it helps the checkpatch at the very
least ;)

also saw a few checkpatch warnings:
+WARNING: 'refered' may be misspelled - perhaps 'referred'?
+#22: FILE: Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:5:
++is also refered to as "WUGEN-MPU", hence the name of the binding.
+WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
+#39: FILE: Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:22:
++  are explicitely forbiden.

> +- 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 ictlr as an interrupt parent. SGIs and PPIs

I think you mean interrupt controller and not nvidia ictlr here.. :)

> +  are explicitely 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>;
> +       };
> -- 
> 2.1.4
> 

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 16:57     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:57 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> 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.
> 
minor checkpatch warnings below:

@@ -0,0 +1,14 @@
+CHECK: Alignment should match open parenthesis
+#249: FILE: arch/arm/mach-imx/gpc.c:158:
++static int imx_gpc_domain_alloc(struct irq_domain *domain,
++				  unsigned int virq,
+WARNING: line over 80 characters
+#272: FILE: arch/arm/mach-imx/gpc.c:181:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+ERROR: code indent should use tabs where possible
+#305: FILE: arch/arm/mach-imx/gpc.c:209:
++^I        return -ENOMEM;$
+NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or
+      scripts/cleanfile
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
@ 2015-01-08 16:57     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> 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.
> 
minor checkpatch warnings below:

@@ -0,0 +1,14 @@
+CHECK: Alignment should match open parenthesis
+#249: FILE: arch/arm/mach-imx/gpc.c:158:
++static int imx_gpc_domain_alloc(struct irq_domain *domain,
++				  unsigned int virq,
+WARNING: line over 80 characters
+#272: FILE: arch/arm/mach-imx/gpc.c:181:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+ERROR: code indent should use tabs where possible
+#305: FILE: arch/arm/mach-imx/gpc.c:209:
++^I        return -ENOMEM;$
+NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or
+      scripts/cleanfile
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 15/21] ARM: exynos4/5: convert pmu wakeup to stacked domains
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-08 16:58     ` Nishanth Menon
  -1 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:58 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Santosh Shilimkar, Shawn Guo,
	Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 17:42-20150107, Marc Zyngier wrote:
> 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.
> 

minor checkpatch warnings:

+WARNING: line over 80 characters
+#230: FILE: arch/arm/mach-exynos/suspend.c:208:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+WARNING: line over 80 characters
+#274: FILE: arch/arm/mach-exynos/suspend.c:252:
++#define EXYNOS_PMU_IRQ(symbol,name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+ERROR: space required after that ',' (ctx:VxV)
+#274: FILE: arch/arm/mach-exynos/suspend.c:252:
++#define EXYNOS_PMU_IRQ(symbol,name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+                              ^
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 15/21] ARM: exynos4/5: convert pmu wakeup to stacked domains
@ 2015-01-08 16:58     ` Nishanth Menon
  0 siblings, 0 replies; 106+ messages in thread
From: Nishanth Menon @ 2015-01-08 16:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 17:42-20150107, Marc Zyngier wrote:
> 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.
> 

minor checkpatch warnings:

+WARNING: line over 80 characters
+#230: FILE: arch/arm/mach-exynos/suspend.c:208:
++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+WARNING: line over 80 characters
+#274: FILE: arch/arm/mach-exynos/suspend.c:252:
++#define EXYNOS_PMU_IRQ(symbol,name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+ERROR: space required after that ',' (ctx:VxV)
+#274: FILE: arch/arm/mach-exynos/suspend.c:252:
++#define EXYNOS_PMU_IRQ(symbol,name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+                              ^
-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
  2015-01-07 17:42   ` Marc Zyngier
@ 2015-01-09 17:40     ` Stefan Agner
  -1 siblings, 0 replies; 106+ messages in thread
From: Stefan Agner @ 2015-01-09 17:40 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-omap, linux-samsung-soc,
	linux-arm-kernel

Hi Marc,

On 2015-01-07 18:42, Marc Zyngier wrote:
> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
>  arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
>  arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
>  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, 116 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> index 4fc03b7..c16d428 100644
> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> @@ -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@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,10 @@
>  			gpc: gpc@020dc000 {
>  				compatible = "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
> +				interrupt-controller;

#interrupt-cells = <3>; is missing here.

I tested the patchset on a Colibri iMX6, but the module stopped booting
at some point. No error, no warn, but it looked like IRQ's are not
working:

[    1.623939] platform sound: Driver imx-sgtl5000 requests probe
deferral
[    1.630677] backlight supply power not found, using dummy regulator
[    1.637067] pwm-backlight backlight: unable to request PWM, trying
legacy API
[    1.644271] pwm-backlight backlight: unable to request legacy PWM
[    1.650534] platform backlight: Driver pwm-backlight requests probe
deferral
[    1.658080] platform 2028000.ssi: Driver fsl-ssi-dai requests probe
deferral
[    1.665441] fec 2188000.ethernet eth0: Freescale FEC PHY driver
[Micrel KSZ8041] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
[    1.677157] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[freeze]

I figured out that the GPC code did not get called. After digging
through the parsing code, I found the reason: irq_find_host always opted
to intc because this was missing... So, interrupt-cells mandatory for
all interrupt-controller? Maybe we could add a warn somewhere..?

With that in place, it worked fine:

Tested-by: Stefan Agner <stefan@agner.ch>

>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
>  					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-parent = <&intc>;
>  			};
>  
>  			gpr: iomuxc-gpr@020e0000 {
> diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
> index 36ab8e0..35099b7 100644
> --- a/arch/arm/boot/dts/imx6sl.dtsi
> +++ b/arch/arm/boot/dts/imx6sl.dtsi
> @@ -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@00900000 {
> @@ -603,7 +604,9 @@
>  			gpc: gpc@020dc000 {
>  				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
> +				interrupt-controller;
>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-parent = <&intc>;
>  			};
>  
>  			gpr: iomuxc-gpr@020e0000 {
> diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
> index 7a24fee..c476e67 100644
> --- a/arch/arm/boot/dts/imx6sx.dtsi
> +++ b/arch/arm/boot/dts/imx6sx.dtsi
> @@ -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,9 @@
>  			gpc: gpc@020dc000 {
>  				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
> +				interrupt-controller;
>  				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-parent = <&intc>;
>  			};
>  
>  			iomuxc: iomuxc@020e0000 {
> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
> index cfcdb62..7052302 100644
> --- a/arch/arm/mach-imx/common.h
> +++ b/arch/arm/mach-imx/common.h
> @@ -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);
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index 5f3602e..240109b 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -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);
> +}

This two function end up very small, can't we just alter
imx_gpc_hwirq_unmask to use struct irq_data directly?

Code looks fine to me:

Acked-by: Stefan Agner <stefan@agner.ch>

> +
> +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 virq,
> +				  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, virq + i, hwirq + i,
> +					      &imx_gpc_chip, NULL);
> +
> +	parent_args = *args;
> +	parent_args.np = domain->parent->of_node;
> +	return irq_domain_alloc_irqs_parent(domain, virq, 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;
> -	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);
> diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
> index 5057d61..bbe6ff8 100644
> --- a/arch/arm/mach-imx/mach-imx6q.c
> +++ b/arch/arm/mach-imx/mach-imx6q.c
> @@ -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();
>  }
>  
> diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
> index 24bfaaf..d39c274 100644
> --- a/arch/arm/mach-imx/mach-imx6sl.c
> +++ b/arch/arm/mach-imx/mach-imx6sl.c
> @@ -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();
>  }
>  
> diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
> index 7a96c65..72fa22d 100644
> --- a/arch/arm/mach-imx/mach-imx6sx.c
> +++ b/arch/arm/mach-imx/mach-imx6sx.c
> @@ -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();
>  }


^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
@ 2015-01-09 17:40     ` Stefan Agner
  0 siblings, 0 replies; 106+ messages in thread
From: Stefan Agner @ 2015-01-09 17:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 2015-01-07 18:42, Marc Zyngier wrote:
> 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.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
>  arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
>  arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
>  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, 116 insertions(+), 31 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> index 4fc03b7..c16d428 100644
> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> @@ -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,10 @@
>  			gpc: gpc at 020dc000 {
>  				compatible = "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
> +				interrupt-controller;

#interrupt-cells = <3>; is missing here.

I tested the patchset on a Colibri iMX6, but the module stopped booting
at some point. No error, no warn, but it looked like IRQ's are not
working:

[    1.623939] platform sound: Driver imx-sgtl5000 requests probe
deferral
[    1.630677] backlight supply power not found, using dummy regulator
[    1.637067] pwm-backlight backlight: unable to request PWM, trying
legacy API
[    1.644271] pwm-backlight backlight: unable to request legacy PWM
[    1.650534] platform backlight: Driver pwm-backlight requests probe
deferral
[    1.658080] platform 2028000.ssi: Driver fsl-ssi-dai requests probe
deferral
[    1.665441] fec 2188000.ethernet eth0: Freescale FEC PHY driver
[Micrel KSZ8041] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
[    1.677157] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[freeze]

I figured out that the GPC code did not get called. After digging
through the parsing code, I found the reason: irq_find_host always opted
to intc because this was missing... So, interrupt-cells mandatory for
all interrupt-controller? Maybe we could add a warn somewhere..?

With that in place, it worked fine:

Tested-by: Stefan Agner <stefan@agner.ch>

>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
>  					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-parent = <&intc>;
>  			};
>  
>  			gpr: iomuxc-gpr at 020e0000 {
> diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
> index 36ab8e0..35099b7 100644
> --- a/arch/arm/boot/dts/imx6sl.dtsi
> +++ b/arch/arm/boot/dts/imx6sl.dtsi
> @@ -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,9 @@
>  			gpc: gpc at 020dc000 {
>  				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
> +				interrupt-controller;
>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-parent = <&intc>;
>  			};
>  
>  			gpr: iomuxc-gpr at 020e0000 {
> diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
> index 7a24fee..c476e67 100644
> --- a/arch/arm/boot/dts/imx6sx.dtsi
> +++ b/arch/arm/boot/dts/imx6sx.dtsi
> @@ -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,9 @@
>  			gpc: gpc at 020dc000 {
>  				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
>  				reg = <0x020dc000 0x4000>;
> +				interrupt-controller;
>  				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-parent = <&intc>;
>  			};
>  
>  			iomuxc: iomuxc at 020e0000 {
> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
> index cfcdb62..7052302 100644
> --- a/arch/arm/mach-imx/common.h
> +++ b/arch/arm/mach-imx/common.h
> @@ -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);
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index 5f3602e..240109b 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -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);
> +}

This two function end up very small, can't we just alter
imx_gpc_hwirq_unmask to use struct irq_data directly?

Code looks fine to me:

Acked-by: Stefan Agner <stefan@agner.ch>

> +
> +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 virq,
> +				  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, virq + i, hwirq + i,
> +					      &imx_gpc_chip, NULL);
> +
> +	parent_args = *args;
> +	parent_args.np = domain->parent->of_node;
> +	return irq_domain_alloc_irqs_parent(domain, virq, 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;
> -	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);
> diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
> index 5057d61..bbe6ff8 100644
> --- a/arch/arm/mach-imx/mach-imx6q.c
> +++ b/arch/arm/mach-imx/mach-imx6q.c
> @@ -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();
>  }
>  
> diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
> index 24bfaaf..d39c274 100644
> --- a/arch/arm/mach-imx/mach-imx6sl.c
> +++ b/arch/arm/mach-imx/mach-imx6sl.c
> @@ -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();
>  }
>  
> diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
> index 7a96c65..72fa22d 100644
> --- a/arch/arm/mach-imx/mach-imx6sx.c
> +++ b/arch/arm/mach-imx/mach-imx6sx.c
> @@ -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();
>  }

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
  2015-01-08 15:06     ` Nishanth Menon
@ 2015-01-10 12:28       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:28 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Benoit Cousson,
	Stephen Warren, Tony Lindgren, Linus Walleij, Magnus Damm,
	Michal Simek, Rob Herring, Shawn Guo, linux-samsung-soc,
	Simon Horman, Thierry Reding, Sascha Hauer, Santosh Shilimkar,
	Thomas Gleixner, linux-omap, linux-arm-kernel, Jason Cooper

On 2015-01-08 15:06, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> 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.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>
> Saw a few checkpatch warnings as below: all of them seem minors.
>
> @@ -0,0 +1,35 @@
> +WARNING: added, moved or deleted file(s), does MAINTAINERS need 
> updating?

I'll leave to the Tegra maintainers to update this file it they want 
to.

> +#36:
> +new file mode 100644
> +WARNING: line over 80 characters
> +#169: FILE: drivers/irqchip/irq-tegra.c:129:
> ++		tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + 
> ICTLR_CPU_IER);

As a matter of principle, I ignore what checkpatch says about the 
length of lines of code. I trust my eyes more than the tool.

[...]

> +WARNING: Missing a blank line after declarations
> +#196: FILE: drivers/irqchip/irq-tegra.c:156:
> ++		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
> ++		writel_relaxed(tegra_ictlr_info->cpu_iep[i],

Done.

> +WARNING: line over 80 characters
> +#284: FILE: drivers/irqchip/irq-tegra.c:244:
> ++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, 
> &parent_args);
> +CHECK: Please don't use multiple blank lines
> +#287: FILE: drivers/irqchip/irq-tegra.c:247:
> ++
> ++
> +WARNING: Missing a blank line after declarations
> +#296: FILE: drivers/irqchip/irq-tegra.c:256:
> ++		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
> ++		irq_domain_reset_irq_data(d);
> `

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller
@ 2015-01-10 12:28       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 15:06, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> 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.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>
> Saw a few checkpatch warnings as below: all of them seem minors.
>
> @@ -0,0 +1,35 @@
> +WARNING: added, moved or deleted file(s), does MAINTAINERS need 
> updating?

I'll leave to the Tegra maintainers to update this file it they want 
to.

> +#36:
> +new file mode 100644
> +WARNING: line over 80 characters
> +#169: FILE: drivers/irqchip/irq-tegra.c:129:
> ++		tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + 
> ICTLR_CPU_IER);

As a matter of principle, I ignore what checkpatch says about the 
length of lines of code. I trust my eyes more than the tool.

[...]

> +WARNING: Missing a blank line after declarations
> +#196: FILE: drivers/irqchip/irq-tegra.c:156:
> ++		void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
> ++		writel_relaxed(tegra_ictlr_info->cpu_iep[i],

Done.

> +WARNING: line over 80 characters
> +#284: FILE: drivers/irqchip/irq-tegra.c:244:
> ++	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, 
> &parent_args);
> +CHECK: Please don't use multiple blank lines
> +#287: FILE: drivers/irqchip/irq-tegra.c:247:
> ++
> ++
> +WARNING: Missing a blank line after declarations
> +#296: FILE: drivers/irqchip/irq-tegra.c:256:
> ++		struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
> ++		irq_domain_reset_irq_data(d);
> `

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy  interrupt controller
  2015-01-08 10:41     ` Thierry Reding
@ 2015-01-10 12:37       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:37 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Nishanth Menon, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Stephen Warren, Tony Lindgren, Linus Walleij, Magnus Damm,
	Michal Simek, Rob Herring, linux-samsung-soc, linux-omap,
	Simon Horman, Benoit Cousson, Santosh Shilimkar, Mark Rutland,
	Shawn Guo, Thomas Gleixner, linux-arm-kernel, Jason Cooper

On 2015-01-08 10:41, Thierry Reding wrote:
> On Wed, Jan 07, 2015 at 05:42:39PM +0000, Marc Zyngier wrote:
>> Describe the legacy interrupt controller in every tegra DTSI files,
>> and make it the parent of most interrupts.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  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(-)
>>

I've updated the patch to reflect the requested changes. See below for 
the few contentious points:

[...]

>> @@ -134,6 +134,19 @@
>>  		      <0x50046000 0x2000>;
>>  		interrupts = <GIC_PPI 9
>>  			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>> +		interrupt-parent = <&gic>;
>
> Is this allowed? It makes the GIC its own parent. I guess we need it 
> to
> stop a loop from GIC -> LIC -> GIC, but it doesn't look quite right.

This seems to be the expected construct to override a parent interrupt 
controller. Actually, this is already what happens when you have a 
single interrupt-controller and a global interrupt-parent property.

[...]

>>  	timer@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>;
>
> Why does this get to have a non-default parent?

The per-cpu timers are using PPIs.  As such,. they are not routed 
through the LIC, but are wired to the GIC instead.

[...]

>>  	timer@60005000 {
>>  		compatible = "nvidia,tegra20-timer";
>>  		reg = <0x60005000 0x60>;
>
> Why doesn't the Tegra timer get to keep the GIC as parent like for
> Tegra114 and Tegra124? Instead I see that the Cortex-A9 TWD timer 
> gets
> to keep the parent instead.

The Tegra timer is using SPI (and can probably be used as a wake-up 
source). As such, it is connected to the LIC, not to the GIC.

Per-CPU timers (arch timer for A15 and TWD for A9) are all using PPIs, 
and are directly wired to the GIC.

[...]

>>  	timer@60005000 {
>>  		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
>>  		reg = <0x60005000 0x400>;
>
> Like for Tegra20, the Tegra timer is now switched to the LIC as 
> parent.

Which, in my understanding, is the right thing to do. Unless I missed 
something obvious about this?

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy interrupt controller
@ 2015-01-10 12:37       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 10:41, Thierry Reding wrote:
> On Wed, Jan 07, 2015 at 05:42:39PM +0000, Marc Zyngier wrote:
>> Describe the legacy interrupt controller in every tegra DTSI files,
>> and make it the parent of most interrupts.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  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(-)
>>

I've updated the patch to reflect the requested changes. See below for 
the few contentious points:

[...]

>> @@ -134,6 +134,19 @@
>>  		      <0x50046000 0x2000>;
>>  		interrupts = <GIC_PPI 9
>>  			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>> +		interrupt-parent = <&gic>;
>
> Is this allowed? It makes the GIC its own parent. I guess we need it 
> to
> stop a loop from GIC -> LIC -> GIC, but it doesn't look quite right.

This seems to be the expected construct to override a parent interrupt 
controller. Actually, this is already what happens when you have a 
single interrupt-controller and a global interrupt-parent property.

[...]

>>  	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>;
>
> Why does this get to have a non-default parent?

The per-cpu timers are using PPIs.  As such,. they are not routed 
through the LIC, but are wired to the GIC instead.

[...]

>>  	timer at 60005000 {
>>  		compatible = "nvidia,tegra20-timer";
>>  		reg = <0x60005000 0x60>;
>
> Why doesn't the Tegra timer get to keep the GIC as parent like for
> Tegra114 and Tegra124? Instead I see that the Cortex-A9 TWD timer 
> gets
> to keep the parent instead.

The Tegra timer is using SPI (and can probably be used as a wake-up 
source). As such, it is connected to the LIC, not to the GIC.

Per-CPU timers (arch timer for A15 and TWD for A9) are all using PPIs, 
and are directly wired to the GIC.

[...]

>>  	timer at 60005000 {
>>  		compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
>>  		reg = <0x60005000 0x400>;
>
> Like for Tegra20, the Tegra timer is now switched to the LIC as 
> parent.

Which, in my understanding, is the right thing to do. Unless I missed 
something obvious about this?

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 06/21] ARM: tegra: remove old LIC support
  2015-01-08 11:29     ` Thierry Reding
@ 2015-01-10 12:43       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:43 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Nishanth Menon, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Stephen Warren, Tony Lindgren, Linus Walleij, Magnus Damm,
	Michal Simek, Rob Herring, linux-samsung-soc, linux-omap,
	Simon Horman, Benoit Cousson, Santosh Shilimkar, Mark Rutland,
	Shawn Guo, Thomas Gleixner, linux-arm-kernel, Jason Cooper

On 2015-01-08 11:29, Thierry Reding wrote:
> On Wed, Jan 07, 2015 at 05:42:41PM +0000, Marc Zyngier wrote:
> [...]
>> diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
> [...]
>>  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;
>> -
>> -	if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
>> -		WARN(1, "Too many (%d) interrupt controllers found. Maximum is 
>> %d.",
>> -			num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
>> -		num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
>> -	}
>> -
>> -	for (i = 0; i < num_ictlrs; i++) {
>> -		void __iomem *ictlr = ictlr_reg_base[i];
>> -		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
>> -		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
>> -	}
>> -
>> -	gic_arch_extn.irq_ack = tegra_ack;
>> -	gic_arch_extn.irq_eoi = tegra_eoi;
>> -	gic_arch_extn.irq_mask = tegra_mask;
>> -	gic_arch_extn.irq_unmask = tegra_unmask;
>> -	gic_arch_extn.irq_retrigger = tegra_retrigger;
>> -	gic_arch_extn.irq_set_wake = tegra_set_wake;
>> -	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
>> +	if (!of_find_matching_node(NULL, tegra_ictlr_match))
>> +		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
>
> I'm not very happy about the ABI breakage here, but I also realize 
> that
> we need this change to properly describe the hardware. To make it 
> more
> obvious that people really should update their DTBs, maybe turn this
> into a WARN()?

Sure, done.

>> -skip_extn_setup:
>>  	tegra114_gic_cpu_pm_registration();
>
> I'm not intimately familiar with the GIC, but is this really SoC
> specific? Doesn't anybody else need this? Comparing to the GIC spec 
> the
> write of 0x1e0 to the GIC_CPU_CTRL register (which I assume 
> corresponds
> to GICC_CTLR in the spec), this simply disables the IRQ and FIQ 
> bypass
> signals for both group 0 and group 1.

This seems to be a Tegra special, at least in mainline. But yes, I'd 
very much like to be able to remove this from platform code and make it 
part of the GIC driver if we can.

Something for a subsequent patch series, I guess.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 06/21] ARM: tegra: remove old LIC support
@ 2015-01-10 12:43       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 11:29, Thierry Reding wrote:
> On Wed, Jan 07, 2015 at 05:42:41PM +0000, Marc Zyngier wrote:
> [...]
>> diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
> [...]
>>  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;
>> -
>> -	if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
>> -		WARN(1, "Too many (%d) interrupt controllers found. Maximum is 
>> %d.",
>> -			num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
>> -		num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
>> -	}
>> -
>> -	for (i = 0; i < num_ictlrs; i++) {
>> -		void __iomem *ictlr = ictlr_reg_base[i];
>> -		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
>> -		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
>> -	}
>> -
>> -	gic_arch_extn.irq_ack = tegra_ack;
>> -	gic_arch_extn.irq_eoi = tegra_eoi;
>> -	gic_arch_extn.irq_mask = tegra_mask;
>> -	gic_arch_extn.irq_unmask = tegra_unmask;
>> -	gic_arch_extn.irq_retrigger = tegra_retrigger;
>> -	gic_arch_extn.irq_set_wake = tegra_set_wake;
>> -	gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
>> +	if (!of_find_matching_node(NULL, tegra_ictlr_match))
>> +		pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
>
> I'm not very happy about the ABI breakage here, but I also realize 
> that
> we need this change to properly describe the hardware. To make it 
> more
> obvious that people really should update their DTBs, maybe turn this
> into a WARN()?

Sure, done.

>> -skip_extn_setup:
>>  	tegra114_gic_cpu_pm_registration();
>
> I'm not intimately familiar with the GIC, but is this really SoC
> specific? Doesn't anybody else need this? Comparing to the GIC spec 
> the
> write of 0x1e0 to the GIC_CPU_CTRL register (which I assume 
> corresponds
> to GICC_CTLR in the spec), this simply disables the IRQ and FIQ 
> bypass
> signals for both group 0 and group 1.

This seems to be a Tegra special, at least in mainline. But yes, I'd 
very much like to be able to remove this from platform code and make it 
part of the GIC driver if we can.

Something for a subsequent patch series, I guess.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent
  2015-01-08 15:15     ` Nishanth Menon
@ 2015-01-10 12:46       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:46 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Thomas Gleixner, Shawn Guo, linux-arm-kernel, Jason Cooper

On 2015-01-08 15:15, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> This proves to be usefull with stacked domains, when the current
> 			^^ useful ?
> minor:
> +WARNING: 'usefull' may be misspelled - perhaps 'useful'?
> +#6:
> +This proves to be usefull with stacked domains, when the current
> +CHECK: extern prototypes should be avoided in .h files
> +#23: FILE: include/linux/irq.h:463:
> ++extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned
> int on);

Consistency trumps whatever checkpatch says, I'm afraid.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent
@ 2015-01-10 12:46       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 15:15, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> This proves to be usefull with stacked domains, when the current
> 			^^ useful ?
> minor:
> +WARNING: 'usefull' may be misspelled - perhaps 'useful'?
> +#6:
> +This proves to be usefull with stacked domains, when the current
> +CHECK: extern prototypes should be avoided in .h files
> +#23: FILE: include/linux/irq.h:463:
> ++extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned
> int on);

Consistency trumps whatever checkpatch says, I'm afraid.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to  stacked domains
  2015-01-08 14:39     ` Nishanth Menon
@ 2015-01-10 12:59       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:59 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Thomas Gleixner, Shawn Guo, linux-arm-kernel, Jason Cooper

On 2015-01-08 14:39, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
> [..]
>> diff --git a/arch/arm/boot/dts/dra7-evm.dts 
>> b/arch/arm/boot/dts/dra7-evm.dts
>> index 10b725c..048cfeb 100644
>> --- a/arch/arm/boot/dts/dra7-evm.dts
>> +++ b/arch/arm/boot/dts/dra7-evm.dts
>> @@ -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>;
> ^^ interrrupt-extended for uart1 here
> [..]
>
>> diff --git a/arch/arm/boot/dts/dra7.dtsi 
>> b/arch/arm/boot/dts/dra7.dtsi
> [...]
>> @@ -344,7 +344,7 @@
>>  		uart1: serial@4806a000 {
>>  			compatible = "ti,omap4-uart";
>>  			reg = <0x4806a000 0x100>;
>> -			interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
>> +			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
> ^^ implies we will have both interrupts and interrupts-extended
> properties for uart1 in dra7-evm.dtb
>
> Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> does not make it clear as to what the priority will be when both
> properties are present.

Yup, good call. I don't think it matters (interrupts inherits the 
implicit irq-parent, but consistency is good.

> [...]
> Also, for 3.19-rc3, Missing the following causing x15 to fail boot.
>
> diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> index 49edbda68cd5..c2241c2e5d9d 100644
> --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> @@ -335,7 +335,6 @@
>  	mcp_rtc: rtc@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";

Ah, thanks for the patch, I've folded this in.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains
@ 2015-01-10 12:59       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 12:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 14:39, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
> [..]
>> diff --git a/arch/arm/boot/dts/dra7-evm.dts 
>> b/arch/arm/boot/dts/dra7-evm.dts
>> index 10b725c..048cfeb 100644
>> --- a/arch/arm/boot/dts/dra7-evm.dts
>> +++ b/arch/arm/boot/dts/dra7-evm.dts
>> @@ -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>;
> ^^ interrrupt-extended for uart1 here
> [..]
>
>> diff --git a/arch/arm/boot/dts/dra7.dtsi 
>> b/arch/arm/boot/dts/dra7.dtsi
> [...]
>> @@ -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 = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
> ^^ implies we will have both interrupts and interrupts-extended
> properties for uart1 in dra7-evm.dtb
>
> Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
> does not make it clear as to what the priority will be when both
> properties are present.

Yup, good call. I don't think it matters (interrupts inherits the 
implicit irq-parent, but consistency is good.

> [...]
> Also, for 3.19-rc3, Missing the following causing x15 to fail boot.
>
> diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> index 49edbda68cd5..c2241c2e5d9d 100644
> --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> @@ -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";

Ah, thanks for the patch, I've folded this in.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains
  2015-01-08 16:44     ` Nishanth Menon
@ 2015-01-10 13:17       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:17 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Thomas Gleixner, Shawn Guo, linux-arm-kernel, Jason Cooper

On 2015-01-08 16:44, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> 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@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
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/boot/dts/am4372.dtsi             |  11 ++-
>>  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              |  24 ++++--
>>  arch/arm/mach-omap2/omap-wakeupgen.c      | 125 
>> +++++++++++++++++++++++-------
>>  arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
>>  arch/arm/mach-omap2/omap4-common.c        |   1 -
>>  15 files changed, 154 insertions(+), 65 deletions(-)
>
> 	we may need the following changes as well:
>
> diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts
> b/arch/arm/boot/dts/am437x-gp-evm.dts
> index 7eaae4cf9f89..69f2313a49d1 100644
> --- a/arch/arm/boot/dts/am437x-gp-evm.dts
> +++ b/arch/arm/boot/dts/am437x-gp-evm.dts
> @@ -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>;
>
> diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts
> b/arch/arm/boot/dts/am437x-sk-evm.dts
> index 53bbfc90b26a..029badefad3d 100644
> --- a/arch/arm/boot/dts/am437x-sk-evm.dts
> +++ b/arch/arm/boot/dts/am437x-sk-evm.dts
> @@ -334,7 +334,6 @@
>  	tps@24 {
>  		compatible = "ti,tps65218";
>  		reg = <0x24>;
> -		interrupt-parent = <&gic>;
>  		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
>  		interrupt-controller;
>  		#interrupt-cells = <2>;
> diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts
> b/arch/arm/boot/dts/am43x-epos-evm.dts
> index 662261d6b2ca..2d26bc11bad6 100644
> --- a/arch/arm/boot/dts/am43x-epos-evm.dts
> +++ b/arch/arm/boot/dts/am43x-epos-evm.dts
> @@ -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>;
>
> diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> index 49edbda68cd5..c2241c2e5d9d 100644
> --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> @@ -335,7 +335,6 @@
>  	mcp_rtc: rtc@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";
> diff --git a/arch/arm/boot/dts/omap5.dtsi 
> b/arch/arm/boot/dts/omap5.dtsi
> index f9c75c782c48..b056156e2a7a 100644
> --- a/arch/arm/boot/dts/omap5.dtsi
> +++ b/arch/arm/boot/dts/omap5.dtsi
> @@ -893,14 +893,12 @@
>  			usbhsohci: ohci@4a064800 {
>  				compatible = "ti,ohci-omap3";
>  				reg = <0x4a064800 0x400>;
> -				interrupt-parent = <&gic>;
>  				interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
>  			};
>
>  			usbhsehci: ehci@4a064c00 {
>  				compatible = "ti,ehci-omap";
>  				reg = <0x4a064c00 0x400>;
> -				interrupt-parent = <&gic>;
>  				interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
>  			};
>  		};

Applied, thanks.

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains
@ 2015-01-10 13:17       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 16:44, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> 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
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/boot/dts/am4372.dtsi             |  11 ++-
>>  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              |  24 ++++--
>>  arch/arm/mach-omap2/omap-wakeupgen.c      | 125 
>> +++++++++++++++++++++++-------
>>  arch/arm/mach-omap2/omap-wakeupgen.h      |   1 -
>>  arch/arm/mach-omap2/omap4-common.c        |   1 -
>>  15 files changed, 154 insertions(+), 65 deletions(-)
>
> 	we may need the following changes as well:
>
> diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts
> b/arch/arm/boot/dts/am437x-gp-evm.dts
> index 7eaae4cf9f89..69f2313a49d1 100644
> --- a/arch/arm/boot/dts/am437x-gp-evm.dts
> +++ b/arch/arm/boot/dts/am437x-gp-evm.dts
> @@ -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>;
>
> diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts
> b/arch/arm/boot/dts/am437x-sk-evm.dts
> index 53bbfc90b26a..029badefad3d 100644
> --- a/arch/arm/boot/dts/am437x-sk-evm.dts
> +++ b/arch/arm/boot/dts/am437x-sk-evm.dts
> @@ -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>;
> diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts
> b/arch/arm/boot/dts/am43x-epos-evm.dts
> index 662261d6b2ca..2d26bc11bad6 100644
> --- a/arch/arm/boot/dts/am43x-epos-evm.dts
> +++ b/arch/arm/boot/dts/am43x-epos-evm.dts
> @@ -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>;
>
> diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> index 49edbda68cd5..c2241c2e5d9d 100644
> --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
> +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
> @@ -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";
> diff --git a/arch/arm/boot/dts/omap5.dtsi 
> b/arch/arm/boot/dts/omap5.dtsi
> index f9c75c782c48..b056156e2a7a 100644
> --- a/arch/arm/boot/dts/omap5.dtsi
> +++ b/arch/arm/boot/dts/omap5.dtsi
> @@ -893,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>;
>  			};
>  		};

Applied, thanks.

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up  generator
  2015-01-08 16:52     ` Nishanth Menon
@ 2015-01-10 13:22       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:22 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Mark Rutland, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Thomas Gleixner, Shawn Guo, linux-arm-kernel, Jason Cooper

On 2015-01-08 16:52, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  .../interrupt-controller/ti,omap4-wugen-mpu        | 32 
>> ++++++++++++++++++++++
>>  1 file changed, 32 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu 
>> b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
>> new file mode 100644
>> index 0000000..16149d9
>> --- /dev/null
>> +++ 
>> b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
>> @@ -0,0 +1,32 @@
>> +TI OMAP4 Wake-up Generator
>> +
>> +All TI OMAP4/5 (and their derivatives) an interrupt controllerthat
> controller that
>> +routes interrupts to the GIC, and also serves as a wakeup source. 
>> It
>> +is also refered to as "WUGEN-MPU", hence the name of the binding.
>> +
>> +Reguired properties:
>> +
>> +- compatible : should contain at least "ti,omap4-wugen-mpu"
> Could we also document ti,omap5-wugen-mpu. In addition, if you could
> make this patch prior to patch #12, it helps the checkpatch at the 
> very
> least ;)

Sure.

> also saw a few checkpatch warnings:
> +WARNING: 'refered' may be misspelled - perhaps 'referred'?
> +#22: FILE:
> 
> Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:5:
> ++is also refered to as "WUGEN-MPU", hence the name of the binding.
> +WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
> +#39: FILE:
> 
> Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:22:
> ++  are explicitely forbiden.
>
>> +- 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 ictlr as an interrupt parent. SGIs and PPIs
>
> I think you mean interrupt controller and not nvidia ictlr here.. :)

-ECOPYPASTE... ;-)

Thanks,

          M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up generator
@ 2015-01-10 13:22       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-08 16:52, Nishanth Menon wrote:
> On 17:42-20150107, Marc Zyngier wrote:
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  .../interrupt-controller/ti,omap4-wugen-mpu        | 32 
>> ++++++++++++++++++++++
>>  1 file changed, 32 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu 
>> b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
>> new file mode 100644
>> index 0000000..16149d9
>> --- /dev/null
>> +++ 
>> b/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
>> @@ -0,0 +1,32 @@
>> +TI OMAP4 Wake-up Generator
>> +
>> +All TI OMAP4/5 (and their derivatives) an interrupt controllerthat
> controller that
>> +routes interrupts to the GIC, and also serves as a wakeup source. 
>> It
>> +is also refered to as "WUGEN-MPU", hence the name of the binding.
>> +
>> +Reguired properties:
>> +
>> +- compatible : should contain at least "ti,omap4-wugen-mpu"
> Could we also document ti,omap5-wugen-mpu. In addition, if you could
> make this patch prior to patch #12, it helps the checkpatch at the 
> very
> least ;)

Sure.

> also saw a few checkpatch warnings:
> +WARNING: 'refered' may be misspelled - perhaps 'referred'?
> +#22: FILE:
> 
> Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:5:
> ++is also refered to as "WUGEN-MPU", hence the name of the binding.
> +WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
> +#39: FILE:
> 
> Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu:22:
> ++  are explicitely forbiden.
>
>> +- 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 ictlr as an interrupt parent. SGIs and PPIs
>
> I think you mean interrupt controller and not nvidia ictlr here.. :)

-ECOPYPASTE... ;-)

Thanks,

          M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
  2015-01-09 17:40     ` Stefan Agner
@ 2015-01-10 13:34       ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:34 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Nishanth Menon, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Mark Rutland, Shawn Guo, Thomas Gleixner, linux-arm-kernel,
	Jason Cooper

On 2015-01-09 17:40, Stefan Agner wrote:
> Hi Marc,
>
> On 2015-01-07 18:42, Marc Zyngier wrote:
>> 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.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
>>  arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
>>  arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
>>  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, 116 insertions(+), 31 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi 
>> b/arch/arm/boot/dts/imx6qdl.dtsi
>> index 4fc03b7..c16d428 100644
>> --- a/arch/arm/boot/dts/imx6qdl.dtsi
>> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
>> @@ -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@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,10 @@
>>  			gpc: gpc@020dc000 {
>>  				compatible = "fsl,imx6q-gpc";
>>  				reg = <0x020dc000 0x4000>;
>> +				interrupt-controller;
>
> #interrupt-cells = <3>; is missing here.

Ah, nice catch!

> I tested the patchset on a Colibri iMX6, but the module stopped 
> booting
> at some point. No error, no warn, but it looked like IRQ's are not
> working:
>
> [    1.623939] platform sound: Driver imx-sgtl5000 requests probe
> deferral
> [    1.630677] backlight supply power not found, using dummy 
> regulator
> [    1.637067] pwm-backlight backlight: unable to request PWM, trying
> legacy API
> [    1.644271] pwm-backlight backlight: unable to request legacy PWM
> [    1.650534] platform backlight: Driver pwm-backlight requests 
> probe
> deferral
> [    1.658080] platform 2028000.ssi: Driver fsl-ssi-dai requests 
> probe
> deferral
> [    1.665441] fec 2188000.ethernet eth0: Freescale FEC PHY driver
> [Micrel KSZ8041] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
> [    1.677157] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
> [freeze]
>
> I figured out that the GPC code did not get called. After digging
> through the parsing code, I found the reason: irq_find_host always 
> opted
> to intc because this was missing... So, interrupt-cells mandatory for
> all interrupt-controller? Maybe we could add a warn somewhere..?

interrupt-cells has a default of 1, I believe. I suppose I could add a 
WARN_ON in the xlate/alloc functions...

> With that in place, it worked fine:
>
> Tested-by: Stefan Agner <stefan@agner.ch>

Thanks!

>
>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
>>  					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
>> +				interrupt-parent = <&intc>;
>>  			};
>>
>>  			gpr: iomuxc-gpr@020e0000 {
>> diff --git a/arch/arm/boot/dts/imx6sl.dtsi 
>> b/arch/arm/boot/dts/imx6sl.dtsi
>> index 36ab8e0..35099b7 100644
>> --- a/arch/arm/boot/dts/imx6sl.dtsi
>> +++ b/arch/arm/boot/dts/imx6sl.dtsi
>> @@ -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@00900000 {
>> @@ -603,7 +604,9 @@
>>  			gpc: gpc@020dc000 {
>>  				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
>>  				reg = <0x020dc000 0x4000>;
>> +				interrupt-controller;
>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
>> +				interrupt-parent = <&intc>;
>>  			};
>>
>>  			gpr: iomuxc-gpr@020e0000 {
>> diff --git a/arch/arm/boot/dts/imx6sx.dtsi 
>> b/arch/arm/boot/dts/imx6sx.dtsi
>> index 7a24fee..c476e67 100644
>> --- a/arch/arm/boot/dts/imx6sx.dtsi
>> +++ b/arch/arm/boot/dts/imx6sx.dtsi
>> @@ -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,9 @@
>>  			gpc: gpc@020dc000 {
>>  				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
>>  				reg = <0x020dc000 0x4000>;
>> +				interrupt-controller;
>>  				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>> +				interrupt-parent = <&intc>;
>>  			};
>>
>>  			iomuxc: iomuxc@020e0000 {
>> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
>> index cfcdb62..7052302 100644
>> --- a/arch/arm/mach-imx/common.h
>> +++ b/arch/arm/mach-imx/common.h
>> @@ -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);
>> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
>> index 5f3602e..240109b 100644
>> --- a/arch/arm/mach-imx/gpc.c
>> +++ b/arch/arm/mach-imx/gpc.c
>> @@ -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);
>> +}
>
> This two function end up very small, can't we just alter
> imx_gpc_hwirq_unmask to use struct irq_data directly?

Unfortunately, pm-imx6.c directly uses the HW irq number.

> Code looks fine to me:
>
> Acked-by: Stefan Agner <stefan@agner.ch>

Thanks again,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
@ 2015-01-10 13:34       ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-09 17:40, Stefan Agner wrote:
> Hi Marc,
>
> On 2015-01-07 18:42, Marc Zyngier wrote:
>> 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.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
>>  arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
>>  arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
>>  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, 116 insertions(+), 31 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi 
>> b/arch/arm/boot/dts/imx6qdl.dtsi
>> index 4fc03b7..c16d428 100644
>> --- a/arch/arm/boot/dts/imx6qdl.dtsi
>> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
>> @@ -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,10 @@
>>  			gpc: gpc at 020dc000 {
>>  				compatible = "fsl,imx6q-gpc";
>>  				reg = <0x020dc000 0x4000>;
>> +				interrupt-controller;
>
> #interrupt-cells = <3>; is missing here.

Ah, nice catch!

> I tested the patchset on a Colibri iMX6, but the module stopped 
> booting
> at some point. No error, no warn, but it looked like IRQ's are not
> working:
>
> [    1.623939] platform sound: Driver imx-sgtl5000 requests probe
> deferral
> [    1.630677] backlight supply power not found, using dummy 
> regulator
> [    1.637067] pwm-backlight backlight: unable to request PWM, trying
> legacy API
> [    1.644271] pwm-backlight backlight: unable to request legacy PWM
> [    1.650534] platform backlight: Driver pwm-backlight requests 
> probe
> deferral
> [    1.658080] platform 2028000.ssi: Driver fsl-ssi-dai requests 
> probe
> deferral
> [    1.665441] fec 2188000.ethernet eth0: Freescale FEC PHY driver
> [Micrel KSZ8041] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
> [    1.677157] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
> [freeze]
>
> I figured out that the GPC code did not get called. After digging
> through the parsing code, I found the reason: irq_find_host always 
> opted
> to intc because this was missing... So, interrupt-cells mandatory for
> all interrupt-controller? Maybe we could add a warn somewhere..?

interrupt-cells has a default of 1, I believe. I suppose I could add a 
WARN_ON in the xlate/alloc functions...

> With that in place, it worked fine:
>
> Tested-by: Stefan Agner <stefan@agner.ch>

Thanks!

>
>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
>>  					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
>> +				interrupt-parent = <&intc>;
>>  			};
>>
>>  			gpr: iomuxc-gpr at 020e0000 {
>> diff --git a/arch/arm/boot/dts/imx6sl.dtsi 
>> b/arch/arm/boot/dts/imx6sl.dtsi
>> index 36ab8e0..35099b7 100644
>> --- a/arch/arm/boot/dts/imx6sl.dtsi
>> +++ b/arch/arm/boot/dts/imx6sl.dtsi
>> @@ -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,9 @@
>>  			gpc: gpc at 020dc000 {
>>  				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
>>  				reg = <0x020dc000 0x4000>;
>> +				interrupt-controller;
>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
>> +				interrupt-parent = <&intc>;
>>  			};
>>
>>  			gpr: iomuxc-gpr at 020e0000 {
>> diff --git a/arch/arm/boot/dts/imx6sx.dtsi 
>> b/arch/arm/boot/dts/imx6sx.dtsi
>> index 7a24fee..c476e67 100644
>> --- a/arch/arm/boot/dts/imx6sx.dtsi
>> +++ b/arch/arm/boot/dts/imx6sx.dtsi
>> @@ -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,9 @@
>>  			gpc: gpc at 020dc000 {
>>  				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
>>  				reg = <0x020dc000 0x4000>;
>> +				interrupt-controller;
>>  				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>> +				interrupt-parent = <&intc>;
>>  			};
>>
>>  			iomuxc: iomuxc at 020e0000 {
>> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
>> index cfcdb62..7052302 100644
>> --- a/arch/arm/mach-imx/common.h
>> +++ b/arch/arm/mach-imx/common.h
>> @@ -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);
>> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
>> index 5f3602e..240109b 100644
>> --- a/arch/arm/mach-imx/gpc.c
>> +++ b/arch/arm/mach-imx/gpc.c
>> @@ -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);
>> +}
>
> This two function end up very small, can't we just alter
> imx_gpc_hwirq_unmask to use struct irq_data directly?

Unfortunately, pm-imx6.c directly uses the HW irq number.

> Code looks fine to me:
>
> Acked-by: Stefan Agner <stefan@agner.ch>

Thanks again,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-10 13:45   ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:45 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner
  Cc: linux-omap, linux-samsung-soc, linux-arm-kernel

On 2015-01-07 17:42, Marc Zyngier wrote:
> 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 landed in -next, 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 already broke it for the OMAP WUGEN block, we might as well 
> do
>   it again for the TI 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 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.
>
> 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've updated this branch with the changes requested in this review 
cycle. I'll give it a test run on Monday with the platforms I have 
around (mainly Tegra20 and OMAP4/5).

Unless anything major comes up, I'll post v3 with a view of getting 
this into 3.20.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-10 13:45   ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-10 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-07 17:42, Marc Zyngier wrote:
> 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 landed in -next, 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 already broke it for the OMAP WUGEN block, we might as well 
> do
>   it again for the TI 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 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.
>
> 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've updated this branch with the changes requested in this review 
cycle. I'll give it a test run on Monday with the platforms I have 
around (mainly Tegra20 and OMAP4/5).

Unless anything major comes up, I'll post v3 with a view of getting 
this into 3.20.

Thanks,

         M.
-- 
Fast, cheap, reliable. Pick two.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
  2015-01-10 13:34       ` Marc Zyngier
@ 2015-01-10 14:16         ` Stefan Agner
  -1 siblings, 0 replies; 106+ messages in thread
From: Stefan Agner @ 2015-01-10 14:16 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Nishanth Menon, Alexandre Courbot, Kukjin Kim, Sascha Hauer,
	Simon Horman, Stephen Warren, Tony Lindgren, Linus Walleij,
	Magnus Damm, Michal Simek, Rob Herring, linux-samsung-soc,
	linux-omap, Thierry Reding, Benoit Cousson, Santosh Shilimkar,
	Mark Rutland, Shawn Guo, Thomas Gleixner, linux-arm-kernel,
	Jason Cooper

On 2015-01-10 14:34, Marc Zyngier wrote:
> On 2015-01-09 17:40, Stefan Agner wrote:
>> Hi Marc,
>>
>> On 2015-01-07 18:42, Marc Zyngier wrote:
>>> 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.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
>>>  arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
>>>  arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
>>>  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, 116 insertions(+), 31 deletions(-)
>>>
>>> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
>>> index 4fc03b7..c16d428 100644
>>> --- a/arch/arm/boot/dts/imx6qdl.dtsi
>>> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
>>> @@ -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@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,10 @@
>>>  			gpc: gpc@020dc000 {
>>>  				compatible = "fsl,imx6q-gpc";
>>>  				reg = <0x020dc000 0x4000>;
>>> +				interrupt-controller;
>>
>> #interrupt-cells = <3>; is missing here.
> 
> Ah, nice catch!
> 
>> I tested the patchset on a Colibri iMX6, but the module stopped booting
>> at some point. No error, no warn, but it looked like IRQ's are not
>> working:
>>
>> [    1.623939] platform sound: Driver imx-sgtl5000 requests probe
>> deferral
>> [    1.630677] backlight supply power not found, using dummy regulator
>> [    1.637067] pwm-backlight backlight: unable to request PWM, trying
>> legacy API
>> [    1.644271] pwm-backlight backlight: unable to request legacy PWM
>> [    1.650534] platform backlight: Driver pwm-backlight requests probe
>> deferral
>> [    1.658080] platform 2028000.ssi: Driver fsl-ssi-dai requests probe
>> deferral
>> [    1.665441] fec 2188000.ethernet eth0: Freescale FEC PHY driver
>> [Micrel KSZ8041] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
>> [    1.677157] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>> [freeze]
>>
>> I figured out that the GPC code did not get called. After digging
>> through the parsing code, I found the reason: irq_find_host always opted
>> to intc because this was missing... So, interrupt-cells mandatory for
>> all interrupt-controller? Maybe we could add a warn somewhere..?
> 
> interrupt-cells has a default of 1, I believe. I suppose I could add a
> WARN_ON in the xlate/alloc functions...
> 

I think the problem was in of_irq_find_parent (of drivers/of/irq.c). In
that while, interrupt-controller without interrupt-cells just get
ignored.

>> With that in place, it worked fine:
>>
>> Tested-by: Stefan Agner <stefan@agner.ch>
> 
> Thanks!
> 
>>
>>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
>>>  					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
>>> +				interrupt-parent = <&intc>;
>>>  			};
>>>
>>>  			gpr: iomuxc-gpr@020e0000 {
>>> diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
>>> index 36ab8e0..35099b7 100644
>>> --- a/arch/arm/boot/dts/imx6sl.dtsi
>>> +++ b/arch/arm/boot/dts/imx6sl.dtsi
>>> @@ -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@00900000 {
>>> @@ -603,7 +604,9 @@
>>>  			gpc: gpc@020dc000 {
>>>  				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
>>>  				reg = <0x020dc000 0x4000>;
>>> +				interrupt-controller;
>>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
>>> +				interrupt-parent = <&intc>;
>>>  			};
>>>
>>>  			gpr: iomuxc-gpr@020e0000 {
>>> diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
>>> index 7a24fee..c476e67 100644
>>> --- a/arch/arm/boot/dts/imx6sx.dtsi
>>> +++ b/arch/arm/boot/dts/imx6sx.dtsi
>>> @@ -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,9 @@
>>>  			gpc: gpc@020dc000 {
>>>  				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
>>>  				reg = <0x020dc000 0x4000>;
>>> +				interrupt-controller;
>>>  				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>>> +				interrupt-parent = <&intc>;
>>>  			};
>>>
>>>  			iomuxc: iomuxc@020e0000 {
>>> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
>>> index cfcdb62..7052302 100644
>>> --- a/arch/arm/mach-imx/common.h
>>> +++ b/arch/arm/mach-imx/common.h
>>> @@ -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);
>>> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
>>> index 5f3602e..240109b 100644
>>> --- a/arch/arm/mach-imx/gpc.c
>>> +++ b/arch/arm/mach-imx/gpc.c
>>> @@ -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);
>>> +}
>>
>> This two function end up very small, can't we just alter
>> imx_gpc_hwirq_unmask to use struct irq_data directly?
> 
> Unfortunately, pm-imx6.c directly uses the HW irq number.
> 

Now I see... 

--
Stefan

>> Code looks fine to me:
>>
>> Acked-by: Stefan Agner <stefan@agner.ch>
> 
> Thanks again,
> 
>         M.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains
@ 2015-01-10 14:16         ` Stefan Agner
  0 siblings, 0 replies; 106+ messages in thread
From: Stefan Agner @ 2015-01-10 14:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-01-10 14:34, Marc Zyngier wrote:
> On 2015-01-09 17:40, Stefan Agner wrote:
>> Hi Marc,
>>
>> On 2015-01-07 18:42, Marc Zyngier wrote:
>>> 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.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  arch/arm/boot/dts/imx6qdl.dtsi  |   6 +-
>>>  arch/arm/boot/dts/imx6sl.dtsi   |   5 +-
>>>  arch/arm/boot/dts/imx6sx.dtsi   |   5 +-
>>>  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, 116 insertions(+), 31 deletions(-)
>>>
>>> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
>>> index 4fc03b7..c16d428 100644
>>> --- a/arch/arm/boot/dts/imx6qdl.dtsi
>>> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
>>> @@ -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,10 @@
>>>  			gpc: gpc at 020dc000 {
>>>  				compatible = "fsl,imx6q-gpc";
>>>  				reg = <0x020dc000 0x4000>;
>>> +				interrupt-controller;
>>
>> #interrupt-cells = <3>; is missing here.
> 
> Ah, nice catch!
> 
>> I tested the patchset on a Colibri iMX6, but the module stopped booting
>> at some point. No error, no warn, but it looked like IRQ's are not
>> working:
>>
>> [    1.623939] platform sound: Driver imx-sgtl5000 requests probe
>> deferral
>> [    1.630677] backlight supply power not found, using dummy regulator
>> [    1.637067] pwm-backlight backlight: unable to request PWM, trying
>> legacy API
>> [    1.644271] pwm-backlight backlight: unable to request legacy PWM
>> [    1.650534] platform backlight: Driver pwm-backlight requests probe
>> deferral
>> [    1.658080] platform 2028000.ssi: Driver fsl-ssi-dai requests probe
>> deferral
>> [    1.665441] fec 2188000.ethernet eth0: Freescale FEC PHY driver
>> [Micrel KSZ8041] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
>> [    1.677157] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>> [freeze]
>>
>> I figured out that the GPC code did not get called. After digging
>> through the parsing code, I found the reason: irq_find_host always opted
>> to intc because this was missing... So, interrupt-cells mandatory for
>> all interrupt-controller? Maybe we could add a warn somewhere..?
> 
> interrupt-cells has a default of 1, I believe. I suppose I could add a
> WARN_ON in the xlate/alloc functions...
> 

I think the problem was in of_irq_find_parent (of drivers/of/irq.c). In
that while, interrupt-controller without interrupt-cells just get
ignored.

>> With that in place, it worked fine:
>>
>> Tested-by: Stefan Agner <stefan@agner.ch>
> 
> Thanks!
> 
>>
>>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
>>>  					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
>>> +				interrupt-parent = <&intc>;
>>>  			};
>>>
>>>  			gpr: iomuxc-gpr at 020e0000 {
>>> diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
>>> index 36ab8e0..35099b7 100644
>>> --- a/arch/arm/boot/dts/imx6sl.dtsi
>>> +++ b/arch/arm/boot/dts/imx6sl.dtsi
>>> @@ -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,9 @@
>>>  			gpc: gpc at 020dc000 {
>>>  				compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
>>>  				reg = <0x020dc000 0x4000>;
>>> +				interrupt-controller;
>>>  				interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
>>> +				interrupt-parent = <&intc>;
>>>  			};
>>>
>>>  			gpr: iomuxc-gpr at 020e0000 {
>>> diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
>>> index 7a24fee..c476e67 100644
>>> --- a/arch/arm/boot/dts/imx6sx.dtsi
>>> +++ b/arch/arm/boot/dts/imx6sx.dtsi
>>> @@ -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,9 @@
>>>  			gpc: gpc at 020dc000 {
>>>  				compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
>>>  				reg = <0x020dc000 0x4000>;
>>> +				interrupt-controller;
>>>  				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
>>> +				interrupt-parent = <&intc>;
>>>  			};
>>>
>>>  			iomuxc: iomuxc at 020e0000 {
>>> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
>>> index cfcdb62..7052302 100644
>>> --- a/arch/arm/mach-imx/common.h
>>> +++ b/arch/arm/mach-imx/common.h
>>> @@ -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);
>>> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
>>> index 5f3602e..240109b 100644
>>> --- a/arch/arm/mach-imx/gpc.c
>>> +++ b/arch/arm/mach-imx/gpc.c
>>> @@ -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);
>>> +}
>>
>> This two function end up very small, can't we just alter
>> imx_gpc_hwirq_unmask to use struct irq_data directly?
> 
> Unfortunately, pm-imx6.c directly uses the HW irq number.
> 

Now I see... 

--
Stefan

>> Code looks fine to me:
>>
>> Acked-by: Stefan Agner <stefan@agner.ch>
> 
> Thanks again,
> 
>         M.

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
  2015-01-07 17:42 ` Marc Zyngier
@ 2015-01-12 14:14   ` Rob Herring
  -1 siblings, 0 replies; 106+ messages in thread
From: Rob Herring @ 2015-01-12 14:14 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On Wed, Jan 7, 2015 at 11:42 AM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> 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 landed in -next, the time has
> come for gic_arch_extn to meet the Big Bit Bucket.

[...]

> - 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...

Just to be clear, you need some agreement from the maintainers of
those platforms before doing this. It doesn't appear there is
disagreement, but I don't see any explicit agreement either.

This seems to model the interrupts as chained, but at least for some
cases aren't these auxiliary controllers in parallel to the GIC? In
other words, do the they require configuration for interrupts to work
for the normal non-wakeup use? I'm not sure that the h/w is being
modeled any more accurately if that is the case. However, we don't
really have a way to describe an interrupt line is connected to 2
interrupt parents in DT, so I'm not sure what else you could do here.

Rob

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-12 14:14   ` Rob Herring
  0 siblings, 0 replies; 106+ messages in thread
From: Rob Herring @ 2015-01-12 14:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 7, 2015 at 11:42 AM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> 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 landed in -next, the time has
> come for gic_arch_extn to meet the Big Bit Bucket.

[...]

> - 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...

Just to be clear, you need some agreement from the maintainers of
those platforms before doing this. It doesn't appear there is
disagreement, but I don't see any explicit agreement either.

This seems to model the interrupts as chained, but at least for some
cases aren't these auxiliary controllers in parallel to the GIC? In
other words, do the they require configuration for interrupts to work
for the normal non-wakeup use? I'm not sure that the h/w is being
modeled any more accurately if that is the case. However, we don't
really have a way to describe an interrupt line is connected to 2
interrupt parents in DT, so I'm not sure what else you could do here.

Rob

^ permalink raw reply	[flat|nested] 106+ messages in thread

* Re: [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
  2015-01-12 14:14   ` Rob Herring
@ 2015-01-12 15:39     ` Marc Zyngier
  -1 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-12 15:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: Stephen Warren, Thierry Reding, Alexandre Courbot,
	Benoit Cousson, Tony Lindgren, Nishanth Menon, Santosh Shilimkar,
	Shawn Guo, Sascha Hauer, Kukjin Kim, Simon Horman, Magnus Damm,
	Linus Walleij, Michal Simek, Rob Herring, Mark Rutland,
	Jason Cooper, Thomas Gleixner, linux-arm-kernel,
	linux-samsung-soc, linux-omap

On 12/01/15 14:14, Rob Herring wrote:
> On Wed, Jan 7, 2015 at 11:42 AM, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> 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 landed in -next, the time has
>> come for gic_arch_extn to meet the Big Bit Bucket.
> 
> [...]
> 
>> - 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...
> 
> Just to be clear, you need some agreement from the maintainers of
> those platforms before doing this. It doesn't appear there is
> disagreement, but I don't see any explicit agreement either.

I'm not trying to go behind anyone's back, if that's your concern. I
fully intend to obtain every maintainer's explicit acknowledgement
before removing any feature from the kernel. The warning above is there
to get the maintainers attention on the disrupting effect of this series.

> This seems to model the interrupts as chained, but at least for some
> cases aren't these auxiliary controllers in parallel to the GIC? In

>From looking at the various TRMs, they all look to be chained interrupt
controllers (at least Tegra, OMAP and IMX6 show this). I have not been
able to find a publicly available TRM for any of the Samsung platforms,
so this one could be different (but I really doubt it somehow).

> other words, do the they require configuration for interrupts to work
> for the normal non-wakeup use? I'm not sure that the h/w is being
> modeled any more accurately if that is the case. However, we don't
> really have a way to describe an interrupt line is connected to 2
> interrupt parents in DT, so I'm not sure what else you could do here.

The main problem is that they are not general-purpose interrupt
controllers. They all come first on the interrupt path, and somehow feed
two signals into the GIC: the actual interrupt, and the bypass signal.

None of that is representable in DT. I'm willing to take any idea though.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 106+ messages in thread

* [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly
@ 2015-01-12 15:39     ` Marc Zyngier
  0 siblings, 0 replies; 106+ messages in thread
From: Marc Zyngier @ 2015-01-12 15:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/01/15 14:14, Rob Herring wrote:
> On Wed, Jan 7, 2015 at 11:42 AM, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> 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 landed in -next, the time has
>> come for gic_arch_extn to meet the Big Bit Bucket.
> 
> [...]
> 
>> - 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...
> 
> Just to be clear, you need some agreement from the maintainers of
> those platforms before doing this. It doesn't appear there is
> disagreement, but I don't see any explicit agreement either.

I'm not trying to go behind anyone's back, if that's your concern. I
fully intend to obtain every maintainer's explicit acknowledgement
before removing any feature from the kernel. The warning above is there
to get the maintainers attention on the disrupting effect of this series.

> This seems to model the interrupts as chained, but at least for some
> cases aren't these auxiliary controllers in parallel to the GIC? In

>From looking at the various TRMs, they all look to be chained interrupt
controllers (at least Tegra, OMAP and IMX6 show this). I have not been
able to find a publicly available TRM for any of the Samsung platforms,
so this one could be different (but I really doubt it somehow).

> other words, do the they require configuration for interrupts to work
> for the normal non-wakeup use? I'm not sure that the h/w is being
> modeled any more accurately if that is the case. However, we don't
> really have a way to describe an interrupt line is connected to 2
> interrupt parents in DT, so I'm not sure what else you could do here.

The main problem is that they are not general-purpose interrupt
controllers. They all come first on the interrupt path, and somehow feed
two signals into the GIC: the actual interrupt, and the bypass signal.

None of that is representable in DT. I'm willing to take any idea though.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 106+ messages in thread

end of thread, other threads:[~2015-01-12 15:39 UTC | newest]

Thread overview: 106+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-07 17:42 [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly Marc Zyngier
2015-01-07 17:42 ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 01/21] ARM: tegra: irq: nuke leftovers from non-DT support Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08  8:56   ` Thierry Reding
2015-01-08  8:56     ` Thierry Reding
2015-01-07 17:42 ` [PATCH v2 02/21] irqchip: tegra: add DT-based support for legacy interrupt controller Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 10:13   ` Thierry Reding
2015-01-08 10:13     ` Thierry Reding
2015-01-08 15:06   ` Nishanth Menon
2015-01-08 15:06     ` Nishanth Menon
2015-01-10 12:28     ` Marc Zyngier
2015-01-10 12:28       ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 03/21] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 10:16   ` Thierry Reding
2015-01-08 10:16     ` Thierry Reding
2015-01-07 17:42 ` [PATCH v2 04/21] ARM: tegra: update DTs to expose legacy interrupt controller Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 10:41   ` Thierry Reding
2015-01-08 10:41     ` Thierry Reding
2015-01-10 12:37     ` Marc Zyngier
2015-01-10 12:37       ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 05/21] DT: tegra: add binding for the " Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 10:51   ` Thierry Reding
2015-01-08 10:51     ` Thierry Reding
2015-01-08 15:12   ` Nishanth Menon
2015-01-08 15:12     ` Nishanth Menon
2015-01-07 17:42 ` [PATCH v2 06/21] ARM: tegra: remove old LIC support Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 11:29   ` Thierry Reding
2015-01-08 11:29     ` Thierry Reding
2015-01-10 12:43     ` Marc Zyngier
2015-01-10 12:43       ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 07/21] genirq: Add irqchip_set_wake_parent Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 15:15   ` Nishanth Menon
2015-01-08 15:15     ` Nishanth Menon
2015-01-10 12:46     ` Marc Zyngier
2015-01-10 12:46       ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 08/21] irqchip: crossbar: convert dra7 crossbar to stacked domains Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 14:39   ` Nishanth Menon
2015-01-08 14:39     ` Nishanth Menon
2015-01-10 12:59     ` Marc Zyngier
2015-01-10 12:59       ` Marc Zyngier
2015-01-08 15:20   ` Nishanth Menon
2015-01-08 15:20     ` Nishanth Menon
2015-01-07 17:42 ` [PATCH v2 09/21] DT: update ti,irq-crossbar binding Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 10/21] irqchip: GIC: get rid of routable domain Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 16:13   ` Nishanth Menon
2015-01-08 16:13     ` Nishanth Menon
2015-01-07 17:42 ` [PATCH v2 11/21] DT: arm,gic: kill arm,routable-irqs Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 12/21] ARM: omap: convert wakeupgen to stacked domains Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 16:44   ` Nishanth Menon
2015-01-08 16:44     ` Nishanth Menon
2015-01-10 13:17     ` Marc Zyngier
2015-01-10 13:17       ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 13/21] DT: omap4/5: add binding for the wake-up generator Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 16:52   ` Nishanth Menon
2015-01-08 16:52     ` Nishanth Menon
2015-01-10 13:22     ` Marc Zyngier
2015-01-10 13:22       ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 14/21] ARM: imx6: convert GPC to stacked domains Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 16:57   ` Nishanth Menon
2015-01-08 16:57     ` Nishanth Menon
2015-01-09 17:40   ` Stefan Agner
2015-01-09 17:40     ` Stefan Agner
2015-01-10 13:34     ` Marc Zyngier
2015-01-10 13:34       ` Marc Zyngier
2015-01-10 14:16       ` Stefan Agner
2015-01-10 14:16         ` Stefan Agner
2015-01-07 17:42 ` [PATCH v2 15/21] ARM: exynos4/5: convert pmu wakeup " Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-08 16:58   ` Nishanth Menon
2015-01-08 16:58     ` Nishanth Menon
2015-01-07 17:42 ` [PATCH v2 16/21] DT: exynos: update PMU binding Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 17/21] irqchip: gic: add an entry point to set up irqchip flags Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 18/21] ARM: shmobile: remove use of gic_arch_extn.irq_set_wake Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 19/21] ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 20/21] ARM: zynq: " Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 17:42 ` [PATCH v2 21/21] irqchip: gic: Drop support for gic_arch_extn Marc Zyngier
2015-01-07 17:42   ` Marc Zyngier
2015-01-07 18:45 ` [PATCH v2 00/21] irqchip: gic: killing gic_arch_extn and co, slowly santosh shilimkar
2015-01-07 18:45   ` santosh shilimkar
2015-01-08  3:31 ` Nishanth Menon
2015-01-08  3:31   ` Nishanth Menon
2015-01-10 13:45 ` Marc Zyngier
2015-01-10 13:45   ` Marc Zyngier
2015-01-12 14:14 ` Rob Herring
2015-01-12 14:14   ` Rob Herring
2015-01-12 15:39   ` Marc Zyngier
2015-01-12 15:39     ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.