openbmc.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
Cc: devicetree@vger.kernel.org, Tomer Maimon <tmaimon77@gmail.com>,
	Avi Fishman <avifishman70@gmail.com>,
	Patrick Venture <venture@google.com>,
	openbmc@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	Tali Perry <tali.perry1@gmail.com>,
	Russell King <linux@armlinux.org.uk>,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-arm-kernel@lists.infradead.org,
	Benjamin Fair <benjaminfair@google.com>
Subject: Re: [PATCH 08/14] irqchip: Add driver for WPCM450 interrupt controller
Date: Wed, 24 Mar 2021 17:16:35 +0000	[thread overview]
Message-ID: <87sg4kiia4.wl-maz@kernel.org> (raw)
In-Reply-To: <20210320181610.680870-9-j.neuschaefer@gmx.net>

On Sat, 20 Mar 2021 18:16:04 +0000,
Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
> 
> The WPCM450 AIC ("Advanced Interrupt Controller") is the interrupt
> controller found in the Nuvoton WPCM450 SoC and other Winbond/Nuvoton
> SoCs.
> 
> The list of registers if based on the AMI vendor kernel and the
> Nuvoton W90N745 datasheet.
> 
> Although the hardware supports other interrupt modes, the driver only
> supports high-level interrupts at the moment, because other modes could
> not be tested so far.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
>  arch/arm/mach-npcm/Kconfig        |   1 +
>  drivers/irqchip/Kconfig           |   6 ++
>  drivers/irqchip/Makefile          |   1 +
>  drivers/irqchip/irq-wpcm450-aic.c | 162 ++++++++++++++++++++++++++++++
>  4 files changed, 170 insertions(+)
>  create mode 100644 drivers/irqchip/irq-wpcm450-aic.c
> 
> diff --git a/arch/arm/mach-npcm/Kconfig b/arch/arm/mach-npcm/Kconfig
> index 658c8efb4ca14..a71cf1d189ae5 100644
> --- a/arch/arm/mach-npcm/Kconfig
> +++ b/arch/arm/mach-npcm/Kconfig
> @@ -10,6 +10,7 @@ config ARCH_WPCM450
>  	bool "Support for WPCM450 BMC (Hermon)"
>  	depends on ARCH_MULTI_V5
>  	select CPU_ARM926T
> +	select WPCM450_AIC
>  	select NPCM7XX_TIMER
>  	help
>  	  General support for WPCM450 BMC (Hermon).
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index e74fa206240a1..baf4efec31c67 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -586,4 +586,10 @@ config MST_IRQ
>  	help
>  	  Support MStar Interrupt Controller.
> 
> +config WPCM450_AIC
> +	bool "Nuvoton WPCM450 Advanced Interrupt Controller"
> +	depends on ARCH_WPCM450 || COMPILE_TEST
> +	help
> +	  Support for the interrupt controller in the Nuvoton WPCM450 BMC SoC.
> +
>  endmenu
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index c59b95a0532c9..bef57937e7296 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -113,3 +113,4 @@ obj-$(CONFIG_LOONGSON_PCH_MSI)		+= irq-loongson-pch-msi.o
>  obj-$(CONFIG_MST_IRQ)			+= irq-mst-intc.o
>  obj-$(CONFIG_SL28CPLD_INTC)		+= irq-sl28cpld.o
>  obj-$(CONFIG_MACH_REALTEK_RTL)		+= irq-realtek-rtl.o
> +obj-$(CONFIG_WPCM450_AIC)		+= irq-wpcm450-aic.o
> diff --git a/drivers/irqchip/irq-wpcm450-aic.c b/drivers/irqchip/irq-wpcm450-aic.c
> new file mode 100644
> index 0000000000000..0d6dd8b1fc824
> --- /dev/null
> +++ b/drivers/irqchip/irq-wpcm450-aic.c
> @@ -0,0 +1,162 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright 2021 Jonathan Neuschäfer
> +
> +#include <linux/console.h>

That's unexpected. Why do you need this?

> +#include <linux/irqchip.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +
> +#include <asm/exception.h>
> +
> +#define AIC_SCR(x)	((x)*4)	/* Source control registers */
> +#define AIC_GEN		0x84
> +#define AIC_GRSR	0x88
> +#define AIC_IRSR	0x100	/* Interrupt raw status register */
> +#define AIC_IASR	0x104	/* Interrupt active status register */
> +#define AIC_ISR		0x108	/* Interrupt status register */
> +#define AIC_IPER	0x10c	/* Interrupt priority encoding register */
> +#define AIC_ISNR	0x110	/* Interrupt source number register */
> +#define AIC_IMR		0x114	/* Interrupt mask register */
> +#define AIC_OISR	0x118	/* Output interrupt status register */
> +#define AIC_MECR	0x120	/* Mask enable command register */
> +#define AIC_MDCR	0x124	/* Mask disable command register */
> +#define AIC_SSCR	0x128	/* Source set command register */
> +#define AIC_SCCR	0x12c	/* Source clear command register */
> +#define AIC_EOSCR	0x130	/* End of service command register */
> +
> +#define AIC_SCR_SRCTYPE_LOW_LEVEL	(0 << 6)
> +#define AIC_SCR_SRCTYPE_HIGH_LEVEL	(1 << 6)
> +#define AIC_SCR_SRCTYPE_NEG_EDGE	(2 << 6)
> +#define AIC_SCR_SRCTYPE_POS_EDGE	(3 << 6)
> +#define AIC_SCR_PRIORITY(x)		(x)

