From: Yoshinori Sato <ysato@users.sourceforge.jp> To: linux-sh@vger.kernel.org Cc: "Yoshinori Sato" <ysato@users.sourceforge.jp>, "Damien Le Moal" <dlemoal@kernel.org>, "Rob Herring" <robh+dt@kernel.org>, "Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>, "Conor Dooley" <conor+dt@kernel.org>, "Geert Uytterhoeven" <geert+renesas@glider.be>, "Michael Turquette" <mturquette@baylibre.com>, "Stephen Boyd" <sboyd@kernel.org>, "Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>, "Maxime Ripard" <mripard@kernel.org>, "Thomas Zimmermann" <tzimmermann@suse.de>, "David Airlie" <airlied@gmail.com>, "Daniel Vetter" <daniel@ffwll.ch>, "Thomas Gleixner" <tglx@linutronix.de>, "Lorenzo Pieralisi" <lpieralisi@kernel.org>, "Krzysztof Wilczyński" <kw@linux.com>, "Bjorn Helgaas" <bhelgaas@google.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Jiri Slaby" <jirislaby@kernel.org>, "Magnus Damm" <magnus.damm@gmail.com>, "Daniel Lezcano" <daniel.lezcano@linaro.org>, "Rich Felker" <dalias@libc.org>, "John Paul Adrian Glaubitz" <glaubitz@physik.fu-berlin.de>, "Lee Jones" <lee@kernel.org>, "Helge Deller" <deller@gmx.de>, "Heiko Stuebner" <heiko@sntech.de>, "Jernej Skrabec" <jernej.skrabec@gmail.com>, "Chris Morgan" <macromorgan@hotmail.com>, "Yang Xiwen" <forbidden405@foxmail.com>, "Sebastian Reichel" <sre@kernel.org>, "Linus Walleij" <linus.walleij@linaro.org>, "Randy Dunlap" <rdunlap@infradead.org>, "Arnd Bergmann" <arnd@arndb.de>, "Vlastimil Babka" <vbabka@suse.cz>, "Hyeonggon Yoo" <42.hyeyoo@gmail.com>, "David Rientjes" <rientjes@google.com>, "Baoquan He" <bhe@redhat.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Guenter Roeck" <linux@roeck-us.net>, "Stephen Rothwell" <sfr@canb.auug.org.au>, "Azeem Shaikh" <azeemshaikh38@gmail.com>, "Javier Martinez Canillas" <javierm@redhat.com>, "Max Filippov" <jcmvbkbc@gmail.com>, "Palmer Dabbelt" <palmer@rivosinc.com>, "Bin Meng" <bmeng@tinylab.org>, "Jonathan Corbet" <corbet@lwn.net>, "Jacky Huang" <ychuang3@nuvoton.com>, "Lukas Bulwahn" <lukas.bulwahn@gmail.com>, "Biju Das" <biju.das.jz@bp.renesas.com>, "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Sam Ravnborg" <sam@ravnborg.org>, "Sergey Shtylyov" <s.shtylyov@omp.ru>, "Michael Karcher" <kernel@mkarcher.dialup.fu-berlin.de>, "Laurent Pinchart" <laurent.pinchart+renesas@ideasonboard.com>, linux-ide@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-clk@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-pci@vger.kernel.org, linux-serial@vger.kernel.org, linux-fbdev@vger.kernel.org Subject: [DO NOT MERGE v6 16/37] irqchip: Add SH7751 INTC driver Date: Tue, 9 Jan 2024 17:23:13 +0900 [thread overview] Message-ID: <5851e1a010c2679f957c0c4be2539261f26957c9.1704788539.git.ysato@users.sourceforge.jp> (raw) In-Reply-To: <cover.1704788539.git.ysato@users.sourceforge.jp> Renesas SH7751 Internal interrupt controller driver. Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> --- drivers/irqchip/Kconfig | 8 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-renesas-sh7751.c | 313 +++++++++++++++++++++++++++ 3 files changed, 322 insertions(+) create mode 100644 drivers/irqchip/irq-renesas-sh7751.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index f7149d0f3d45..658523f65b1d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -679,4 +679,12 @@ config SUNPLUS_SP7021_INTC chained controller, routing all interrupt source in P-Chip to the primary controller on C-Chip. +config RENESAS_SH7751_INTC + bool "Renesas SH7751 Interrupt Controller" + depends on SH_DEVICE_TREE || COMPILE_TEST + select IRQ_DOMAIN_HIERARCHY + help + Support for the Renesas SH7751 On-chip interrupt controller. + And external interrupt encoder for some targets. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index ffd945fe71aa..26c91d075e25 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -120,3 +120,4 @@ obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o +obj-$(CONFIG_RENESAS_SH7751_INTC) += irq-renesas-sh7751.o diff --git a/drivers/irqchip/irq-renesas-sh7751.c b/drivers/irqchip/irq-renesas-sh7751.c new file mode 100644 index 000000000000..9e5337f793c8 --- /dev/null +++ b/drivers/irqchip/irq-renesas-sh7751.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas SH7751 interrupt controller driver + * + * Copyright 2023 Yoshinori Sato <ysato@users.sourceforge.jp> + */ + +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of.h> +#include <linux/io.h> +#include <dt-bindings/interrupt-controller/renesas,sh7751-intc.h> + +struct ipr { + unsigned int off; + unsigned int idx; +}; + +struct sh7751_intc_priv { + void __iomem *base; + void __iomem *intpri00; + struct ipr *iprmap[2]; + bool irlm; +}; + +enum { + R_ICR = 0x00, + R_IPR = 0x04, + R_INTPRI00 = 0x00, + R_INTREQ00 = 0x20, + R_INTMSK00 = 0x40, + R_INTMSKCLR00 = 0x60, +}; + +#define ICR_IRLM BIT(7) + +/* + * SH7751 IRQ mapping + * IRQ16 - 63: Group0 - IPRA to IPRD + * IRQ16 - 31: external IRL input (ICR.IRLM is 0) + * IRQ80 - 92: Group1 - INTPRI00 + */ +#define IRQ_START 16 +#define MAX_IRL (IRQ_START + NR_IRL) +#define GRP0_IRQ_END 63 +#define GRP1_IRQ_START 80 +#define IRQ_END 92 + +#define NR_IPRMAP0 (GRP0_IRQ_END - IRQ_START + 1) +#define NR_IPRMAP1 (IRQ_END - GRP1_IRQ_START) +#define IPR_PRI_MASK 0x000f + +/* + * IPR registers have 4bit priority x 4 entry (16bits) + */ +static void update_ipr(struct sh7751_intc_priv *priv, unsigned int irq, u16 pri) +{ + struct ipr *ipr = NULL; + void __iomem *ipr_base; + unsigned int offset; + u16 mask; + + if (irq < GRP1_IRQ_START) { + /* Group0 */ + ipr = priv->iprmap[0]; + ipr += irq - IRQ_START; + ipr_base = priv->base + R_IPR; + offset = ipr->off; + } else { + /* Group1 */ + ipr = priv->iprmap[1]; + ipr += irq - GRP1_IRQ_START; + ipr_base = priv->intpri00; + offset = ipr->off - INTPRI00; + } + if (ipr->off != ~0) { + mask = ~(IPR_PRI_MASK << ipr->idx); + pri = (pri & IPR_PRI_MASK) << ipr->idx; + mask &= __raw_readw(ipr_base + offset); + __raw_writew(mask | pri, ipr_base + offset); + } else { + pr_warn_once("%s: undefined IPR in irq %u\n", __FILE__, irq); + } +} + +static inline bool is_valid_irq(unsigned int irq) +{ + /* IRQ16 - 63 */ + if (irq >= IRQ_START && irq < IRQ_START + NR_IPRMAP0) + return true; + /* IRQ80 - 92 */ + if (irq >= GRP1_IRQ_START && irq <= IRQ_END) + return true; + return false; +} + +static inline struct sh7751_intc_priv *irq_data_to_priv(struct irq_data *data) +{ + return data->domain->host_data; +} + +/* Interrupt unmask priority is 1, mask priority is 0 */ +#define PRI_ENABLE 1 +#define PRI_DISABLE 0 +static void endisable_irq(struct irq_data *data, bool enable) +{ + struct sh7751_intc_priv *priv; + unsigned int irq; + + priv = irq_data_to_priv(data); + + irq = irqd_to_hwirq(data); + if (!is_valid_irq(irq)) { + /* IRQ out of range */ + pr_warn_once("%s: IRQ %u is out of range\n", __FILE__, irq); + return; + } + + if (irq <= MAX_IRL && !priv->irlm) { + /* IRL encoded external interrupt */ + /* enable and disable from SR.IMASK */ + update_sr_imask(irq - IRQ_START, enable); + } else { + /* Internal peripheral interrupt */ + /* enable and disable from interrupt priority */ + update_ipr(priv, irq, enable ? PRI_ENABLE : PRI_DISABLE); + } +} + +static void sh7751_mask_irq(struct irq_data *data) +{ + endisable_irq(data, false); +} + +static void sh7751_unmask_irq(struct irq_data *data) +{ + endisable_irq(data, true); +} + +static const struct irq_chip sh7751_irq_chip = { + .name = "SH7751-INTC", + .irq_unmask = sh7751_unmask_irq, + .irq_mask = sh7751_mask_irq, +}; + +static int irq_sh7751_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &sh7751_irq_chip, handle_level_irq); + irq_get_irq_data(virq)->chip_data = h->host_data; + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOPROBE); + return 0; +} + +static int irq_sh7751_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize < 1)) + return -EINVAL; + *out_hwirq = evt2irq(intspec[0]); + *out_type = IRQ_TYPE_NONE; + return 0; +} + +static const struct irq_domain_ops irq_ops = { + .map = irq_sh7751_map, + .xlate = irq_sh7751_xlate, +}; + +/* renesas,ipr-map has 3words per entry */ +#define IPR_MAP_WORDS 3 +static int __init load_ipr_map(struct device_node *intc, + struct sh7751_intc_priv *priv) +{ + struct property *ipr_map; + unsigned int num_ipr, i; + struct ipr *ipr; + const __be32 *p; + u32 irq; + + ipr_map = of_find_property(intc, "renesas,ipr-map", &num_ipr); + if (IS_ERR(ipr_map)) + return PTR_ERR(ipr_map); + num_ipr /= sizeof(u32); + + if (num_ipr % IPR_MAP_WORDS) + goto error1; + num_ipr /= IPR_MAP_WORDS; + if (num_ipr >= NR_IPRMAP0 + NR_IPRMAP1) + goto error1; + + /* Allocate map array and fill in unassigned */ + priv->iprmap[0] = kmalloc_array(NR_IPRMAP0, sizeof(struct ipr), GFP_KERNEL); + if (priv->iprmap[0] == NULL) + return -ENOMEM; + memset(priv->iprmap[0], ~0, NR_IPRMAP0 * sizeof(struct ipr)); + priv->iprmap[1] = kmalloc_array(NR_IPRMAP1, sizeof(struct ipr), GFP_KERNEL); + if (priv->iprmap[1] == NULL) { + kfree(priv->iprmap[0]); + return -ENOMEM; + } + memset(priv->iprmap[1], ~0, NR_IPRMAP1 * sizeof(struct ipr)); + + p = NULL; + for (; num_ipr > 0; num_ipr--) { + /* 1st word - INTEVT code */ + p = of_prop_next_u32(ipr_map, p, &irq); + if (!p) + goto error; + irq = evt2irq(irq); + if (!is_valid_irq(irq)) + goto error; + if (irq < GRP1_IRQ_START) { + ipr = priv->iprmap[0]; + irq -= IRQ_START; + } else { + ipr = priv->iprmap[1]; + irq -= GRP1_IRQ_START; + } + ipr += irq; + /* 2nd word - IPR register offset */ + p = of_prop_next_u32(ipr_map, p, &ipr->off); + /* 3rd word - IPR register bit indx */ + p = of_prop_next_u32(ipr_map, p, &ipr->idx); + + if ((ipr->off != INTPRI00 && ipr->off > IPRD) || + ipr->idx > IPR_B12) + goto error; + } + + for (ipr = priv->iprmap[0], i = 0; i < NR_IPRMAP0; ipr++, i++) { + if (ipr->off != ~0) { + pr_debug("INTEVT=%04x (%u) reg=IPR%c idx=%u\n", + irq2evt(i + IRQ_START), i + IRQ_START, + 'A' + ipr->off / 4, ipr->idx); + } + } + for (ipr = priv->iprmap[1], i = 0; i < NR_IPRMAP1; ipr++, i++) { + if (ipr->off != ~0) { + pr_debug("INTEVT=%04x (%u) reg=INTPRI00 idx=%u\n", + irq2evt(i + GRP1_IRQ_START), i + GRP1_IRQ_START, + ipr->idx); + } + } + return 0; +error: + kfree(priv->iprmap[0]); + kfree(priv->iprmap[1]); +error1: + pr_err("%pOFP: Failed to load renesas,ipr-map\n", intc); + return -EINVAL; +} + +static int __init sh7751_intc_of_init(struct device_node *intc, + struct device_node *parent) +{ + struct sh7751_intc_priv *priv; + void __iomem *base, *base2; + struct irq_domain *domain; + u16 icr; + int ret; + + priv = kzalloc(sizeof(struct sh7751_intc_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + base = of_iomap(intc, 0); + base2 = of_iomap(intc, 1); + if (!base || !base2) { + pr_err("%pOFP: Invalid register definition\n", intc); + ret = -EINVAL; + goto error; + } + + ret = load_ipr_map(intc, priv); + if (ret < 0) + goto error; + + priv->base = base; + priv->intpri00 = base2; + + if (of_property_read_bool(intc, "renesas,irlm")) { + priv->irlm = true; + icr = __raw_readw(priv->base + R_ICR); + icr |= ICR_IRLM; + __raw_writew(icr, priv->base + R_ICR); + } + + domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, priv); + if (domain == NULL) { + pr_err("%pOFP: cannot initialize irq domain\n", intc); + ret = -ENOMEM; + goto error; + } + + irq_set_default_host(domain); + pr_info("%pOFP: SH7751 Interrupt controller (%s external IRQ)", + intc, priv->irlm ? "4 lines" : "15 level"); + return 0; + +error: + if (base) + iounmap(base); + if (base2) + iounmap(base); + kfree(priv); + return ret; +} + +IRQCHIP_DECLARE(sh_7751_intc, "renesas,sh7751-intc", sh7751_intc_of_init); -- 2.39.2
WARNING: multiple messages have this Message-ID (diff)
From: Yoshinori Sato <ysato@users.sourceforge.jp> To: linux-sh@vger.kernel.org Cc: "Krzysztof Wilczyński" <kw@linux.com>, linux-fbdev@vger.kernel.org, "Rich Felker" <dalias@libc.org>, "Geert Uytterhoeven" <geert+renesas@glider.be>, "Bin Meng" <bmeng@tinylab.org>, "Michael Turquette" <mturquette@baylibre.com>, linux-pci@vger.kernel.org, "Jacky Huang" <ychuang3@nuvoton.com>, "Palmer Dabbelt" <palmer@rivosinc.com>, linux-kernel@vger.kernel.org, "Max Filippov" <jcmvbkbc@gmail.com>, "Lee Jones" <lee@kernel.org>, "Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>, "Hyeonggon Yoo" <42.hyeyoo@gmail.com>, "Jiri Slaby" <jirislaby@kernel.org>, linux-clk@vger.kernel.org, "Stephen Rothwell" <sfr@canb.auug.org.au>, "Laurent Pinchart" <laurent.pinchart+renesas@ideasonboard.com>, "Yoshinori Sato" <ysato@users.sourceforge.jp>, "Jonathan Corbet" <corbet@lwn.net>, "Helge Deller" <deller@gmx.de>, "Daniel Lezcano" <daniel.lezcano@linaro.org>, "Magnus Damm" <magnus.damm@gmail.com>, "Javier Martinez Canillas" <javierm@redhat.com>, "Jernej Skrabec" <jernej.skrabec@gmail.com>, linux-serial@vger.kernel.org, "David Rientjes" <rientjes@google.com>, "Lukas Bulwahn" <lukas.bulwahn@gmail.com>, "Lorenzo Pieralisi" <lpieralisi@kernel.org>, "Guenter Roeck" <linux@roeck-us.net>, devicetree@vger.kernel.org, "Conor Dooley" <conor+dt@kernel.org>, "Arnd Bergmann" <arnd@arndb.de>, "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Maxime Ripard" <mripard@kernel.org>, "Sam Ravnborg" <sam@ravnborg.org>, "Rob Herring" <robh+dt@kernel.org>, dri-devel@lists.freedesktop.org, "Chris Morgan" <macromorgan@hotmail.com>, "John Paul Adrian Glaubitz" <glaubitz@physik.fu-berlin.de>, "Bjorn Helgaas" <bhelgaas@google.com>, "Thomas Gleixner" <tglx@linutronix.de>, "Vlastimil Babka" <vbabka@suse.cz>, "Yang Xiwen" <forbidden405@foxmail.com>, "Sergey Shtylyov" <s.shtylyov@omp.ru>, "Baoquan He" <bhe@redhat.com>, linux-ide@vger.kernel.org, "Stephen Boyd" <sboyd@kernel.org>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Randy Dunlap" <rdunlap@infradead.org>, "Biju Das" <biju.das.jz@bp.renesas.com>, "Sebastian Reichel" <sre@kernel.org>, "Azeem Shaikh" <azeemshaikh38@gmail.com>, linux-renesas-soc@vger.kernel.org, "Damien Le Moal" <dlemoal@kernel.org>, "Thomas Zimmermann" <tzimmermann@suse.de>, "Michael Karcher" <kernel@mkarcher.dialup.fu-berlin.de>, "Andrew Morton" <akpm@linux-foundation.org> Subject: [DO NOT MERGE v6 16/37] irqchip: Add SH7751 INTC driver Date: Tue, 9 Jan 2024 17:23:13 +0900 [thread overview] Message-ID: <5851e1a010c2679f957c0c4be2539261f26957c9.1704788539.git.ysato@users.sourceforge.jp> (raw) In-Reply-To: <cover.1704788539.git.ysato@users.sourceforge.jp> Renesas SH7751 Internal interrupt controller driver. Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> --- drivers/irqchip/Kconfig | 8 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-renesas-sh7751.c | 313 +++++++++++++++++++++++++++ 3 files changed, 322 insertions(+) create mode 100644 drivers/irqchip/irq-renesas-sh7751.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index f7149d0f3d45..658523f65b1d 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -679,4 +679,12 @@ config SUNPLUS_SP7021_INTC chained controller, routing all interrupt source in P-Chip to the primary controller on C-Chip. +config RENESAS_SH7751_INTC + bool "Renesas SH7751 Interrupt Controller" + depends on SH_DEVICE_TREE || COMPILE_TEST + select IRQ_DOMAIN_HIERARCHY + help + Support for the Renesas SH7751 On-chip interrupt controller. + And external interrupt encoder for some targets. + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index ffd945fe71aa..26c91d075e25 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -120,3 +120,4 @@ obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o obj-$(CONFIG_APPLE_AIC) += irq-apple-aic.o obj-$(CONFIG_MCHP_EIC) += irq-mchp-eic.o obj-$(CONFIG_SUNPLUS_SP7021_INTC) += irq-sp7021-intc.o +obj-$(CONFIG_RENESAS_SH7751_INTC) += irq-renesas-sh7751.o diff --git a/drivers/irqchip/irq-renesas-sh7751.c b/drivers/irqchip/irq-renesas-sh7751.c new file mode 100644 index 000000000000..9e5337f793c8 --- /dev/null +++ b/drivers/irqchip/irq-renesas-sh7751.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas SH7751 interrupt controller driver + * + * Copyright 2023 Yoshinori Sato <ysato@users.sourceforge.jp> + */ + +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of.h> +#include <linux/io.h> +#include <dt-bindings/interrupt-controller/renesas,sh7751-intc.h> + +struct ipr { + unsigned int off; + unsigned int idx; +}; + +struct sh7751_intc_priv { + void __iomem *base; + void __iomem *intpri00; + struct ipr *iprmap[2]; + bool irlm; +}; + +enum { + R_ICR = 0x00, + R_IPR = 0x04, + R_INTPRI00 = 0x00, + R_INTREQ00 = 0x20, + R_INTMSK00 = 0x40, + R_INTMSKCLR00 = 0x60, +}; + +#define ICR_IRLM BIT(7) + +/* + * SH7751 IRQ mapping + * IRQ16 - 63: Group0 - IPRA to IPRD + * IRQ16 - 31: external IRL input (ICR.IRLM is 0) + * IRQ80 - 92: Group1 - INTPRI00 + */ +#define IRQ_START 16 +#define MAX_IRL (IRQ_START + NR_IRL) +#define GRP0_IRQ_END 63 +#define GRP1_IRQ_START 80 +#define IRQ_END 92 + +#define NR_IPRMAP0 (GRP0_IRQ_END - IRQ_START + 1) +#define NR_IPRMAP1 (IRQ_END - GRP1_IRQ_START) +#define IPR_PRI_MASK 0x000f + +/* + * IPR registers have 4bit priority x 4 entry (16bits) + */ +static void update_ipr(struct sh7751_intc_priv *priv, unsigned int irq, u16 pri) +{ + struct ipr *ipr = NULL; + void __iomem *ipr_base; + unsigned int offset; + u16 mask; + + if (irq < GRP1_IRQ_START) { + /* Group0 */ + ipr = priv->iprmap[0]; + ipr += irq - IRQ_START; + ipr_base = priv->base + R_IPR; + offset = ipr->off; + } else { + /* Group1 */ + ipr = priv->iprmap[1]; + ipr += irq - GRP1_IRQ_START; + ipr_base = priv->intpri00; + offset = ipr->off - INTPRI00; + } + if (ipr->off != ~0) { + mask = ~(IPR_PRI_MASK << ipr->idx); + pri = (pri & IPR_PRI_MASK) << ipr->idx; + mask &= __raw_readw(ipr_base + offset); + __raw_writew(mask | pri, ipr_base + offset); + } else { + pr_warn_once("%s: undefined IPR in irq %u\n", __FILE__, irq); + } +} + +static inline bool is_valid_irq(unsigned int irq) +{ + /* IRQ16 - 63 */ + if (irq >= IRQ_START && irq < IRQ_START + NR_IPRMAP0) + return true; + /* IRQ80 - 92 */ + if (irq >= GRP1_IRQ_START && irq <= IRQ_END) + return true; + return false; +} + +static inline struct sh7751_intc_priv *irq_data_to_priv(struct irq_data *data) +{ + return data->domain->host_data; +} + +/* Interrupt unmask priority is 1, mask priority is 0 */ +#define PRI_ENABLE 1 +#define PRI_DISABLE 0 +static void endisable_irq(struct irq_data *data, bool enable) +{ + struct sh7751_intc_priv *priv; + unsigned int irq; + + priv = irq_data_to_priv(data); + + irq = irqd_to_hwirq(data); + if (!is_valid_irq(irq)) { + /* IRQ out of range */ + pr_warn_once("%s: IRQ %u is out of range\n", __FILE__, irq); + return; + } + + if (irq <= MAX_IRL && !priv->irlm) { + /* IRL encoded external interrupt */ + /* enable and disable from SR.IMASK */ + update_sr_imask(irq - IRQ_START, enable); + } else { + /* Internal peripheral interrupt */ + /* enable and disable from interrupt priority */ + update_ipr(priv, irq, enable ? PRI_ENABLE : PRI_DISABLE); + } +} + +static void sh7751_mask_irq(struct irq_data *data) +{ + endisable_irq(data, false); +} + +static void sh7751_unmask_irq(struct irq_data *data) +{ + endisable_irq(data, true); +} + +static const struct irq_chip sh7751_irq_chip = { + .name = "SH7751-INTC", + .irq_unmask = sh7751_unmask_irq, + .irq_mask = sh7751_mask_irq, +}; + +static int irq_sh7751_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw_irq_num) +{ + irq_set_chip_and_handler(virq, &sh7751_irq_chip, handle_level_irq); + irq_get_irq_data(virq)->chip_data = h->host_data; + irq_modify_status(virq, IRQ_NOREQUEST, IRQ_NOPROBE); + return 0; +} + +static int irq_sh7751_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + unsigned long *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize < 1)) + return -EINVAL; + *out_hwirq = evt2irq(intspec[0]); + *out_type = IRQ_TYPE_NONE; + return 0; +} + +static const struct irq_domain_ops irq_ops = { + .map = irq_sh7751_map, + .xlate = irq_sh7751_xlate, +}; + +/* renesas,ipr-map has 3words per entry */ +#define IPR_MAP_WORDS 3 +static int __init load_ipr_map(struct device_node *intc, + struct sh7751_intc_priv *priv) +{ + struct property *ipr_map; + unsigned int num_ipr, i; + struct ipr *ipr; + const __be32 *p; + u32 irq; + + ipr_map = of_find_property(intc, "renesas,ipr-map", &num_ipr); + if (IS_ERR(ipr_map)) + return PTR_ERR(ipr_map); + num_ipr /= sizeof(u32); + + if (num_ipr % IPR_MAP_WORDS) + goto error1; + num_ipr /= IPR_MAP_WORDS; + if (num_ipr >= NR_IPRMAP0 + NR_IPRMAP1) + goto error1; + + /* Allocate map array and fill in unassigned */ + priv->iprmap[0] = kmalloc_array(NR_IPRMAP0, sizeof(struct ipr), GFP_KERNEL); + if (priv->iprmap[0] == NULL) + return -ENOMEM; + memset(priv->iprmap[0], ~0, NR_IPRMAP0 * sizeof(struct ipr)); + priv->iprmap[1] = kmalloc_array(NR_IPRMAP1, sizeof(struct ipr), GFP_KERNEL); + if (priv->iprmap[1] == NULL) { + kfree(priv->iprmap[0]); + return -ENOMEM; + } + memset(priv->iprmap[1], ~0, NR_IPRMAP1 * sizeof(struct ipr)); + + p = NULL; + for (; num_ipr > 0; num_ipr--) { + /* 1st word - INTEVT code */ + p = of_prop_next_u32(ipr_map, p, &irq); + if (!p) + goto error; + irq = evt2irq(irq); + if (!is_valid_irq(irq)) + goto error; + if (irq < GRP1_IRQ_START) { + ipr = priv->iprmap[0]; + irq -= IRQ_START; + } else { + ipr = priv->iprmap[1]; + irq -= GRP1_IRQ_START; + } + ipr += irq; + /* 2nd word - IPR register offset */ + p = of_prop_next_u32(ipr_map, p, &ipr->off); + /* 3rd word - IPR register bit indx */ + p = of_prop_next_u32(ipr_map, p, &ipr->idx); + + if ((ipr->off != INTPRI00 && ipr->off > IPRD) || + ipr->idx > IPR_B12) + goto error; + } + + for (ipr = priv->iprmap[0], i = 0; i < NR_IPRMAP0; ipr++, i++) { + if (ipr->off != ~0) { + pr_debug("INTEVT=%04x (%u) reg=IPR%c idx=%u\n", + irq2evt(i + IRQ_START), i + IRQ_START, + 'A' + ipr->off / 4, ipr->idx); + } + } + for (ipr = priv->iprmap[1], i = 0; i < NR_IPRMAP1; ipr++, i++) { + if (ipr->off != ~0) { + pr_debug("INTEVT=%04x (%u) reg=INTPRI00 idx=%u\n", + irq2evt(i + GRP1_IRQ_START), i + GRP1_IRQ_START, + ipr->idx); + } + } + return 0; +error: + kfree(priv->iprmap[0]); + kfree(priv->iprmap[1]); +error1: + pr_err("%pOFP: Failed to load renesas,ipr-map\n", intc); + return -EINVAL; +} + +static int __init sh7751_intc_of_init(struct device_node *intc, + struct device_node *parent) +{ + struct sh7751_intc_priv *priv; + void __iomem *base, *base2; + struct irq_domain *domain; + u16 icr; + int ret; + + priv = kzalloc(sizeof(struct sh7751_intc_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + base = of_iomap(intc, 0); + base2 = of_iomap(intc, 1); + if (!base || !base2) { + pr_err("%pOFP: Invalid register definition\n", intc); + ret = -EINVAL; + goto error; + } + + ret = load_ipr_map(intc, priv); + if (ret < 0) + goto error; + + priv->base = base; + priv->intpri00 = base2; + + if (of_property_read_bool(intc, "renesas,irlm")) { + priv->irlm = true; + icr = __raw_readw(priv->base + R_ICR); + icr |= ICR_IRLM; + __raw_writew(icr, priv->base + R_ICR); + } + + domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, priv); + if (domain == NULL) { + pr_err("%pOFP: cannot initialize irq domain\n", intc); + ret = -ENOMEM; + goto error; + } + + irq_set_default_host(domain); + pr_info("%pOFP: SH7751 Interrupt controller (%s external IRQ)", + intc, priv->irlm ? "4 lines" : "15 level"); + return 0; + +error: + if (base) + iounmap(base); + if (base2) + iounmap(base); + kfree(priv); + return ret; +} + +IRQCHIP_DECLARE(sh_7751_intc, "renesas,sh7751-intc", sh7751_intc_of_init); -- 2.39.2
next prev parent reply other threads:[~2024-01-09 8:24 UTC|newest] Thread overview: 138+ messages / expand[flat|nested] mbox.gz Atom feed top 2024-01-09 8:22 [DO NOT MERGE v6 00/37] Device Tree support for SH7751 based board Yoshinori Sato 2024-01-09 8:22 ` Yoshinori Sato 2024-01-09 8:22 ` [DO NOT MERGE v6 01/37] sh: passing FDT address to kernel startup Yoshinori Sato 2024-01-09 8:22 ` Yoshinori Sato 2024-01-15 14:03 ` Geert Uytterhoeven 2024-01-15 14:03 ` Geert Uytterhoeven 2024-01-09 8:22 ` [DO NOT MERGE v6 02/37] sh: Kconfig unified OF supported targets Yoshinori Sato 2024-01-09 8:22 ` Yoshinori Sato 2024-02-26 16:21 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 03/37] sh: Enable OF support for build and configuration Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 04/37] dt-bindings: interrupt-controller: Add header for Renesas SH3/4 INTC Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 18:41 ` Krzysztof Kozlowski 2024-01-09 18:41 ` Krzysztof Kozlowski 2024-01-09 8:23 ` [DO NOT MERGE v6 05/37] sh: GENERIC_IRQ_CHIP support for CONFIG_OF=y Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 06/37] sh: kernel/setup Update DT support Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 07/37] sh: Fix COMMON_CLK support in CONFIG_OF=y Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 08/37] clocksource: sh_tmu: CLOCKSOURCE support Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-02-26 16:54 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas,tmu: add renesas,tmu-sh7750 Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas, tmu: add renesas, tmu-sh7750 Yoshinori Sato 2024-01-15 13:59 ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas,tmu: add renesas,tmu-sh7750 Geert Uytterhoeven 2024-01-15 13:59 ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas, tmu: add renesas, tmu-sh7750 Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 10/37] sh: Common PCI Framework driver support Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 11/37] pci: pci-sh7751: Add SH7751 PCI driver Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 12/37] dt-bindings: pci: pci-sh7751: Add SH7751 PCI Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 12:42 ` Linus Walleij 2024-01-09 12:42 ` Linus Walleij 2024-01-09 17:31 ` Rob Herring 2024-01-09 17:31 ` Rob Herring 2024-01-09 8:23 ` [DO NOT MERGE v6 13/37] dt-bindings: clock: sh7750-cpg: Add renesas,sh7750-cpg header Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 13/37] dt-bindings: clock: sh7750-cpg: Add renesas, sh7750-cpg header Yoshinori Sato 2024-02-27 16:47 ` [DO NOT MERGE v6 13/37] dt-bindings: clock: sh7750-cpg: Add renesas,sh7750-cpg header Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 14/37] clk: Compatible with narrow registers Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-02-27 15:41 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 15/37] clk: renesas: Add SH7750/7751 CPG Driver Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-02-27 16:34 ` Geert Uytterhoeven 2024-01-09 8:23 ` Yoshinori Sato [this message] 2024-01-09 8:23 ` [DO NOT MERGE v6 16/37] irqchip: Add SH7751 INTC driver Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: Add json-schema Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas, sh7751-intc: " Yoshinori Sato 2024-01-09 12:30 ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: " Linus Walleij 2024-01-09 12:30 ` Linus Walleij 2024-01-17 9:46 ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas, sh7751-intc: " Yoshinori Sato 2024-01-17 9:46 ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: " Yoshinori Sato 2024-01-17 10:06 ` Geert Uytterhoeven 2024-01-17 10:06 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 18/37] irqchip: SH7751 external interrupt encoder with enable gate Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 19/37] dt-bindings: interrupt-controller: renesas,sh7751-irl-ext: Add json-schema Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 19/37] dt-bindings: interrupt-controller: renesas, sh7751-irl-ext: " Yoshinori Sato 2024-01-09 16:29 ` [DO NOT MERGE v6 19/37] dt-bindings: interrupt-controller: renesas,sh7751-irl-ext: " Rob Herring 2024-01-09 16:29 ` Rob Herring 2024-01-09 17:18 ` Rob Herring 2024-01-09 17:18 ` Rob Herring 2024-01-09 8:23 ` [DO NOT MERGE v6 20/37] serial: sh-sci: fix SH4 OF support Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas,scif: Add scif-sh7751 Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas, scif: " Yoshinori Sato 2024-01-15 9:29 ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas,scif: " Geert Uytterhoeven 2024-01-15 9:29 ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas, scif: " Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 22/37] dt-bindings: display: smi,sm501: SMI SM501 binding json-schema Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 22/37] dt-bindings: display: smi, sm501: " Yoshinori Sato 2024-01-15 9:52 ` [DO NOT MERGE v6 22/37] dt-bindings: display: smi,sm501: " Geert Uytterhoeven 2024-01-15 9:52 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 23/37] mfd: sm501: Convert platform_data to OF property Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-11 11:35 ` Lee Jones 2024-01-11 11:35 ` Lee Jones 2024-01-09 8:23 ` [DO NOT MERGE v6 24/37] dt-binding: sh: cpus: Add SH CPUs json-schema Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 18:00 ` Conor Dooley 2024-01-09 18:00 ` Conor Dooley 2024-01-09 8:23 ` [DO NOT MERGE v6 25/37] dt-bindings: vendor-prefixes: Add iodata Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 18:03 ` Conor Dooley 2024-01-09 18:03 ` Conor Dooley 2024-01-15 14:02 ` Geert Uytterhoeven 2024-01-15 14:02 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 26/37] dt-bindings: vendor-prefixes: Add smi Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 18:05 ` Conor Dooley 2024-01-09 18:05 ` Conor Dooley 2024-01-10 11:23 ` Geert Uytterhoeven 2024-01-10 11:23 ` Geert Uytterhoeven 2024-01-10 14:28 ` Guenter Roeck 2024-01-10 14:28 ` Guenter Roeck 2024-01-10 16:11 ` Conor Dooley 2024-01-10 16:11 ` Conor Dooley 2024-01-11 14:59 ` Rob Herring 2024-01-11 14:59 ` Rob Herring 2024-01-09 21:40 ` Uwe Kleine-König 2024-01-09 21:40 ` Uwe Kleine-König 2024-01-09 8:23 ` [DO NOT MERGE v6 27/37] dt-bindings: ata: ata-generic: Add new targets Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 18:07 ` Conor Dooley 2024-01-09 18:07 ` Conor Dooley 2024-01-09 18:09 ` Conor Dooley 2024-01-09 18:09 ` Conor Dooley 2024-01-10 2:06 ` Damien Le Moal 2024-01-10 2:06 ` Damien Le Moal 2024-01-10 7:19 ` Krzysztof Kozlowski 2024-01-10 7:19 ` Krzysztof Kozlowski 2024-01-10 7:25 ` Damien Le Moal 2024-01-10 7:25 ` Damien Le Moal 2024-01-09 8:23 ` [DO NOT MERGE v6 28/37] dt-bindings: soc: renesas: sh: Add SH7751 based target Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-02-27 15:58 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 29/37] sh: SH7751R SoC Internal peripheral definition dtsi Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 30/37] sh: add RTS7751R2D Plus DTS Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 31/37] sh: Add IO DATA LANDISK dts Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 32/37] sh: Add IO DATA USL-5P dts Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 33/37] sh: j2_mimas_v2.dts update Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-02-27 16:07 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 34/37] sh: Add dtbs target support Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-02-27 18:48 ` Geert Uytterhoeven 2024-01-09 8:23 ` [DO NOT MERGE v6 35/37] sh: RTS7751R2D Plus OF defconfig Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 36/37] sh: LANDISK " Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato 2024-01-09 8:23 ` [DO NOT MERGE v6 37/37] sh: j2_defconfig: update Yoshinori Sato 2024-01-09 8:23 ` Yoshinori Sato
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=5851e1a010c2679f957c0c4be2539261f26957c9.1704788539.git.ysato@users.sourceforge.jp \ --to=ysato@users.sourceforge.jp \ --cc=42.hyeyoo@gmail.com \ --cc=airlied@gmail.com \ --cc=akpm@linux-foundation.org \ --cc=arnd@arndb.de \ --cc=azeemshaikh38@gmail.com \ --cc=bhe@redhat.com \ --cc=bhelgaas@google.com \ --cc=biju.das.jz@bp.renesas.com \ --cc=bmeng@tinylab.org \ --cc=conor+dt@kernel.org \ --cc=corbet@lwn.net \ --cc=dalias@libc.org \ --cc=daniel.lezcano@linaro.org \ --cc=daniel@ffwll.ch \ --cc=deller@gmx.de \ --cc=devicetree@vger.kernel.org \ --cc=dlemoal@kernel.org \ --cc=dri-devel@lists.freedesktop.org \ --cc=forbidden405@foxmail.com \ --cc=geert+renesas@glider.be \ --cc=glaubitz@physik.fu-berlin.de \ --cc=gregkh@linuxfoundation.org \ --cc=heiko@sntech.de \ --cc=javierm@redhat.com \ --cc=jcmvbkbc@gmail.com \ --cc=jernej.skrabec@gmail.com \ --cc=jirislaby@kernel.org \ --cc=kernel@mkarcher.dialup.fu-berlin.de \ --cc=krzysztof.kozlowski+dt@linaro.org \ --cc=kw@linux.com \ --cc=laurent.pinchart+renesas@ideasonboard.com \ --cc=lee@kernel.org \ --cc=linus.walleij@linaro.org \ --cc=linux-clk@vger.kernel.org \ --cc=linux-fbdev@vger.kernel.org \ --cc=linux-ide@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-pci@vger.kernel.org \ --cc=linux-renesas-soc@vger.kernel.org \ --cc=linux-serial@vger.kernel.org \ --cc=linux-sh@vger.kernel.org \ --cc=linux@roeck-us.net \ --cc=lpieralisi@kernel.org \ --cc=lukas.bulwahn@gmail.com \ --cc=maarten.lankhorst@linux.intel.com \ --cc=macromorgan@hotmail.com \ --cc=magnus.damm@gmail.com \ --cc=mripard@kernel.org \ --cc=mturquette@baylibre.com \ --cc=palmer@rivosinc.com \ --cc=rdunlap@infradead.org \ --cc=rientjes@google.com \ --cc=robh+dt@kernel.org \ --cc=s.shtylyov@omp.ru \ --cc=sam@ravnborg.org \ --cc=sboyd@kernel.org \ --cc=sfr@canb.auug.org.au \ --cc=sre@kernel.org \ --cc=tglx@linutronix.de \ --cc=tzimmermann@suse.de \ --cc=u.kleine-koenig@pengutronix.de \ --cc=vbabka@suse.cz \ --cc=ychuang3@nuvoton.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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.