Hi Marc, On 31 October 2018 15:31, Marc Zyngier wrote: > On 31/10/18 15:09, Phil Edworthy wrote: > > On 31 October 2018 08:02, Marc Zyngier wote: > >> On Tue, 30 Oct 2018 10:44:38 +0000, Phil Edworthy wrote: > >>> > >>> 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@xxxxxxxxxxx> > >>> --- > >>> 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 | 10 ++ > >>> drivers/irqchip/Makefile | 1 + > >>> drivers/irqchip/rzn1-irq-mux.c | 235 > >>> +++++++++++++++++++++++++++++++++ > >>> 3 files changed, 246 insertions(+) > >>> create mode 100644 drivers/irqchip/rzn1-irq-mux.c > >>> > >>> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index > >>> 96451b581452..3a60a8af60dd 100644 > >>> --- a/drivers/irqchip/Kconfig > >>> +++ b/drivers/irqchip/Kconfig > >>> @@ -204,6 +204,16 @@ 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 > >>> + select IRQ_DOMAIN_HIERARCHY > >>> + 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..767ce67e34d2 > >>> --- /dev/null > >>> +++ b/drivers/irqchip/rzn1-irq-mux.c > >>> @@ -0,0 +1,235 @@ > >>> +// 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/bitops.h> > >>> +#include <linux/interrupt.h> > >>> +#include <linux/irq.h> > >>> +#include <linux/irqchip/chained_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 GPIO_IRQ_SPEC_SIZE 3 > >>> +#define MAX_NR_GPIO_CONTROLLERS 3 > >>> +#define MAX_NR_GPIO_IRQ 32 > >>> +#define MAX_NR_INPUT_IRQS (MAX_NR_GPIO_CONTROLLERS * > >> MAX_NR_GPIO_IRQ) > >>> +#define MAX_NR_OUTPUT_IRQS 8 > >>> + > >>> +struct irqmux_priv; > >>> +struct irqmux_one { > >>> + unsigned int mapped_irq; > >>> + unsigned int input_irq_nr; > >>> + struct irqmux_priv *priv; > >>> +}; > >>> + > >>> +struct irqmux_priv { > >>> + struct device *dev; > >>> + struct irq_chip irq_chip; > >> > >> Do we really need this to be per-device? See below. > > I thought we generally wanted everything to be per-device so that we > > can cope when someone sticks two of these in a device. Am I wrong? > > This only contains function pointers that are specific to a particular type of > interrupt controller. Nothing in struct irq_chip is instance-specific. Ah, I see! <snip> > >> OK, that's where I think we have a problem. Your irqchip structure > >> seem to only be used to display a name?!? > > Right, that wasn't the intention! So, how do I hook in my own > > interrupt handler without calling irq_set_chip_and_handler()? > > That's what led me to think I need an irq_chip instance. > > That's the thing, you don't need it. each irq_chip is just a bunch of methods, > and these methods apply to all the instances of the same controller. > > >> To start with, that's not really the primary use for this object, and > >> I'd like it to be a single static structure for the whole driver. > >> Userspace doesn't need to know about the name, so please get rid of > this. > >> > >> The real issue is that you build the whole thing as a chained > >> interrupt controller, meaning that nothing controls the masking of > >> the interrupt. If, as I understand it, this IP is an interrupt router > >> that selects 8 out of 32 interrupts and passes them onto the GIC, > >> then a noisy device can just take the whole CPU down by keeping the line > asserted, and SW cannot mask it. > > The interrupts into this mux come from GPIO blocks that do the > > masking. The GPIO blocks in this case are standard Synopsys IP blocks. > > There is nothing in the irq mux hardware that can mask them, or do > > anything other than select which one to use, hence why this is a > > chained interrupt controller. Should I be using something else in this case? > > There are two cases: > 1) there is 1:1 mapping between a used input and an output, leaving some > input unused > 2) there is an n:1 mapping between input and output, and all the input can be > used at any given time > > If what you have is (1), you need to implement an hierarchy. > If what you have is (2), you need to implement a chained controller. > > (1) requires you to revisit this driver, making it a lot more like ti's irq-crossbar > (2) requires you to actually do some decoding in the chained handler > > I believe you're in configuration (1). Am I right? Right, it's a 1:1 mapping. The information about which input to be used needs to be specified in dt. I didn’t think I could implement a hierarchy that didn’t mask the interrupts, so I need to go back over that and look again... Many thanks! Phil > Thanks, > > M. > -- > Jazz is not dead. It just smells funny...