A mask would be welcomed for this field.

> +
> +#define IRQS		32

Please use something a bit less generic.

> +
> +struct wpcm450_aic {
> +	void __iomem *regs;
> +	struct irq_domain *domain;
> +};
> +
> +static struct wpcm450_aic *aic;
> +
> +static void wpcm450_aic_init_hw(void)
> +{
> +	int i;
> +
> +	/* Disable (mask) all interrupts */
> +	writel(0xffffffff, aic->regs + AIC_MDCR);

Consider using relaxed accessors throughout this driver.

> +
> +	/*
> +	 * Make sure the interrupt controller is ready to serve new interrupts.
> +	 * Reading from IPER indicates that the nIRQ signal may be deasserted,
> +	 * and writing to EOSCR indicates that interrupt handling has finished.
> +	 */
> +	readl(aic->regs + AIC_IPER);
> +	writel(0, aic->regs + AIC_EOSCR);
> +
> +	/* Initialize trigger mode and priority of each interrupt source */
> +	for (i = 0; i < IRQS; i++)
> +		writel(AIC_SCR_SRCTYPE_HIGH_LEVEL | AIC_SCR_PRIORITY(7),
> +		       aic->regs + AIC_SCR(i));
> +}
> +
> +static void __exception_irq_entry wpcm450_aic_handle_irq(struct pt_regs *regs)
> +{
> +	int hwirq;
> +
> +	/* Determine the interrupt source */
> +	/* Read IPER to signal that nIRQ can be de-asserted */
> +	hwirq = readl(aic->regs + AIC_IPER) / 4;
> +
> +	handle_domain_irq(aic->domain, hwirq, regs);
> +}
> +
> +static void wpcm450_aic_ack(struct irq_data *d)
> +{
> +	/* Signal end-of-service */
> +	writel(0, aic->regs + AIC_EOSCR);

Is that an Ack or an EOI? My gut feeling is that the above read is the
Ack, and that this write should actually be an EOI callback.

> +}
> +
> +static void wpcm450_aic_mask(struct irq_data *d)
> +{
> +	unsigned int mask = 1U << d->hwirq;

Consider using BIT().

> +
> +	/* Disable (mask) the interrupt */
> +	writel(mask, aic->regs + AIC_MDCR);
> +}
> +
> +static void wpcm450_aic_unmask(struct irq_data *d)
> +{
> +	unsigned int mask = 1U << d->hwirq;
> +
> +	/* Enable (unmask) the interrupt */
> +	writel(mask, aic->regs + AIC_MECR);
> +}
> +
> +static int wpcm450_aic_set_type(struct irq_data *d, unsigned int flow_type)
> +{
> +	/*
> +	 * The hardware supports high/low level, as well as rising/falling edge
> +	 * modes, and the DT binding accommodates for that, but as long as
> +	 * other modes than high level mode are not used and can't be tested,
> +	 * they are rejected in this driver.
> +	 */
> +	if ((flow_type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_HIGH) {
> +		pr_err("IRQ mode %#x is not supported\n", flow_type);

The core kernel shouts loudly enough, no need for extra messages.

> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct irq_chip wpcm450_aic_chip = {
> +	.name = "wpcm450-aic",
> +	.irq_ack = wpcm450_aic_ack,
> +	.irq_mask = wpcm450_aic_mask,
> +	.irq_unmask = wpcm450_aic_unmask,
> +	.irq_set_type = wpcm450_aic_set_type,
> +};
> +
> +static int wpcm450_aic_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq)
> +{
> +	if (hwirq > IRQS)
> +		return -EPERM;
> +
> +	irq_set_chip_and_handler(irq, &wpcm450_aic_chip, handle_level_irq);
> +	irq_set_chip_data(irq, aic);
> +	irq_set_probe(irq);
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops wpcm450_aic_ops = {
> +	.map = wpcm450_aic_map,
> +	.xlate = irq_domain_xlate_twocell,
> +};
> +
> +static int __init wpcm450_aic_of_init(struct device_node *node,
> +				      struct device_node *parent)
> +{
> +	if (parent)
> +		return -EINVAL;
> +
> +	aic = kzalloc(sizeof(*aic), GFP_KERNEL);
> +	if (!aic)
> +		return -ENOMEM;
> +
> +	aic->regs = of_iomap(node, 0);
> +	if (!aic->regs) {
> +		pr_err("Failed to map WPCM450 AIC registers\n");
> +		return -ENOMEM;
> +	}
> +
> +	wpcm450_aic_init_hw();
> +
> +	set_handle_irq(wpcm450_aic_handle_irq);
> +
> +	aic->domain = irq_domain_add_linear(node, IRQS, &wpcm450_aic_ops, aic);
> +
> +	return 0;
> +}
> +
> +IRQCHIP_DECLARE(wpcm450_aic, "nuvoton,wpcm450-aic", wpcm450_aic_of_init);

Otherwise, looks good.

	M.

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

  reply	other threads:[~2021-03-24 17:17 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-20 18:15 [PATCH 00/14] Initial support for Nuvoton WPCM450 BMC SoC Jonathan Neuschäfer
2021-03-20 18:15 ` [PATCH 01/14] dt-bindings: vendor-prefixes: Add Supermicro Jonathan Neuschäfer
2021-03-27 16:36   ` Rob Herring
2021-03-20 18:15 ` [PATCH 02/14] dt-bindings: arm: npcm: Add nuvoton, wpcm450 compatible string Jonathan Neuschäfer
2021-03-27 16:36   ` Rob Herring
2021-03-20 18:15 ` [PATCH 03/14] dt-bindings: interrupt-controller: Add nuvoton, wpcm450-aic Jonathan Neuschäfer
2021-03-27 16:37   ` Rob Herring
2021-03-20 18:16 ` [PATCH 04/14] dt-bindings: serial: 8250: Add nuvoton,wpcm450-uart Jonathan Neuschäfer
2021-03-27 16:37   ` [PATCH 04/14] dt-bindings: serial: 8250: Add nuvoton, wpcm450-uart Rob Herring
2021-03-20 18:16 ` [PATCH 05/14] dt-bindings: timer: nuvoton,npcm7xx: Add wpcm450-timer Jonathan Neuschäfer
2021-03-27 16:39   ` Rob Herring
2021-04-04 20:28   ` Daniel Lezcano
2021-03-20 18:16 ` [PATCH 06/14] dt-bindings: watchdog: npcm: Add nuvoton,wpcm450-wdt Jonathan Neuschäfer
2021-03-27 16:39   ` Rob Herring
2021-03-20 18:16 ` [PATCH 07/14] ARM: npcm: Introduce Nuvoton WPCM450 SoC Jonathan Neuschäfer
2021-03-20 18:16 ` [PATCH 08/14] irqchip: Add driver for WPCM450 interrupt controller Jonathan Neuschäfer
2021-03-24 17:16   ` Marc Zyngier [this message]
2021-03-26 18:52     ` Jonathan Neuschäfer
2021-04-05 17:25       ` Jonathan Neuschäfer
2021-03-20 18:16 ` [PATCH 09/14] serial: 8250_of: Add nuvoton,wpcm450-uart Jonathan Neuschäfer
2021-03-20 18:16 ` [PATCH 10/14] clocksource/drivers/npcm: Add support for WPCM450 Jonathan Neuschäfer
2021-03-22 10:46   ` Daniel Lezcano
2021-03-20 18:16 ` [PATCH 11/14] watchdog: npcm: " Jonathan Neuschäfer
2021-03-20 20:24   ` Guenter Roeck
2021-03-20 20:43     ` Jonathan Neuschäfer
2021-03-20 18:16 ` [PATCH 12/14] ARM: dts: Add devicetree for Nuvoton WPCM450 BMC chip Jonathan Neuschäfer
2021-03-20 18:16 ` [PATCH 13/14] ARM: dts: Add devicetree for Supermicro X9SCi-LN4F based on WPCM450 Jonathan Neuschäfer
2021-03-20 18:44   ` Jonathan Neuschäfer
2021-03-20 18:16 ` [PATCH 14/14] MAINTAINERS: Nuvoton NPCM: Add wpcm patterns Jonathan Neuschäfer
2021-03-20 18:47 ` [PATCH 00/14] Initial support for Nuvoton WPCM450 BMC SoC Jonathan Neuschäfer
2021-03-21 11:07 ` Tomer Maimon
2021-03-21 12:31   ` Jonathan Neuschäfer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87sg4kiia4.wl-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=avifishman70@gmail.com \
    --cc=benjaminfair@google.com \
    --cc=devicetree@vger.kernel.org \
    --cc=j.neuschaefer@gmx.net \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=openbmc@lists.ozlabs.org \
    --cc=tali.perry1@gmail.com \
    --cc=tglx@linutronix.de \
    --cc=tmaimon77@gmail.com \
    --cc=venture@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).