linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer
@ 2018-11-13 13:09 Phil Edworthy
  2018-11-13 13:09 ` [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding Phil Edworthy
  2018-11-13 13:09 ` [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
  0 siblings, 2 replies; 10+ messages in thread
From: Phil Edworthy @ 2018-11-13 13:09 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper, Rob Herring, Mark Rutland
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-kernel,
	Phil Edworthy, devicetree

On RZ/N1 devices, there are lots of GPIO interrupts that are multiplexed before
getting to the GIC interrupt controller. Other than the multiplexing, there is
no other logic applied to the signals.

The multiplexing cannot be handled dynamically because there is another CPU that
runs firmware. It's likely that the firmware will use some of these GPIO
interrupts and so we don't want them to move around.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v3:
 - Use 'interrupt-map' DT property to map the interrupts, this is very similar
   to PCIe MSI. The only difference is that we need to get hold of the interrupt
   specifier for the interupts coming into the irqmux.
   I had completely messed up the use of 'interrupt-map' in v2... oops.
 - Do not use a chained interrupt controller.
v2:
 - Split DT bindings into separate patch.
 - Use interrupt-map to allow the GPIO controller info to be specified
   as part of the irq.
 - Don't show status in binding examples.
 - Don't show the soc/board split in binding doc.
 - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.

Phil Edworthy (2):
  dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer

 .../interrupt-controller/renesas,rzn1-mux.txt |  73 +++++++
 drivers/irqchip/Kconfig                       |   9 +
 drivers/irqchip/Makefile                      |   1 +
 drivers/irqchip/rzn1-irq-mux.c                | 205 ++++++++++++++++++
 4 files changed, 288 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
 create mode 100644 drivers/irqchip/rzn1-irq-mux.c

-- 
2.17.1


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

* [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  2018-11-13 13:09 [PATCH v3 0/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
@ 2018-11-13 13:09 ` Phil Edworthy
  2018-11-17 14:32   ` Rob Herring
  2018-11-13 13:09 ` [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
  1 sibling, 1 reply; 10+ messages in thread
From: Phil Edworthy @ 2018-11-13 13:09 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper, Rob Herring, Mark Rutland
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-kernel,
	Phil Edworthy, devicetree

Add device binding documentation for the Renesas RZ/N1 GPIO interrupt
multiplexer.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v3:
 - Use 'interrupt-map' DT property correctly.
v2:
 - Use interrupt-map to allow the GPIO controller info to be specified
   as part of the irq.
 - Don't show status in binding examples.
 - Don't show the soc/board split in binding doc.
---
 .../interrupt-controller/renesas,rzn1-mux.txt | 73 +++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
new file mode 100644
index 000000000000..6515880e25cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
@@ -0,0 +1,73 @@
+* Renesas RZ/N1 GPIO Interrupt Multiplexer
+
+On Renesas RZ/N1 devices, there are several GPIO Controllers each with a number
+of interrupt outputs. All of the interrupts from the GPIO Controllers are passed
+to the GPIO Interrupt Multiplexer, which selects a sub-set of the interrupts to
+pass onto the system interrupt controller.
+
+A single node in the device tree is used to describe the GPIO IRQ Muxer.
+
+Required properties:
+- compatible: SoC-specific compatible string "renesas,<soc-specific>-gpioirqmux"
+  followed by "renesas,rzn1-gpioirqmux" as fallback. The SoC-specific compatible
+  strings must be one of:
+	"renesas,r9a06g032-gpioirqmux" for RZ/N1D
+	"renesas,r9a06g033-gpioirqmux" for RZ/N1S
+- reg: Base address and size of GPIO IRQ Muxer registers.
+- interrupts: List of output interrupts.
+- #interrupt-cells: Numder of cells in the input interrupt specifier, must be 1.
+- #address-cells: Must be 0.
+- interrupt-map-mask: must be 127.
+- interrupt-map: Standard property detailing the maps between input irqs and the
+  corresponding output irq. This consist of a list of:
+	<input-irq-spec phandle-to-interrupt-controller output-irq-spec>
+  The input-irq-spec is from 0 to 95, corresponding to the outputs of the GPIO
+  Controllers.
+
+Example:
+
+	The following is an example for the RZ/N1D SoC.
+
+	gpioirqmux: gpioirqmux@51000480 {
+		compatible = "renesas,r9a06g032-gpioirqmux",
+				"renesas,rzn1-gpioirqmux";
+		reg = <0x51000480 0x20>;
+		interrupts =
+			<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+
+		#interrupt-cells = <1>;
+		#address-cells = <0>;
+		interrupt-map-mask = <127>;
+		interrupt-map =
+			/* gpio2a 24, pin 146: ETH Port 1 IRQ */
+			<88 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+			/* gpio2a 26, pin 148: TouchSCRN_IRQ */
+			<90 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	gpio2: gpio@5000d000 {
+		compatible = "snps,dw-apb-gpio";
+		reg = <0x5000d000 0x80>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "bus";
+		clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
+
+		gpio2a: gpio-controller@0 {
+			compatible = "snps,dw-apb-gpio-port";
+			bank-name = "gpio2a";
+			gpio-controller;
+			#gpio-cells = <2>;
+			snps,nr-gpios = <32>;
+			reg = <0>;
+
+			interrupt-controller;
+			interrupt-parent = <&gpioirqmux>;
+			interrupts =  < 64 65 66 67 68 69 70 71
+					72 73 74 75 76 77 78 79
+					80 81 82 83 84 85 86 87
+					88 89 90 91 92 93 94 95 >;
+			#interrupt-cells = <2>;
+		};
+	};
-- 
2.17.1


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

* [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer
  2018-11-13 13:09 [PATCH v3 0/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
  2018-11-13 13:09 ` [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding Phil Edworthy
@ 2018-11-13 13:09 ` Phil Edworthy
  2019-02-19 15:27   ` Phil Edworthy
  1 sibling, 1 reply; 10+ messages in thread
From: Phil Edworthy @ 2018-11-13 13:09 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-kernel, Phil Edworthy

On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
configured to have 32 interrupt outputs, so we have a total of 96 GPIO
interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
aren't latched, so there is nothing to do in this driver when an interrupt
is received, other than tell the corresponding GPIO block.

Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
---
v3:
 - Use 'interrupt-map' DT property to map the interrupts, this is very similar
   to PCIe MSI. The only difference is that we need to get hold of the interrupt
   specifier for the interupts coming into the irqmux.
 - Do not use a chained interrupt controller.
v2:
 - Use interrupt-map to allow the GPIO controller info to be specified
   as part of the irq.
 - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
---
 drivers/irqchip/Kconfig        |   9 ++
 drivers/irqchip/Makefile       |   1 +
 drivers/irqchip/rzn1-irq-mux.c | 205 +++++++++++++++++++++++++++++++++
 3 files changed, 215 insertions(+)
 create mode 100644 drivers/irqchip/rzn1-irq-mux.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 96451b581452..53c54bba1dd8 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -204,6 +204,15 @@ config RENESAS_IRQC
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config RENESAS_RZN1_IRQ_MUX
+	bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
+	depends on ARCH_RZN1
+	select IRQ_DOMAIN
+	help
+	  Say yes here to add support for the GPIO IRQ multiplexer embedded
+	  in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
+	  the interrupts coming from the GPIO controllers are used.
+
 config ST_IRQCHIP
 	bool
 	select REGMAP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b822199445ff..b090f84dd42e 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
 obj-$(CONFIG_JCORE_AIC)			+= irq-jcore-aic.o
 obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
 obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
+obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX)	+= rzn1-irq-mux.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
diff --git a/drivers/irqchip/rzn1-irq-mux.c b/drivers/irqchip/rzn1-irq-mux.c
new file mode 100644
index 000000000000..ee7810b9b3f3
--- /dev/null
+++ b/drivers/irqchip/rzn1-irq-mux.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/N1 GPIO Interrupt Multiplexer
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each configured
+ * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
+ * All of these are passed to the GPIO IRQ Muxer, which selects 8 of the GPIO
+ * interrupts to pass onto the GIC.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#define MAX_NR_INPUT_IRQS	96
+#define MAX_NR_OUTPUT_IRQS	8
+
+/*
+ * "interrupt-map" consists of 1 interrupt cell, 0 address cells, phandle to
+ * interrupt parent, and parent interrupt specifier (3 cells for GIC), giving
+ * a total of 5 cells.
+ */
+#define IMAP_LENGTH		5
+
+struct irqmux_priv;
+struct irqmux_one {
+	unsigned int irq;
+	unsigned int src_hwirq;
+	struct irqmux_priv *priv;
+};
+
+struct irqmux_priv {
+	struct device *dev;
+	struct irq_domain *irq_domain;
+	unsigned int nr_irqs;
+	struct irqmux_one mux[MAX_NR_OUTPUT_IRQS];
+};
+
+static irqreturn_t irqmux_handler(int irq, void *data)
+{
+	struct irqmux_one *mux = data;
+	struct irqmux_priv *priv = mux->priv;
+	unsigned int virq;
+
+	virq = irq_find_mapping(priv->irq_domain, mux->src_hwirq);
+
+	generic_handle_irq(virq);
+
+	return IRQ_HANDLED;
+}
+
+static int irqmux_domain_map(struct irq_domain *h, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	irq_set_chip_data(irq, h->host_data);
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops irqmux_domain_ops = {
+	.map = irqmux_domain_map,
+};
+
+static int irqmux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct resource *res;
+	u32 __iomem *regs;
+	struct irqmux_priv *priv;
+	unsigned int i;
+	int nr_irqs;
+	int ret;
+	const __be32 *imap;
+	int imaplen;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	platform_set_drvdata(pdev, priv);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	nr_irqs = of_irq_count(np);
+	if (nr_irqs < 0)
+		return nr_irqs;
+
+	if (nr_irqs > MAX_NR_OUTPUT_IRQS) {
+		dev_err(dev, "too many output interrupts\n");
+		return -ENOENT;
+	}
+
+	priv->nr_irqs = nr_irqs;
+
+	/* Look for the interrupt-map */
+	imap = of_get_property(np, "interrupt-map", &imaplen);
+	if (!imap)
+		return -ENOENT;
+	imaplen /= IMAP_LENGTH * sizeof(__be32);
+
+	/* Sometimes not all muxs are used */
+	if (imaplen < priv->nr_irqs)
+		priv->nr_irqs = imaplen;
+
+	/* Create IRQ domain for the interrupts coming from the GPIO blocks */
+	priv->irq_domain = irq_domain_add_linear(np, MAX_NR_INPUT_IRQS,
+						 &irqmux_domain_ops, priv);
+	if (!priv->irq_domain)
+		return -ENOMEM;
+
+	for (i = 0; i < MAX_NR_INPUT_IRQS; i++)
+		irq_create_mapping(priv->irq_domain, i);
+
+	for (i = 0; i < priv->nr_irqs; i++) {
+		struct irqmux_one *mux = &priv->mux[i];
+
+		ret = irq_of_parse_and_map(np, i);
+		if (ret < 0) {
+			ret = -ENOENT;
+			goto err;
+		}
+
+		mux->irq = ret;
+		mux->priv = priv;
+
+		/*
+		 * We need the first cell of the interrupt-map to configure
+		 * the hardware.
+		 */
+		mux->src_hwirq = be32_to_cpu(*imap);
+		imap += IMAP_LENGTH;
+
+		dev_info(dev, "%u: %u mapped irq %u\n", i,  mux->src_hwirq,
+			 mux->irq);
+
+		ret = devm_request_irq(dev, mux->irq, irqmux_handler,
+				       IRQF_SHARED | IRQF_NO_THREAD,
+				       "irqmux", mux);
+		if (ret < 0) {
+			dev_err(dev, "failed to request IRQ: %d\n", ret);
+			goto err;
+		}
+
+		/* Set up the hardware to pass the interrupt through */
+		writel(mux->src_hwirq, &regs[i]);
+	}
+
+	dev_info(dev, "probed, %d gpio interrupts\n", priv->nr_irqs);
+
+	return 0;
+
+err:
+	while (i--)
+		irq_dispose_mapping(priv->mux[i].irq);
+	irq_domain_remove(priv->irq_domain);
+
+	return ret;
+}
+
+static int irqmux_remove(struct platform_device *pdev)
+{
+	struct irqmux_priv *priv = platform_get_drvdata(pdev);
+	unsigned int i;
+
+	for (i = 0; i < priv->nr_irqs; i++)
+		irq_dispose_mapping(priv->mux[i].irq);
+	irq_domain_remove(priv->irq_domain);
+
+	return 0;
+}
+
+static const struct of_device_id irqmux_match[] = {
+	{ .compatible = "renesas,rzn1-gpioirqmux", },
+	{ /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, irqmux_match);
+
+static struct platform_driver irqmux_driver = {
+	.driver = {
+		.name = "gpio_irq_mux",
+		.owner = THIS_MODULE,
+		.of_match_table = irqmux_match,
+	},
+	.probe = irqmux_probe,
+	.remove = irqmux_remove,
+};
+
+module_platform_driver(irqmux_driver);
+
+MODULE_DESCRIPTION("Renesas RZ/N1 GPIO IRQ Multiplexer Driver");
+MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


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

* Re: [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  2018-11-13 13:09 ` [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding Phil Edworthy
@ 2018-11-17 14:32   ` Rob Herring
  2018-11-19  9:39     ` Phil Edworthy
  0 siblings, 1 reply; 10+ messages in thread
From: Rob Herring @ 2018-11-17 14:32 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: Marc Zyngier, Thomas Gleixner, Jason Cooper, Mark Rutland,
	Geert Uytterhoeven, linux-renesas-soc, linux-kernel, devicetree

On Tue, Nov 13, 2018 at 01:09:09PM +0000, Phil Edworthy wrote:
> Add device binding documentation for the Renesas RZ/N1 GPIO interrupt
> multiplexer.
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> ---
> v3:
>  - Use 'interrupt-map' DT property correctly.
> v2:
>  - Use interrupt-map to allow the GPIO controller info to be specified
>    as part of the irq.
>  - Don't show status in binding examples.
>  - Don't show the soc/board split in binding doc.
> ---
>  .../interrupt-controller/renesas,rzn1-mux.txt | 73 +++++++++++++++++++
>  1 file changed, 73 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt

A few nits, otherwise:

Reviewed-by: Rob Herring <robh@kernel.org>

> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
> new file mode 100644
> index 000000000000..6515880e25cc
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mux.txt
> @@ -0,0 +1,73 @@
> +* Renesas RZ/N1 GPIO Interrupt Multiplexer
> +
> +On Renesas RZ/N1 devices, there are several GPIO Controllers each with a number
> +of interrupt outputs. All of the interrupts from the GPIO Controllers are passed
> +to the GPIO Interrupt Multiplexer, which selects a sub-set of the interrupts to
> +pass onto the system interrupt controller.
> +
> +A single node in the device tree is used to describe the GPIO IRQ Muxer.
> +
> +Required properties:
> +- compatible: SoC-specific compatible string "renesas,<soc-specific>-gpioirqmux"
> +  followed by "renesas,rzn1-gpioirqmux" as fallback. The SoC-specific compatible
> +  strings must be one of:
> +	"renesas,r9a06g032-gpioirqmux" for RZ/N1D
> +	"renesas,r9a06g033-gpioirqmux" for RZ/N1S
> +- reg: Base address and size of GPIO IRQ Muxer registers.
> +- interrupts: List of output interrupts.
> +- #interrupt-cells: Numder of cells in the input interrupt specifier, must be 1.
> +- #address-cells: Must be 0.
> +- interrupt-map-mask: must be 127.
> +- interrupt-map: Standard property detailing the maps between input irqs and the
> +  corresponding output irq. This consist of a list of:
> +	<input-irq-spec phandle-to-interrupt-controller output-irq-spec>
> +  The input-irq-spec is from 0 to 95, corresponding to the outputs of the GPIO
> +  Controllers.
> +
> +Example:
> +
> +	The following is an example for the RZ/N1D SoC.
> +
> +	gpioirqmux: gpioirqmux@51000480 {

interrupt-controller@...

> +		compatible = "renesas,r9a06g032-gpioirqmux",
> +				"renesas,rzn1-gpioirqmux";
> +		reg = <0x51000480 0x20>;
> +		interrupts =
> +			<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> +			<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;

This is a bit redundant as the same information is in interrupt-map, but 
I guess you need it to get the irq resources.

> +
> +		#interrupt-cells = <1>;
> +		#address-cells = <0>;
> +		interrupt-map-mask = <127>;

Use hex for masks.

> +		interrupt-map =
> +			/* gpio2a 24, pin 146: ETH Port 1 IRQ */
> +			<88 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> +			/* gpio2a 26, pin 148: TouchSCRN_IRQ */
> +			<90 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> +	};
> +
> +	gpio2: gpio@5000d000 {
> +		compatible = "snps,dw-apb-gpio";
> +		reg = <0x5000d000 0x80>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clock-names = "bus";
> +		clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
> +
> +		gpio2a: gpio-controller@0 {

gpio@0

> +			compatible = "snps,dw-apb-gpio-port";
> +			bank-name = "gpio2a";
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +			snps,nr-gpios = <32>;
> +			reg = <0>;
> +
> +			interrupt-controller;
> +			interrupt-parent = <&gpioirqmux>;
> +			interrupts =  < 64 65 66 67 68 69 70 71
> +					72 73 74 75 76 77 78 79
> +					80 81 82 83 84 85 86 87
> +					88 89 90 91 92 93 94 95 >;
> +			#interrupt-cells = <2>;
> +		};
> +	};
> -- 
> 2.17.1
> 

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

* RE: [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  2018-11-17 14:32   ` Rob Herring
@ 2018-11-19  9:39     ` Phil Edworthy
  2018-11-19 21:50       ` Rob Herring
  0 siblings, 1 reply; 10+ messages in thread
From: Phil Edworthy @ 2018-11-19  9:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marc Zyngier, Thomas Gleixner, Jason Cooper, Mark Rutland,
	Geert Uytterhoeven, linux-renesas-soc, linux-kernel, devicetree

Hi Rob,

On 17 November 2018 14:33 Rob Herring wrote:
> On Tue, Nov 13, 2018 at 01:09:09PM +0000, Phil Edworthy wrote:
> > Add device binding documentation for the Renesas RZ/N1 GPIO interrupt
> > multiplexer.
> >
> > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> > ---
> > v3:
> >  - Use 'interrupt-map' DT property correctly.
> > v2:
> >  - Use interrupt-map to allow the GPIO controller info to be specified
> >    as part of the irq.
> >  - Don't show status in binding examples.
> >  - Don't show the soc/board split in binding doc.
> > ---
> >  .../interrupt-controller/renesas,rzn1-mux.txt | 73
> > +++++++++++++++++++
> >  1 file changed, 73 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mu
> > x.txt
> 
> A few nits, otherwise:
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
Thanks for the review!

> >
> > diff --git
> > a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > mux.txt
> > b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > mux.txt
> > new file mode 100644
> > index 000000000000..6515880e25cc
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,r
> > +++ zn1-mux.txt
> > @@ -0,0 +1,73 @@
> > +* Renesas RZ/N1 GPIO Interrupt Multiplexer
> > +
> > +On Renesas RZ/N1 devices, there are several GPIO Controllers each
> > +with a number of interrupt outputs. All of the interrupts from the
> > +GPIO Controllers are passed to the GPIO Interrupt Multiplexer, which
> > +selects a sub-set of the interrupts to pass onto the system interrupt
> controller.
> > +
> > +A single node in the device tree is used to describe the GPIO IRQ Muxer.
> > +
> > +Required properties:
> > +- compatible: SoC-specific compatible string "renesas,<soc-specific>-
> gpioirqmux"
> > +  followed by "renesas,rzn1-gpioirqmux" as fallback. The SoC-specific
> > +compatible
> > +  strings must be one of:
> > +	"renesas,r9a06g032-gpioirqmux" for RZ/N1D
> > +	"renesas,r9a06g033-gpioirqmux" for RZ/N1S
> > +- reg: Base address and size of GPIO IRQ Muxer registers.
> > +- interrupts: List of output interrupts.
> > +- #interrupt-cells: Numder of cells in the input interrupt specifier, must be
> 1.
> > +- #address-cells: Must be 0.
> > +- interrupt-map-mask: must be 127.
> > +- interrupt-map: Standard property detailing the maps between input
> > +irqs and the
> > +  corresponding output irq. This consist of a list of:
> > +	<input-irq-spec phandle-to-interrupt-controller output-irq-spec>
> > +  The input-irq-spec is from 0 to 95, corresponding to the outputs of
> > +the GPIO
> > +  Controllers.
> > +
> > +Example:
> > +
> > +	The following is an example for the RZ/N1D SoC.
> > +
> > +	gpioirqmux: gpioirqmux@51000480 {
> 
> interrupt-controller@...
Sure

> > +		compatible = "renesas,r9a06g032-gpioirqmux",
> > +				"renesas,rzn1-gpioirqmux";
> > +		reg = <0x51000480 0x20>;
> > +		interrupts =
> > +			<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > +			<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> 
> This is a bit redundant as the same information is in interrupt-map, but I
> guess you need it to get the irq resources.
That's right.

> > +
> > +		#interrupt-cells = <1>;
> > +		#address-cells = <0>;
> > +		interrupt-map-mask = <127>;
> 
> Use hex for masks.
Ok.

> > +		interrupt-map =
> > +			/* gpio2a 24, pin 146: ETH Port 1 IRQ */
> > +			<88 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > +			/* gpio2a 26, pin 148: TouchSCRN_IRQ */
> > +			<90 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> > +	};
> > +
> > +	gpio2: gpio@5000d000 {
> > +		compatible = "snps,dw-apb-gpio";
> > +		reg = <0x5000d000 0x80>;
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +		clock-names = "bus";
> > +		clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
> > +
> > +		gpio2a: gpio-controller@0 {
> 
> gpio@0
Are you sure about this?
The bindings in Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
show an example where the sub-nodes for gpio banks are gpio-controller@.
This is also in Documentation/devicetree/bindings/gpio/gpio.txt.

Thanks
Phil

> > +			compatible = "snps,dw-apb-gpio-port";
> > +			bank-name = "gpio2a";
> > +			gpio-controller;
> > +			#gpio-cells = <2>;
> > +			snps,nr-gpios = <32>;
> > +			reg = <0>;
> > +
> > +			interrupt-controller;
> > +			interrupt-parent = <&gpioirqmux>;
> > +			interrupts =  < 64 65 66 67 68 69 70 71
> > +					72 73 74 75 76 77 78 79
> > +					80 81 82 83 84 85 86 87
> > +					88 89 90 91 92 93 94 95 >;
> > +			#interrupt-cells = <2>;
> > +		};
> > +	};
> > --
> > 2.17.1
> >

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

* Re: [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  2018-11-19  9:39     ` Phil Edworthy
@ 2018-11-19 21:50       ` Rob Herring
  2018-11-20 10:30         ` Phil Edworthy
  0 siblings, 1 reply; 10+ messages in thread
From: Rob Herring @ 2018-11-19 21:50 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: Marc Zyngier, Thomas Gleixner, Jason Cooper, Mark Rutland,
	Geert Uytterhoeven, open list:MEDIA DRIVERS FOR RENESAS - FCP,
	linux-kernel, devicetree

On Mon, Nov 19, 2018 at 3:39 AM Phil Edworthy <phil.edworthy@renesas.com> wrote:
>
> Hi Rob,
>
> On 17 November 2018 14:33 Rob Herring wrote:
> > On Tue, Nov 13, 2018 at 01:09:09PM +0000, Phil Edworthy wrote:
> > > Add device binding documentation for the Renesas RZ/N1 GPIO interrupt
> > > multiplexer.
> > >
> > > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> > > ---
> > > v3:
> > >  - Use 'interrupt-map' DT property correctly.
> > > v2:
> > >  - Use interrupt-map to allow the GPIO controller info to be specified
> > >    as part of the irq.
> > >  - Don't show status in binding examples.
> > >  - Don't show the soc/board split in binding doc.
> > > ---
> > >  .../interrupt-controller/renesas,rzn1-mux.txt | 73
> > > +++++++++++++++++++
> > >  1 file changed, 73 insertions(+)
> > >  create mode 100644
> > > Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-mu
> > > x.txt
> >
> > A few nits, otherwise:
> >
> > Reviewed-by: Rob Herring <robh@kernel.org>
> Thanks for the review!
>
> > >
> > > diff --git
> > > a/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > > mux.txt
> > > b/Documentation/devicetree/bindings/interrupt-controller/renesas,rzn1-
> > > mux.txt
> > > new file mode 100644
> > > index 000000000000..6515880e25cc
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,r
> > > +++ zn1-mux.txt
> > > @@ -0,0 +1,73 @@
> > > +* Renesas RZ/N1 GPIO Interrupt Multiplexer
> > > +
> > > +On Renesas RZ/N1 devices, there are several GPIO Controllers each
> > > +with a number of interrupt outputs. All of the interrupts from the
> > > +GPIO Controllers are passed to the GPIO Interrupt Multiplexer, which
> > > +selects a sub-set of the interrupts to pass onto the system interrupt
> > controller.
> > > +
> > > +A single node in the device tree is used to describe the GPIO IRQ Muxer.
> > > +
> > > +Required properties:
> > > +- compatible: SoC-specific compatible string "renesas,<soc-specific>-
> > gpioirqmux"
> > > +  followed by "renesas,rzn1-gpioirqmux" as fallback. The SoC-specific
> > > +compatible
> > > +  strings must be one of:
> > > +   "renesas,r9a06g032-gpioirqmux" for RZ/N1D
> > > +   "renesas,r9a06g033-gpioirqmux" for RZ/N1S
> > > +- reg: Base address and size of GPIO IRQ Muxer registers.
> > > +- interrupts: List of output interrupts.
> > > +- #interrupt-cells: Numder of cells in the input interrupt specifier, must be
> > 1.
> > > +- #address-cells: Must be 0.
> > > +- interrupt-map-mask: must be 127.
> > > +- interrupt-map: Standard property detailing the maps between input
> > > +irqs and the
> > > +  corresponding output irq. This consist of a list of:
> > > +   <input-irq-spec phandle-to-interrupt-controller output-irq-spec>
> > > +  The input-irq-spec is from 0 to 95, corresponding to the outputs of
> > > +the GPIO
> > > +  Controllers.
> > > +
> > > +Example:
> > > +
> > > +   The following is an example for the RZ/N1D SoC.
> > > +
> > > +   gpioirqmux: gpioirqmux@51000480 {
> >
> > interrupt-controller@...
> Sure
>
> > > +           compatible = "renesas,r9a06g032-gpioirqmux",
> > > +                           "renesas,rzn1-gpioirqmux";
> > > +           reg = <0x51000480 0x20>;
> > > +           interrupts =
> > > +                   <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > > +                   <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> >
> > This is a bit redundant as the same information is in interrupt-map, but I
> > guess you need it to get the irq resources.
> That's right.
>
> > > +
> > > +           #interrupt-cells = <1>;
> > > +           #address-cells = <0>;
> > > +           interrupt-map-mask = <127>;
> >
> > Use hex for masks.
> Ok.
>
> > > +           interrupt-map =
> > > +                   /* gpio2a 24, pin 146: ETH Port 1 IRQ */
> > > +                   <88 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > > +                   /* gpio2a 26, pin 148: TouchSCRN_IRQ */
> > > +                   <90 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> > > +   };
> > > +
> > > +   gpio2: gpio@5000d000 {
> > > +           compatible = "snps,dw-apb-gpio";
> > > +           reg = <0x5000d000 0x80>;
> > > +           #address-cells = <1>;
> > > +           #size-cells = <0>;
> > > +           clock-names = "bus";
> > > +           clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
> > > +
> > > +           gpio2a: gpio-controller@0 {
> >
> > gpio@0
> Are you sure about this?

Yes, 'gpio' is what the DT spec says. It is the oddball though and I
always have to think about it.

> The bindings in Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> show an example where the sub-nodes for gpio banks are gpio-controller@.
> This is also in Documentation/devicetree/bindings/gpio/gpio.txt.

Indeed. Those should be fixed. I would be easily persuaded to just
change the spec, but 'gpio@' is much more widely used:

$ git grep gpio@ -- arch/ | wc
   1110    4378   67766
$ git grep gpio-controller@ -- arch/ | wc
     60     232    4270

Rob

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

* RE: [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding
  2018-11-19 21:50       ` Rob Herring
@ 2018-11-20 10:30         ` Phil Edworthy
  0 siblings, 0 replies; 10+ messages in thread
From: Phil Edworthy @ 2018-11-20 10:30 UTC (permalink / raw)
  To: Rob Herring
  Cc: Marc Zyngier, Thomas Gleixner, Jason Cooper, Mark Rutland,
	Geert Uytterhoeven, open list:MEDIA DRIVERS FOR RENESAS - FCP,
	linux-kernel, devicetree

Hi Rob,

On 19 November 2018 21:51, Rob Herring wrote:
> On Mon, Nov 19, 2018 at 3:39 AM Phil Edworthy
> <phil.edworthy@renesas.com> wrote:
> >
> > Hi Rob,
> >
> > On 17 November 2018 14:33 Rob Herring wrote:
> > > On Tue, Nov 13, 2018 at 01:09:09PM +0000, Phil Edworthy wrote:
> > > > Add device binding documentation for the Renesas RZ/N1 GPIO
> > > > interrupt multiplexer.
> > > >
> > > > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> > > > ---
> > > > v3:
> > > >  - Use 'interrupt-map' DT property correctly.
> > > > v2:
> > > >  - Use interrupt-map to allow the GPIO controller info to be specified
> > > >    as part of the irq.
> > > >  - Don't show status in binding examples.
> > > >  - Don't show the soc/board split in binding doc.
> > > > ---
> > > >  .../interrupt-controller/renesas,rzn1-mux.txt | 73
> > > > +++++++++++++++++++
> > > >  1 file changed, 73 insertions(+)
> > > >  create mode 100644
> > > > Documentation/devicetree/bindings/interrupt-controller/renesas,rzn
> > > > 1-mu
> > > > x.txt
> > >
> > > A few nits, otherwise:
> > >
> > > Reviewed-by: Rob Herring <robh@kernel.org>
> > Thanks for the review!
> >
> > > >
> > > > diff --git
> > > > a/Documentation/devicetree/bindings/interrupt-controller/renesas,r
> > > > zn1-
> > > > mux.txt
> > > > b/Documentation/devicetree/bindings/interrupt-controller/renesas,r
> > > > zn1-
> > > > mux.txt
> > > > new file mode 100644
> > > > index 000000000000..6515880e25cc
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/interrupt-controller/renes
> > > > +++ as,r
> > > > +++ zn1-mux.txt
> > > > @@ -0,0 +1,73 @@
> > > > +* Renesas RZ/N1 GPIO Interrupt Multiplexer
> > > > +
> > > > +On Renesas RZ/N1 devices, there are several GPIO Controllers each
> > > > +with a number of interrupt outputs. All of the interrupts from
> > > > +the GPIO Controllers are passed to the GPIO Interrupt
> > > > +Multiplexer, which selects a sub-set of the interrupts to pass
> > > > +onto the system interrupt
> > > controller.
> > > > +
> > > > +A single node in the device tree is used to describe the GPIO IRQ
> Muxer.
> > > > +
> > > > +Required properties:
> > > > +- compatible: SoC-specific compatible string
> > > > +"renesas,<soc-specific>-
> > > gpioirqmux"
> > > > +  followed by "renesas,rzn1-gpioirqmux" as fallback. The
> > > > +SoC-specific compatible
> > > > +  strings must be one of:
> > > > +   "renesas,r9a06g032-gpioirqmux" for RZ/N1D
> > > > +   "renesas,r9a06g033-gpioirqmux" for RZ/N1S
> > > > +- reg: Base address and size of GPIO IRQ Muxer registers.
> > > > +- interrupts: List of output interrupts.
> > > > +- #interrupt-cells: Numder of cells in the input interrupt
> > > > +specifier, must be
> > > 1.
> > > > +- #address-cells: Must be 0.
> > > > +- interrupt-map-mask: must be 127.
> > > > +- interrupt-map: Standard property detailing the maps between
> > > > +input irqs and the
> > > > +  corresponding output irq. This consist of a list of:
> > > > +   <input-irq-spec phandle-to-interrupt-controller
> > > > +output-irq-spec>
> > > > +  The input-irq-spec is from 0 to 95, corresponding to the
> > > > +outputs of the GPIO
> > > > +  Controllers.
> > > > +
> > > > +Example:
> > > > +
> > > > +   The following is an example for the RZ/N1D SoC.
> > > > +
> > > > +   gpioirqmux: gpioirqmux@51000480 {
> > >
> > > interrupt-controller@...
> > Sure
> >
> > > > +           compatible = "renesas,r9a06g032-gpioirqmux",
> > > > +                           "renesas,rzn1-gpioirqmux";
> > > > +           reg = <0x51000480 0x20>;
> > > > +           interrupts =
> > > > +                   <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > > > +                   <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> > >
> > > This is a bit redundant as the same information is in interrupt-map,
> > > but I guess you need it to get the irq resources.
> > That's right.
> >
> > > > +
> > > > +           #interrupt-cells = <1>;
> > > > +           #address-cells = <0>;
> > > > +           interrupt-map-mask = <127>;
> > >
> > > Use hex for masks.
> > Ok.
> >
> > > > +           interrupt-map =
> > > > +                   /* gpio2a 24, pin 146: ETH Port 1 IRQ */
> > > > +                   <88 &gic GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
> > > > +                   /* gpio2a 26, pin 148: TouchSCRN_IRQ */
> > > > +                   <90 &gic GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
> > > > +   };
> > > > +
> > > > +   gpio2: gpio@5000d000 {
> > > > +           compatible = "snps,dw-apb-gpio";
> > > > +           reg = <0x5000d000 0x80>;
> > > > +           #address-cells = <1>;
> > > > +           #size-cells = <0>;
> > > > +           clock-names = "bus";
> > > > +           clocks = <&sysctrl R9A06G032_HCLK_GPIO2>;
> > > > +
> > > > +           gpio2a: gpio-controller@0 {
> > >
> > > gpio@0
> > Are you sure about this?
> 
> Yes, 'gpio' is what the DT spec says. It is the oddball though and I always have
> to think about it.
OK, got it.

> > The bindings in
> > Documentation/devicetree/bindings/gpio/snps-dwapb-gpio.txt
> > show an example where the sub-nodes for gpio banks are gpio-
> controller@.
> > This is also in Documentation/devicetree/bindings/gpio/gpio.txt.
> 
> Indeed. Those should be fixed. I would be easily persuaded to just change
> the spec, but 'gpio@' is much more widely used:
> 
> $ git grep gpio@ -- arch/ | wc
>    1110    4378   67766
> $ git grep gpio-controller@ -- arch/ | wc
>      60     232    4270
> 
Yes, indeed.

Thanks
Phil

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

* RE: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer
  2018-11-13 13:09 ` [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
@ 2019-02-19 15:27   ` Phil Edworthy
  2019-02-19 15:39     ` Marc Zyngier
  0 siblings, 1 reply; 10+ messages in thread
From: Phil Edworthy @ 2019-02-19 15:27 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper
  Cc: Geert Uytterhoeven, linux-renesas-soc, linux-kernel

Hello,

Any comments on this patch?

Thanks
Phil

> -----Original Message-----
> From: Phil Edworthy <phil.edworthy@renesas.com>
> Sent: 13 November 2018 13:09
> To: Marc Zyngier <marc.zyngier@arm.com>; Thomas Gleixner
> <tglx@linutronix.de>; Jason Cooper <jason@lakedaemon.net>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>; linux-renesas-
> soc@vger.kernel.org; linux-kernel@vger.kernel.org; Phil Edworthy
> <phil.edworthy@renesas.com>
> Subject: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO
> interrupt multiplexer
> 
> On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> configured to have 32 interrupt outputs, so we have a total of 96 GPIO
> interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
> 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals aren't
> latched, so there is nothing to do in this driver when an interrupt is received,
> other than tell the corresponding GPIO block.
> 
> Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> ---
> v3:
>  - Use 'interrupt-map' DT property to map the interrupts, this is very similar
>    to PCIe MSI. The only difference is that we need to get hold of the interrupt
>    specifier for the interupts coming into the irqmux.
>  - Do not use a chained interrupt controller.
> v2:
>  - Use interrupt-map to allow the GPIO controller info to be specified
>    as part of the irq.
>  - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
> ---
>  drivers/irqchip/Kconfig        |   9 ++
>  drivers/irqchip/Makefile       |   1 +
>  drivers/irqchip/rzn1-irq-mux.c | 205
> +++++++++++++++++++++++++++++++++
>  3 files changed, 215 insertions(+)
>  create mode 100644 drivers/irqchip/rzn1-irq-mux.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
> 96451b581452..53c54bba1dd8 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -204,6 +204,15 @@ config RENESAS_IRQC
>  	select GENERIC_IRQ_CHIP
>  	select IRQ_DOMAIN
> 
> +config RENESAS_RZN1_IRQ_MUX
> +	bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
> +	depends on ARCH_RZN1
> +	select IRQ_DOMAIN
> +	help
> +	  Say yes here to add support for the GPIO IRQ multiplexer
> embedded
> +	  in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
> +	  the interrupts coming from the GPIO controllers are used.
> +
>  config ST_IRQCHIP
>  	bool
>  	select REGMAP
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index
> b822199445ff..b090f84dd42e 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)			+= irq-
> sirfsoc.o
>  obj-$(CONFIG_JCORE_AIC)			+= irq-jcore-aic.o
>  obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
>  obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
> +obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX)	+= rzn1-irq-mux.o
>  obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
>  obj-$(CONFIG_ARCH_NSPIRE)		+= irq-zevio.o
>  obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
> diff --git a/drivers/irqchip/rzn1-irq-mux.c b/drivers/irqchip/rzn1-irq-mux.c
> new file mode 100644 index 000000000000..ee7810b9b3f3
> --- /dev/null
> +++ b/drivers/irqchip/rzn1-irq-mux.c
> @@ -0,0 +1,205 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * RZ/N1 GPIO Interrupt Multiplexer
> + *
> + * Copyright (C) 2018 Renesas Electronics Europe Limited
> + *
> + * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> +configured
> + * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
> + * All of these are passed to the GPIO IRQ Muxer, which selects 8 of
> +the GPIO
> + * interrupts to pass onto the GIC.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +
> +#define MAX_NR_INPUT_IRQS	96
> +#define MAX_NR_OUTPUT_IRQS	8
> +
> +/*
> + * "interrupt-map" consists of 1 interrupt cell, 0 address cells,
> +phandle to
> + * interrupt parent, and parent interrupt specifier (3 cells for GIC),
> +giving
> + * a total of 5 cells.
> + */
> +#define IMAP_LENGTH		5
> +
> +struct irqmux_priv;
> +struct irqmux_one {
> +	unsigned int irq;
> +	unsigned int src_hwirq;
> +	struct irqmux_priv *priv;
> +};
> +
> +struct irqmux_priv {
> +	struct device *dev;
> +	struct irq_domain *irq_domain;
> +	unsigned int nr_irqs;
> +	struct irqmux_one mux[MAX_NR_OUTPUT_IRQS]; };
> +
> +static irqreturn_t irqmux_handler(int irq, void *data) {
> +	struct irqmux_one *mux = data;
> +	struct irqmux_priv *priv = mux->priv;
> +	unsigned int virq;
> +
> +	virq = irq_find_mapping(priv->irq_domain, mux->src_hwirq);
> +
> +	generic_handle_irq(virq);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int irqmux_domain_map(struct irq_domain *h, unsigned int irq,
> +			     irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_data(irq, h->host_data);
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip,
> handle_simple_irq);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops irqmux_domain_ops = {
> +	.map = irqmux_domain_map,
> +};
> +
> +static int irqmux_probe(struct platform_device *pdev) {
> +	struct device *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct resource *res;
> +	u32 __iomem *regs;
> +	struct irqmux_priv *priv;
> +	unsigned int i;
> +	int nr_irqs;
> +	int ret;
> +	const __be32 *imap;
> +	int imaplen;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->dev = dev;
> +	platform_set_drvdata(pdev, priv);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	nr_irqs = of_irq_count(np);
> +	if (nr_irqs < 0)
> +		return nr_irqs;
> +
> +	if (nr_irqs > MAX_NR_OUTPUT_IRQS) {
> +		dev_err(dev, "too many output interrupts\n");
> +		return -ENOENT;
> +	}
> +
> +	priv->nr_irqs = nr_irqs;
> +
> +	/* Look for the interrupt-map */
> +	imap = of_get_property(np, "interrupt-map", &imaplen);
> +	if (!imap)
> +		return -ENOENT;
> +	imaplen /= IMAP_LENGTH * sizeof(__be32);
> +
> +	/* Sometimes not all muxs are used */
> +	if (imaplen < priv->nr_irqs)
> +		priv->nr_irqs = imaplen;
> +
> +	/* Create IRQ domain for the interrupts coming from the GPIO blocks
> */
> +	priv->irq_domain = irq_domain_add_linear(np,
> MAX_NR_INPUT_IRQS,
> +						 &irqmux_domain_ops, priv);
> +	if (!priv->irq_domain)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < MAX_NR_INPUT_IRQS; i++)
> +		irq_create_mapping(priv->irq_domain, i);
> +
> +	for (i = 0; i < priv->nr_irqs; i++) {
> +		struct irqmux_one *mux = &priv->mux[i];
> +
> +		ret = irq_of_parse_and_map(np, i);
> +		if (ret < 0) {
> +			ret = -ENOENT;
> +			goto err;
> +		}
> +
> +		mux->irq = ret;
> +		mux->priv = priv;
> +
> +		/*
> +		 * We need the first cell of the interrupt-map to configure
> +		 * the hardware.
> +		 */
> +		mux->src_hwirq = be32_to_cpu(*imap);
> +		imap += IMAP_LENGTH;
> +
> +		dev_info(dev, "%u: %u mapped irq %u\n", i,  mux-
> >src_hwirq,
> +			 mux->irq);
> +
> +		ret = devm_request_irq(dev, mux->irq, irqmux_handler,
> +				       IRQF_SHARED | IRQF_NO_THREAD,
> +				       "irqmux", mux);
> +		if (ret < 0) {
> +			dev_err(dev, "failed to request IRQ: %d\n", ret);
> +			goto err;
> +		}
> +
> +		/* Set up the hardware to pass the interrupt through */
> +		writel(mux->src_hwirq, &regs[i]);
> +	}
> +
> +	dev_info(dev, "probed, %d gpio interrupts\n", priv->nr_irqs);
> +
> +	return 0;
> +
> +err:
> +	while (i--)
> +		irq_dispose_mapping(priv->mux[i].irq);
> +	irq_domain_remove(priv->irq_domain);
> +
> +	return ret;
> +}
> +
> +static int irqmux_remove(struct platform_device *pdev) {
> +	struct irqmux_priv *priv = platform_get_drvdata(pdev);
> +	unsigned int i;
> +
> +	for (i = 0; i < priv->nr_irqs; i++)
> +		irq_dispose_mapping(priv->mux[i].irq);
> +	irq_domain_remove(priv->irq_domain);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id irqmux_match[] = {
> +	{ .compatible = "renesas,rzn1-gpioirqmux", },
> +	{ /* sentinel */ },
> +};
> +
> +MODULE_DEVICE_TABLE(of, irqmux_match);
> +
> +static struct platform_driver irqmux_driver = {
> +	.driver = {
> +		.name = "gpio_irq_mux",
> +		.owner = THIS_MODULE,
> +		.of_match_table = irqmux_match,
> +	},
> +	.probe = irqmux_probe,
> +	.remove = irqmux_remove,
> +};
> +
> +module_platform_driver(irqmux_driver);
> +
> +MODULE_DESCRIPTION("Renesas RZ/N1 GPIO IRQ Multiplexer Driver");
> +MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
> +MODULE_LICENSE("GPL v2");
> --
> 2.17.1


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

* Re: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer
  2019-02-19 15:27   ` Phil Edworthy
@ 2019-02-19 15:39     ` Marc Zyngier
  2019-02-19 15:41       ` Phil Edworthy
  0 siblings, 1 reply; 10+ messages in thread
From: Marc Zyngier @ 2019-02-19 15:39 UTC (permalink / raw)
  To: Phil Edworthy
  Cc: Thomas Gleixner, Jason Cooper, Geert Uytterhoeven,
	linux-renesas-soc, linux-kernel

On Tue, 19 Feb 2019 15:27:25 +0000
Phil Edworthy <phil.edworthy@renesas.com> wrote:

> Hello,
> 
> Any comments on this patch?

Err... I'm afraid it fell through the cracks. It's been three months,
and I've paged out most of last year.

Can you please resend it on top of a recent -rc, and I'll try to have a
look. No promise though.

Thanks,

	M.

> 
> Thanks
> Phil
> 
> > -----Original Message-----
> > From: Phil Edworthy <phil.edworthy@renesas.com>
> > Sent: 13 November 2018 13:09
> > To: Marc Zyngier <marc.zyngier@arm.com>; Thomas Gleixner
> > <tglx@linutronix.de>; Jason Cooper <jason@lakedaemon.net>
> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>; linux-renesas-
> > soc@vger.kernel.org; linux-kernel@vger.kernel.org; Phil Edworthy
> > <phil.edworthy@renesas.com>
> > Subject: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO
> > interrupt multiplexer
> > 
> > On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > configured to have 32 interrupt outputs, so we have a total of 96 GPIO
> > interrupts. All of these are passed to the GPIO IRQ Muxer, which selects
> > 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals aren't
> > latched, so there is nothing to do in this driver when an interrupt is received,
> > other than tell the corresponding GPIO block.
> > 
> > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> > ---
> > v3:
> >  - Use 'interrupt-map' DT property to map the interrupts, this is very similar
> >    to PCIe MSI. The only difference is that we need to get hold of the interrupt
> >    specifier for the interupts coming into the irqmux.
> >  - Do not use a chained interrupt controller.
> > v2:
> >  - Use interrupt-map to allow the GPIO controller info to be specified
> >    as part of the irq.
> >  - Renamed struct and funcs from 'girq' to a more comprehenisble 'irqmux'.
> > ---
> >  drivers/irqchip/Kconfig        |   9 ++
> >  drivers/irqchip/Makefile       |   1 +
> >  drivers/irqchip/rzn1-irq-mux.c | 205
> > +++++++++++++++++++++++++++++++++
> >  3 files changed, 215 insertions(+)
> >  create mode 100644 drivers/irqchip/rzn1-irq-mux.c
> > 
> > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
> > 96451b581452..53c54bba1dd8 100644
> > --- a/drivers/irqchip/Kconfig
> > +++ b/drivers/irqchip/Kconfig
> > @@ -204,6 +204,15 @@ config RENESAS_IRQC
> >  	select GENERIC_IRQ_CHIP
> >  	select IRQ_DOMAIN
> > 
> > +config RENESAS_RZN1_IRQ_MUX
> > +	bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
> > +	depends on ARCH_RZN1
> > +	select IRQ_DOMAIN
> > +	help
> > +	  Say yes here to add support for the GPIO IRQ multiplexer
> > embedded
> > +	  in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
> > +	  the interrupts coming from the GPIO controllers are used.
> > +
> >  config ST_IRQCHIP
> >  	bool
> >  	select REGMAP
> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index
> > b822199445ff..b090f84dd42e 100644
> > --- a/drivers/irqchip/Makefile
> > +++ b/drivers/irqchip/Makefile
> > @@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)			+= irq-
> > sirfsoc.o
> >  obj-$(CONFIG_JCORE_AIC)			+= irq-jcore-aic.o
> >  obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
> >  obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
> > +obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX)	+= rzn1-irq-mux.o
> >  obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
> >  obj-$(CONFIG_ARCH_NSPIRE)		+= irq-zevio.o
> >  obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
> > diff --git a/drivers/irqchip/rzn1-irq-mux.c b/drivers/irqchip/rzn1-irq-mux.c
> > new file mode 100644 index 000000000000..ee7810b9b3f3
> > --- /dev/null
> > +++ b/drivers/irqchip/rzn1-irq-mux.c
> > @@ -0,0 +1,205 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * RZ/N1 GPIO Interrupt Multiplexer
> > + *
> > + * Copyright (C) 2018 Renesas Electronics Europe Limited
> > + *
> > + * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > +configured
> > + * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
> > + * All of these are passed to the GPIO IRQ Muxer, which selects 8 of
> > +the GPIO
> > + * interrupts to pass onto the GIC.
> > + */
> > +
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_platform.h>
> > +
> > +#define MAX_NR_INPUT_IRQS	96
> > +#define MAX_NR_OUTPUT_IRQS	8
> > +
> > +/*
> > + * "interrupt-map" consists of 1 interrupt cell, 0 address cells,
> > +phandle to
> > + * interrupt parent, and parent interrupt specifier (3 cells for GIC),
> > +giving
> > + * a total of 5 cells.
> > + */
> > +#define IMAP_LENGTH		5
> > +
> > +struct irqmux_priv;
> > +struct irqmux_one {
> > +	unsigned int irq;
> > +	unsigned int src_hwirq;
> > +	struct irqmux_priv *priv;
> > +};
> > +
> > +struct irqmux_priv {
> > +	struct device *dev;
> > +	struct irq_domain *irq_domain;
> > +	unsigned int nr_irqs;
> > +	struct irqmux_one mux[MAX_NR_OUTPUT_IRQS]; };
> > +
> > +static irqreturn_t irqmux_handler(int irq, void *data) {
> > +	struct irqmux_one *mux = data;
> > +	struct irqmux_priv *priv = mux->priv;
> > +	unsigned int virq;
> > +
> > +	virq = irq_find_mapping(priv->irq_domain, mux->src_hwirq);
> > +
> > +	generic_handle_irq(virq);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int irqmux_domain_map(struct irq_domain *h, unsigned int irq,
> > +			     irq_hw_number_t hwirq)
> > +{
> > +	irq_set_chip_data(irq, h->host_data);
> > +	irq_set_chip_and_handler(irq, &dummy_irq_chip,
> > handle_simple_irq);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct irq_domain_ops irqmux_domain_ops = {
> > +	.map = irqmux_domain_map,
> > +};
> > +
> > +static int irqmux_probe(struct platform_device *pdev) {
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *np = dev->of_node;
> > +	struct resource *res;
> > +	u32 __iomem *regs;
> > +	struct irqmux_priv *priv;
> > +	unsigned int i;
> > +	int nr_irqs;
> > +	int ret;
> > +	const __be32 *imap;
> > +	int imaplen;
> > +
> > +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +	if (!priv)
> > +		return -ENOMEM;
> > +
> > +	priv->dev = dev;
> > +	platform_set_drvdata(pdev, priv);
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	regs = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(regs))
> > +		return PTR_ERR(regs);
> > +
> > +	nr_irqs = of_irq_count(np);
> > +	if (nr_irqs < 0)
> > +		return nr_irqs;
> > +
> > +	if (nr_irqs > MAX_NR_OUTPUT_IRQS) {
> > +		dev_err(dev, "too many output interrupts\n");
> > +		return -ENOENT;
> > +	}
> > +
> > +	priv->nr_irqs = nr_irqs;
> > +
> > +	/* Look for the interrupt-map */
> > +	imap = of_get_property(np, "interrupt-map", &imaplen);
> > +	if (!imap)
> > +		return -ENOENT;
> > +	imaplen /= IMAP_LENGTH * sizeof(__be32);
> > +
> > +	/* Sometimes not all muxs are used */
> > +	if (imaplen < priv->nr_irqs)
> > +		priv->nr_irqs = imaplen;
> > +
> > +	/* Create IRQ domain for the interrupts coming from the GPIO blocks
> > */
> > +	priv->irq_domain = irq_domain_add_linear(np,
> > MAX_NR_INPUT_IRQS,
> > +						 &irqmux_domain_ops, priv);
> > +	if (!priv->irq_domain)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < MAX_NR_INPUT_IRQS; i++)
> > +		irq_create_mapping(priv->irq_domain, i);
> > +
> > +	for (i = 0; i < priv->nr_irqs; i++) {
> > +		struct irqmux_one *mux = &priv->mux[i];
> > +
> > +		ret = irq_of_parse_and_map(np, i);
> > +		if (ret < 0) {
> > +			ret = -ENOENT;
> > +			goto err;
> > +		}
> > +
> > +		mux->irq = ret;
> > +		mux->priv = priv;
> > +
> > +		/*
> > +		 * We need the first cell of the interrupt-map to configure
> > +		 * the hardware.
> > +		 */
> > +		mux->src_hwirq = be32_to_cpu(*imap);
> > +		imap += IMAP_LENGTH;
> > +
> > +		dev_info(dev, "%u: %u mapped irq %u\n", i,  mux-  
> > >src_hwirq,  
> > +			 mux->irq);
> > +
> > +		ret = devm_request_irq(dev, mux->irq, irqmux_handler,
> > +				       IRQF_SHARED | IRQF_NO_THREAD,
> > +				       "irqmux", mux);
> > +		if (ret < 0) {
> > +			dev_err(dev, "failed to request IRQ: %d\n", ret);
> > +			goto err;
> > +		}
> > +
> > +		/* Set up the hardware to pass the interrupt through */
> > +		writel(mux->src_hwirq, &regs[i]);
> > +	}
> > +
> > +	dev_info(dev, "probed, %d gpio interrupts\n", priv->nr_irqs);
> > +
> > +	return 0;
> > +
> > +err:
> > +	while (i--)
> > +		irq_dispose_mapping(priv->mux[i].irq);
> > +	irq_domain_remove(priv->irq_domain);
> > +
> > +	return ret;
> > +}
> > +
> > +static int irqmux_remove(struct platform_device *pdev) {
> > +	struct irqmux_priv *priv = platform_get_drvdata(pdev);
> > +	unsigned int i;
> > +
> > +	for (i = 0; i < priv->nr_irqs; i++)
> > +		irq_dispose_mapping(priv->mux[i].irq);
> > +	irq_domain_remove(priv->irq_domain);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id irqmux_match[] = {
> > +	{ .compatible = "renesas,rzn1-gpioirqmux", },
> > +	{ /* sentinel */ },
> > +};
> > +
> > +MODULE_DEVICE_TABLE(of, irqmux_match);
> > +
> > +static struct platform_driver irqmux_driver = {
> > +	.driver = {
> > +		.name = "gpio_irq_mux",
> > +		.owner = THIS_MODULE,
> > +		.of_match_table = irqmux_match,
> > +	},
> > +	.probe = irqmux_probe,
> > +	.remove = irqmux_remove,
> > +};
> > +
> > +module_platform_driver(irqmux_driver);
> > +
> > +MODULE_DESCRIPTION("Renesas RZ/N1 GPIO IRQ Multiplexer Driver");
> > +MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 2.17.1  
> 



-- 
Without deviation from the norm, progress is not possible.

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

* RE: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer
  2019-02-19 15:39     ` Marc Zyngier
@ 2019-02-19 15:41       ` Phil Edworthy
  0 siblings, 0 replies; 10+ messages in thread
From: Phil Edworthy @ 2019-02-19 15:41 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Thomas Gleixner, Jason Cooper, Geert Uytterhoeven,
	linux-renesas-soc, linux-kernel

Hi Marc,

> On Tue, 19 Feb 2019 15:27:25 +0000
> Phil Edworthy <phil.edworthy@renesas.com> wrote:
> 
> > Hello,
> >
> > Any comments on this patch?
> 
> Err... I'm afraid it fell through the cracks. It's been three months, and I've
> paged out most of last year.
> 
> Can you please resend it on top of a recent -rc, and I'll try to have a look. No
> promise though.

Thanks, appreciate it you can!
Phil

> 
> Thanks,
> 
> 	M.
> 
> >
> > Thanks
> > Phil
> >
> > > -----Original Message-----
> > > From: Phil Edworthy <phil.edworthy@renesas.com>
> > > Sent: 13 November 2018 13:09
> > > To: Marc Zyngier <marc.zyngier@arm.com>; Thomas Gleixner
> > > <tglx@linutronix.de>; Jason Cooper <jason@lakedaemon.net>
> > > Cc: Geert Uytterhoeven <geert@linux-m68k.org>; linux-renesas-
> > > soc@vger.kernel.org; linux-kernel@vger.kernel.org; Phil Edworthy
> > > <phil.edworthy@renesas.com>
> > > Subject: [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO
> > > interrupt multiplexer
> > >
> > > On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks each
> > > configured to have 32 interrupt outputs, so we have a total of 96
> > > GPIO interrupts. All of these are passed to the GPIO IRQ Muxer,
> > > which selects
> > > 8 of the GPIO interrupts to pass onto the GIC. The interrupt signals
> > > aren't latched, so there is nothing to do in this driver when an
> > > interrupt is received, other than tell the corresponding GPIO block.
> > >
> > > Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
> > > ---
> > > v3:
> > >  - Use 'interrupt-map' DT property to map the interrupts, this is very
> similar
> > >    to PCIe MSI. The only difference is that we need to get hold of the
> interrupt
> > >    specifier for the interupts coming into the irqmux.
> > >  - Do not use a chained interrupt controller.
> > > v2:
> > >  - Use interrupt-map to allow the GPIO controller info to be specified
> > >    as part of the irq.
> > >  - Renamed struct and funcs from 'girq' to a more comprehenisble
> 'irqmux'.
> > > ---
> > >  drivers/irqchip/Kconfig        |   9 ++
> > >  drivers/irqchip/Makefile       |   1 +
> > >  drivers/irqchip/rzn1-irq-mux.c | 205
> > > +++++++++++++++++++++++++++++++++
> > >  3 files changed, 215 insertions(+)
> > >  create mode 100644 drivers/irqchip/rzn1-irq-mux.c
> > >
> > > diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index
> > > 96451b581452..53c54bba1dd8 100644
> > > --- a/drivers/irqchip/Kconfig
> > > +++ b/drivers/irqchip/Kconfig
> > > @@ -204,6 +204,15 @@ config RENESAS_IRQC
> > >  	select GENERIC_IRQ_CHIP
> > >  	select IRQ_DOMAIN
> > >
> > > +config RENESAS_RZN1_IRQ_MUX
> > > +	bool "Renesas RZ/N1 GPIO IRQ multiplexer support"
> > > +	depends on ARCH_RZN1
> > > +	select IRQ_DOMAIN
> > > +	help
> > > +	  Say yes here to add support for the GPIO IRQ multiplexer
> > > embedded
> > > +	  in Renesas RZ/N1 SoC devices. The GPIO IRQ Muxer selects which of
> > > +	  the interrupts coming from the GPIO controllers are used.
> > > +
> > >  config ST_IRQCHIP
> > >  	bool
> > >  	select REGMAP
> > > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> > > index b822199445ff..b090f84dd42e 100644
> > > --- a/drivers/irqchip/Makefile
> > > +++ b/drivers/irqchip/Makefile
> > > @@ -45,6 +45,7 @@ obj-$(CONFIG_SIRF_IRQ)			+=
> irq-
> > > sirfsoc.o
> > >  obj-$(CONFIG_JCORE_AIC)			+= irq-jcore-aic.o
> > >  obj-$(CONFIG_RENESAS_INTC_IRQPIN)	+= irq-renesas-intc-irqpin.o
> > >  obj-$(CONFIG_RENESAS_IRQC)		+= irq-renesas-irqc.o
> > > +obj-$(CONFIG_RENESAS_RZN1_IRQ_MUX)	+= rzn1-irq-mux.o
> > >  obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
> > >  obj-$(CONFIG_ARCH_NSPIRE)		+= irq-zevio.o
> > >  obj-$(CONFIG_ARCH_VT8500)		+= irq-vt8500.o
> > > diff --git a/drivers/irqchip/rzn1-irq-mux.c
> > > b/drivers/irqchip/rzn1-irq-mux.c new file mode 100644 index
> > > 000000000000..ee7810b9b3f3
> > > --- /dev/null
> > > +++ b/drivers/irqchip/rzn1-irq-mux.c
> > > @@ -0,0 +1,205 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * RZ/N1 GPIO Interrupt Multiplexer
> > > + *
> > > + * Copyright (C) 2018 Renesas Electronics Europe Limited
> > > + *
> > > + * On RZ/N1 devices, there are 3 Synopsys DesignWare GPIO blocks
> > > +each configured
> > > + * to have 32 interrupt outputs, so we have a total of 96 GPIO interrupts.
> > > + * All of these are passed to the GPIO IRQ Muxer, which selects 8
> > > +of the GPIO
> > > + * interrupts to pass onto the GIC.
> > > + */
> > > +
> > > +#include <linux/interrupt.h>
> > > +#include <linux/irq.h>
> > > +#include <linux/irqdomain.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of_irq.h>
> > > +#include <linux/of_platform.h>
> > > +
> > > +#define MAX_NR_INPUT_IRQS	96
> > > +#define MAX_NR_OUTPUT_IRQS	8
> > > +
> > > +/*
> > > + * "interrupt-map" consists of 1 interrupt cell, 0 address cells,
> > > +phandle to
> > > + * interrupt parent, and parent interrupt specifier (3 cells for
> > > +GIC), giving
> > > + * a total of 5 cells.
> > > + */
> > > +#define IMAP_LENGTH		5
> > > +
> > > +struct irqmux_priv;
> > > +struct irqmux_one {
> > > +	unsigned int irq;
> > > +	unsigned int src_hwirq;
> > > +	struct irqmux_priv *priv;
> > > +};
> > > +
> > > +struct irqmux_priv {
> > > +	struct device *dev;
> > > +	struct irq_domain *irq_domain;
> > > +	unsigned int nr_irqs;
> > > +	struct irqmux_one mux[MAX_NR_OUTPUT_IRQS]; };
> > > +
> > > +static irqreturn_t irqmux_handler(int irq, void *data) {
> > > +	struct irqmux_one *mux = data;
> > > +	struct irqmux_priv *priv = mux->priv;
> > > +	unsigned int virq;
> > > +
> > > +	virq = irq_find_mapping(priv->irq_domain, mux->src_hwirq);
> > > +
> > > +	generic_handle_irq(virq);
> > > +
> > > +	return IRQ_HANDLED;
> > > +}
> > > +
> > > +static int irqmux_domain_map(struct irq_domain *h, unsigned int irq,
> > > +			     irq_hw_number_t hwirq)
> > > +{
> > > +	irq_set_chip_data(irq, h->host_data);
> > > +	irq_set_chip_and_handler(irq, &dummy_irq_chip,
> > > handle_simple_irq);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct irq_domain_ops irqmux_domain_ops = {
> > > +	.map = irqmux_domain_map,
> > > +};
> > > +
> > > +static int irqmux_probe(struct platform_device *pdev) {
> > > +	struct device *dev = &pdev->dev;
> > > +	struct device_node *np = dev->of_node;
> > > +	struct resource *res;
> > > +	u32 __iomem *regs;
> > > +	struct irqmux_priv *priv;
> > > +	unsigned int i;
> > > +	int nr_irqs;
> > > +	int ret;
> > > +	const __be32 *imap;
> > > +	int imaplen;
> > > +
> > > +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > > +	if (!priv)
> > > +		return -ENOMEM;
> > > +
> > > +	priv->dev = dev;
> > > +	platform_set_drvdata(pdev, priv);
> > > +
> > > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > +	regs = devm_ioremap_resource(dev, res);
> > > +	if (IS_ERR(regs))
> > > +		return PTR_ERR(regs);
> > > +
> > > +	nr_irqs = of_irq_count(np);
> > > +	if (nr_irqs < 0)
> > > +		return nr_irqs;
> > > +
> > > +	if (nr_irqs > MAX_NR_OUTPUT_IRQS) {
> > > +		dev_err(dev, "too many output interrupts\n");
> > > +		return -ENOENT;
> > > +	}
> > > +
> > > +	priv->nr_irqs = nr_irqs;
> > > +
> > > +	/* Look for the interrupt-map */
> > > +	imap = of_get_property(np, "interrupt-map", &imaplen);
> > > +	if (!imap)
> > > +		return -ENOENT;
> > > +	imaplen /= IMAP_LENGTH * sizeof(__be32);
> > > +
> > > +	/* Sometimes not all muxs are used */
> > > +	if (imaplen < priv->nr_irqs)
> > > +		priv->nr_irqs = imaplen;
> > > +
> > > +	/* Create IRQ domain for the interrupts coming from the GPIO
> > > +blocks
> > > */
> > > +	priv->irq_domain = irq_domain_add_linear(np,
> > > MAX_NR_INPUT_IRQS,
> > > +						 &irqmux_domain_ops, priv);
> > > +	if (!priv->irq_domain)
> > > +		return -ENOMEM;
> > > +
> > > +	for (i = 0; i < MAX_NR_INPUT_IRQS; i++)
> > > +		irq_create_mapping(priv->irq_domain, i);
> > > +
> > > +	for (i = 0; i < priv->nr_irqs; i++) {
> > > +		struct irqmux_one *mux = &priv->mux[i];
> > > +
> > > +		ret = irq_of_parse_and_map(np, i);
> > > +		if (ret < 0) {
> > > +			ret = -ENOENT;
> > > +			goto err;
> > > +		}
> > > +
> > > +		mux->irq = ret;
> > > +		mux->priv = priv;
> > > +
> > > +		/*
> > > +		 * We need the first cell of the interrupt-map to configure
> > > +		 * the hardware.
> > > +		 */
> > > +		mux->src_hwirq = be32_to_cpu(*imap);
> > > +		imap += IMAP_LENGTH;
> > > +
> > > +		dev_info(dev, "%u: %u mapped irq %u\n", i,  mux-
> > > >src_hwirq,
> > > +			 mux->irq);
> > > +
> > > +		ret = devm_request_irq(dev, mux->irq, irqmux_handler,
> > > +				       IRQF_SHARED | IRQF_NO_THREAD,
> > > +				       "irqmux", mux);
> > > +		if (ret < 0) {
> > > +			dev_err(dev, "failed to request IRQ: %d\n", ret);
> > > +			goto err;
> > > +		}
> > > +
> > > +		/* Set up the hardware to pass the interrupt through */
> > > +		writel(mux->src_hwirq, &regs[i]);
> > > +	}
> > > +
> > > +	dev_info(dev, "probed, %d gpio interrupts\n", priv->nr_irqs);
> > > +
> > > +	return 0;
> > > +
> > > +err:
> > > +	while (i--)
> > > +		irq_dispose_mapping(priv->mux[i].irq);
> > > +	irq_domain_remove(priv->irq_domain);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static int irqmux_remove(struct platform_device *pdev) {
> > > +	struct irqmux_priv *priv = platform_get_drvdata(pdev);
> > > +	unsigned int i;
> > > +
> > > +	for (i = 0; i < priv->nr_irqs; i++)
> > > +		irq_dispose_mapping(priv->mux[i].irq);
> > > +	irq_domain_remove(priv->irq_domain);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct of_device_id irqmux_match[] = {
> > > +	{ .compatible = "renesas,rzn1-gpioirqmux", },
> > > +	{ /* sentinel */ },
> > > +};
> > > +
> > > +MODULE_DEVICE_TABLE(of, irqmux_match);
> > > +
> > > +static struct platform_driver irqmux_driver = {
> > > +	.driver = {
> > > +		.name = "gpio_irq_mux",
> > > +		.owner = THIS_MODULE,
> > > +		.of_match_table = irqmux_match,
> > > +	},
> > > +	.probe = irqmux_probe,
> > > +	.remove = irqmux_remove,
> > > +};
> > > +
> > > +module_platform_driver(irqmux_driver);
> > > +
> > > +MODULE_DESCRIPTION("Renesas RZ/N1 GPIO IRQ Multiplexer Driver");
> > > +MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
> > > +MODULE_LICENSE("GPL v2");
> > > --
> > > 2.17.1
> >
> 
> 
> 
> --
> Without deviation from the norm, progress is not possible.

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

end of thread, other threads:[~2019-02-19 15:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-13 13:09 [PATCH v3 0/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
2018-11-13 13:09 ` [PATCH v3 1/2] dt-bindings/interrupt-controller: rzn1: Add RZ/N1 gpio irq mux binding Phil Edworthy
2018-11-17 14:32   ` Rob Herring
2018-11-19  9:39     ` Phil Edworthy
2018-11-19 21:50       ` Rob Herring
2018-11-20 10:30         ` Phil Edworthy
2018-11-13 13:09 ` [PATCH v3 2/2] irqchip: Add support for Renesas RZ/N1 GPIO interrupt multiplexer Phil Edworthy
2019-02-19 15:27   ` Phil Edworthy
2019-02-19 15:39     ` Marc Zyngier
2019-02-19 15:41       ` Phil Edworthy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).