From: Marc Zyngier <marc.zyngier@arm.com>
To: Joshua Henderson <joshua.henderson@microchip.com>,
linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org, ralf@linux-mips.org,
Cristian Birsan <cristian.birsan@microchip.com>,
Thomas Gleixner <tglx@linutronix.de>,
Jason Cooper <jason@lakedaemon.net>
Subject: Re: [PATCH v2 02/14] irqchip: irq-pic32-evic: Add support for PIC32 interrupt controller
Date: Tue, 15 Dec 2015 17:00:11 +0000 [thread overview]
Message-ID: <5670471B.6090608@arm.com> (raw)
In-Reply-To: <1450133093-7053-3-git-send-email-joshua.henderson@microchip.com>
On 14/12/15 22:42, Joshua Henderson wrote:
> From: Cristian Birsan <cristian.birsan@microchip.com>
>
> This adds support for the interrupt controller present on PIC32 class
> devices.
>
> The following features are supported:
> - DT properties for EVIC and for devices that use interrupt lines
> - Persistent and non-persistent interrupt handling
> - irqdomain support
>
> Signed-off-by: Cristian Birsan <cristian.birsan@microchip.com>
> Signed-off-by: Joshua Henderson <joshua.henderson@microchip.com>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> ---
> drivers/irqchip/Makefile | 1 +
> drivers/irqchip/irq-pic32-evic.c | 321 ++++++++++++++++++++++++++++++++++++
> include/linux/irqchip/pic32-evic.h | 19 +++
> 3 files changed, 341 insertions(+)
> create mode 100644 drivers/irqchip/irq-pic32-evic.c
> create mode 100644 include/linux/irqchip/pic32-evic.h
>
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index 177f78f..e3608fc 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
> obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
> obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
> obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
> +obj-$(CONFIG_MACH_PIC32) += irq-pic32-evic.o
> diff --git a/drivers/irqchip/irq-pic32-evic.c b/drivers/irqchip/irq-pic32-evic.c
> new file mode 100644
> index 0000000..6a7747c
> --- /dev/null
> +++ b/drivers/irqchip/irq-pic32-evic.c
> @@ -0,0 +1,321 @@
> +/*
> + * Cristian Birsan <cristian.birsan@microchip.com>
> + * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqchip/pic32-evic.h>
> +
> +#include <asm/irq.h>
> +#include <asm/traps.h>
> +
> +#define CORE_TIMER_INTERRUPT 0
> +#define EXTERNAL_INTERRUPT_0 3
> +#define EXTERNAL_INTERRUPT_1 8
> +#define EXTERNAL_INTERRUPT_2 13
> +#define EXTERNAL_INTERRUPT_3 18
> +#define EXTERNAL_INTERRUPT_4 23
> +
> +#define PRI_MASK 0x7 /* 3 bit priority mask */
> +#define SUBPRI_MASK 0x3 /* 2 bit subpriority mask */
> +#define INT_MASK 0x1F /* 5 bit pri and subpri mask */
> +#define NR_EXT_IRQS 5 /* 5 external interrupts sources */
> +
> +#define PIC32_INT_PRI(pri, subpri) \
> + (((pri & PRI_MASK) << 2) | (subpri & SUBPRI_MASK))
> +#define DEFAULT_PIC32_INT_PRI PIC32_INT_PRI(2, 0)
> +
> +static struct irq_domain *evic_irq_domain;
> +static struct evic __iomem *evic_base;
> +
> +static unsigned int *evic_irq_prio;
> +
> +struct pic_reg {
> + u32 val; /* value register*/
> + u32 clr; /* clear register */
> + u32 set; /* set register */
> + u32 inv; /* inv register */
> +} __packed;
> +
> +struct evic {
> + struct pic_reg intcon;
> + struct pic_reg priss;
> + struct pic_reg intstat;
> + struct pic_reg iptmr;
> + struct pic_reg ifs[6];
> + u32 reserved1[8];
> + struct pic_reg iec[6];
> + u32 reserved2[8];
> + struct pic_reg ipc[48];
> + u32 reserved3[64];
> + u32 off[191];
> +} __packed;
> +
> +static int get_ext_irq_index(irq_hw_number_t hw);
> +static void evic_set_ext_irq_polarity(int ext_irq, u32 type);
> +
> +#define BIT_REG_MASK(bit, reg, mask) \
> + do { \
> + reg = bit/32; \
> + mask = 1 << (bit % 32); \
> + } while (0)
> +
> +asmlinkage void __weak plat_irq_dispatch(void)
> +{
> + unsigned int irq, hwirq;
> + u32 reg, mask;
> +
> + hwirq = readl(&evic_base->intstat.val) & 0xFF;
> +
> + /* Check if the interrupt was really triggered by hardware*/
> + BIT_REG_MASK(hwirq, reg, mask);
> + if (likely(readl(&evic_base->ifs[reg].val) &
> + readl(&evic_base->iec[reg].val) & mask)) {
> + irq = irq_linear_revmap(evic_irq_domain, hwirq);
> + do_IRQ(irq);
> + } else
> + spurious_interrupt();
> +}
> +
> +/* mask off an interrupt */
> +static inline void mask_pic32_irq(struct irq_data *irqd)
> +{
> + u32 reg, mask;
> + unsigned int hwirq = irqd_to_hwirq(irqd);
> +
> + BIT_REG_MASK(hwirq, reg, mask);
> + writel(mask, &evic_base->iec[reg].clr);
> +}
> +
> +/* unmask an interrupt */
> +static inline void unmask_pic32_irq(struct irq_data *irqd)
> +{
> + u32 reg, mask;
> + unsigned int hwirq = irqd_to_hwirq(irqd);
> +
> + BIT_REG_MASK(hwirq, reg, mask);
> + writel(mask, &evic_base->iec[reg].set);
> +}
> +
> +/* acknowledge an interrupt */
> +static void ack_pic32_irq(struct irq_data *irqd)
> +{
> + u32 reg, mask;
> + unsigned int hwirq = irqd_to_hwirq(irqd);
> +
> + BIT_REG_MASK(hwirq, reg, mask);
> + writel(mask, &evic_base->ifs[reg].clr);
> +}
> +
> +/* mask off and acknowledge an interrupt */
> +static inline void mask_ack_pic32_irq(struct irq_data *irqd)
> +{
> + u32 reg, mask;
> + unsigned int hwirq = irqd_to_hwirq(irqd);
> +
> + BIT_REG_MASK(hwirq, reg, mask);
> + writel(mask, &evic_base->iec[reg].clr);
> + writel(mask, &evic_base->ifs[reg].clr);
> +}
> +
> +static int set_type_pic32_irq(struct irq_data *data, unsigned int flow_type)
> +{
> + int index;
> +
> + switch (flow_type) {
> +
> + case IRQ_TYPE_EDGE_RISING:
> + case IRQ_TYPE_EDGE_FALLING:
> + irq_set_handler_locked(data, handle_edge_irq);
> + break;
> +
> + case IRQ_TYPE_LEVEL_HIGH:
> + case IRQ_TYPE_LEVEL_LOW:
> + irq_set_handler_locked(data, handle_fasteoi_irq);
> + break;
> +
> + default:
> + pr_err("Invalid interrupt type !\n");
> + return -EINVAL;
> + }
> +
> + /* set polarity for external interrupts only */
> + index = get_ext_irq_index(data->hwirq);
> + if (index >= 0)
> + evic_set_ext_irq_polarity(index, flow_type);
> +
> + return IRQ_SET_MASK_OK;
> +}
> +
> +static void pic32_bind_evic_interrupt(int irq, int set)
> +{
> + writel(set, &evic_base->off[irq]);
> +}
> +
> +int pic32_get_c0_compare_int(void)
> +{
> + int virq;
> +
> + virq = irq_create_mapping(evic_irq_domain, CORE_TIMER_INTERRUPT);
> + irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
> + return virq;
> +}
> +
> +static struct irq_chip pic32_irq_chip = {
> + .name = "PIC32-EVIC",
> + .irq_ack = ack_pic32_irq,
> + .irq_mask = mask_pic32_irq,
> + .irq_mask_ack = mask_ack_pic32_irq,
> + .irq_unmask = unmask_pic32_irq,
> + .irq_eoi = ack_pic32_irq,
> + .irq_set_type = set_type_pic32_irq,
> + .irq_enable = unmask_pic32_irq,
> + .irq_disable = mask_pic32_irq,
I'm not sure I see the point of having all these methods. First, there
is a lot of duplication: no need to provide enable/disable if all you
have is mask/unmask - the core code can deal with that.
Then, your EOI method is not really an EOI. It doesn't terminate the
handling, or at least that's not what the name suggest. If this is
really an EOI, then you should be able to simplify the whole thing on
only use the fasteoi handler, including for edge interrupts.
It would be good to have an insight on how this thing actually works
(I've tried to read the only documentation, but this is vague at best),
that would help picking the right design for your use case.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
next prev parent reply other threads:[~2015-12-15 17:00 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-14 22:42 [PATCH v2 00/14] Initial Microchip PIC32MZDA Support Joshua Henderson
2015-12-14 22:42 ` [PATCH v2 01/14] DEVICETREE: Add bindings for PIC32 interrupt controller Joshua Henderson
2015-12-14 23:34 ` Rob Herring
2015-12-14 22:42 ` [PATCH v2 02/14] irqchip: irq-pic32-evic: Add support " Joshua Henderson
2015-12-15 17:00 ` Marc Zyngier [this message]
2016-01-05 17:50 ` Joshua Henderson
2015-12-14 22:42 ` [PATCH v2 03/14] DEVICETREE: Add PIC32 clock binding documentation Joshua Henderson
2015-12-18 15:44 ` Rob Herring
2015-12-19 11:48 ` Purna Chandra Mandal
2015-12-14 22:42 ` [PATCH v2 04/14] clk: clk-pic32: Add PIC32 clock driver Joshua Henderson
2015-12-14 22:42 ` [PATCH v2 05/14] DEVICETREE: Add bindings for PIC32/MZDA platforms Joshua Henderson
2015-12-18 15:47 ` Rob Herring
2015-12-14 22:42 ` [PATCH v2 06/14] MIPS: Add support for PIC32MZDA platform Joshua Henderson
2015-12-14 22:42 ` [PATCH v2 07/14] DEVICETREE: Add bindings for PIC32 pin control and GPIO Joshua Henderson
2015-12-15 19:58 ` Rob Herring
2015-12-14 22:42 ` [PATCH v2 08/14] pinctrl: pinctrl-pic32: Add PIC32 pin control driver Joshua Henderson
2015-12-14 22:42 ` [PATCH v2 09/14] DEVICETREE: Add bindings for PIC32 UART driver Joshua Henderson
2015-12-15 20:00 ` Rob Herring
2015-12-14 22:42 ` [PATCH v2 10/14] serial: pic32_uart: Add " Joshua Henderson
2015-12-20 16:13 ` Andy Shevchenko
2016-01-05 20:29 ` Paul.Thacker
2016-01-05 20:43 ` One Thousand Gnomes
2016-01-06 22:00 ` Paul.Thacker
2016-01-06 22:32 ` One Thousand Gnomes
2015-12-14 22:42 ` [PATCH v2 11/14] DEVICETREE: Add bindings for PIC32 SDHCI host controller Joshua Henderson
2015-12-15 20:00 ` Rob Herring
2015-12-14 22:42 ` [PATCH v2 12/14] mmc: sdhci-pic32: Add PIC32 SDHCI host controller driver Joshua Henderson
2015-12-15 0:32 ` Andy Green
2015-12-16 17:35 ` Paul.Thacker
2015-12-16 10:48 ` Ulf Hansson
2015-12-17 18:05 ` Paul.Thacker
2015-12-14 22:42 ` [PATCH v2 13/14] MIPS: dts: Add initial DTS for the PIC32MZDA Starter Kit Joshua Henderson
2015-12-14 22:42 ` [PATCH v2 14/14] MIPS: pic32mzda: Add initial PIC32MZDA Starter Kit defconfig Joshua Henderson
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=5670471B.6090608@arm.com \
--to=marc.zyngier@arm.com \
--cc=cristian.birsan@microchip.com \
--cc=jason@lakedaemon.net \
--cc=joshua.henderson@microchip.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@linux-mips.org \
--cc=ralf@linux-mips.org \
--cc=tglx@linutronix.de \
/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