This patch enables Loongson-1 irqchip driver by adding platform INTC device nodes. And drop the legacy platform IRQ driver accordingly. Based on previous patch by Jiaxun Yang. Link: https://lore.kernel.org/all/20190411121915.8040-3-jiaxun.yang@xxxxxxxxxxx Signed-off-by: Keguang Zhang <keguang.zhang@xxxxxxxxx> --- arch/mips/boot/dts/loongson/loongson1.dtsi | 53 ++++++ arch/mips/boot/dts/loongson/loongson1c.dtsi | 13 ++ arch/mips/loongson32/common/Makefile | 2 +- arch/mips/loongson32/common/irq.c | 191 -------------------- arch/mips/loongson32/init.c | 5 + 5 files changed, 72 insertions(+), 192 deletions(-) delete mode 100644 arch/mips/loongson32/common/irq.c diff --git a/arch/mips/boot/dts/loongson/loongson1.dtsi b/arch/mips/boot/dts/loongson/loongson1.dtsi index a2b5c828bbbd..711c88fd2781 100644 --- a/arch/mips/boot/dts/loongson/loongson1.dtsi +++ b/arch/mips/boot/dts/loongson/loongson1.dtsi @@ -19,4 +19,57 @@ cpu_intc: interrupt-controller { interrupt-controller; #interrupt-cells = <1>; }; + + ahb: bus@1f000000 { + compatible = "simple-bus"; + reg = <0x1f000000 0xe40000>; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + intc0: interrupt-controller@1fd01040 { + compatible = "loongson,ls1x-intc"; + reg = <0x1fd01040 0x18>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpu_intc>; + interrupts = <2>; + }; + + intc1: interrupt-controller@1fd01058 { + compatible = "loongson,ls1x-intc"; + reg = <0x1fd01058 0x18>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpu_intc>; + interrupts = <3>; + }; + + intc2: interrupt-controller@1fd01070 { + compatible = "loongson,ls1x-intc"; + reg = <0x1fd01070 0x18>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpu_intc>; + interrupts = <4>; + }; + + intc3: interrupt-controller@1fd01088 { + compatible = "loongson,ls1x-intc"; + reg = <0x1fd01088 0x18>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpu_intc>; + interrupts = <5>; + }; + }; }; diff --git a/arch/mips/boot/dts/loongson/loongson1c.dtsi b/arch/mips/boot/dts/loongson/loongson1c.dtsi index d552e1668984..8570c4c72677 100644 --- a/arch/mips/boot/dts/loongson/loongson1c.dtsi +++ b/arch/mips/boot/dts/loongson/loongson1c.dtsi @@ -27,3 +27,16 @@ clkc: clock-controller@1fe78030 { #clock-cells = <1>; }; }; + +&ahb { + intc4: interrupt-controller@1fd010a0 { + compatible = "loongson,ls1x-intc"; + reg = <0x1fd010a0 0x18>; + + interrupt-controller; + #interrupt-cells = <2>; + + interrupt-parent = <&cpu_intc>; + interrupts = <6>; + }; +}; diff --git a/arch/mips/loongson32/common/Makefile b/arch/mips/loongson32/common/Makefile index b5c2f4e0f4cc..25e54b4fca7c 100644 --- a/arch/mips/loongson32/common/Makefile +++ b/arch/mips/loongson32/common/Makefile @@ -3,4 +3,4 @@ # Makefile for common code of loongson1 based machines. # -obj-y += irq.o platform.o +obj-y += platform.o diff --git a/arch/mips/loongson32/common/irq.c b/arch/mips/loongson32/common/irq.c deleted file mode 100644 index 9a50070f74f7..000000000000 --- a/arch/mips/loongson32/common/irq.c +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@xxxxxxxxx> - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <asm/irq_cpu.h> - -#include <loongson1.h> -#include <irq.h> - -#define LS1X_INTC_REG(n, x) \ - ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x))) - -#define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0) -#define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4) -#define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8) -#define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc) -#define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10) -#define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14) - -static void ls1x_irq_ack(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) - | (1 << bit), LS1X_INTC_INTCLR(n)); -} - -static void ls1x_irq_mask(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) - & ~(1 << bit), LS1X_INTC_INTIEN(n)); -} - -static void ls1x_irq_mask_ack(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) - & ~(1 << bit), LS1X_INTC_INTIEN(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) - | (1 << bit), LS1X_INTC_INTCLR(n)); -} - -static void ls1x_irq_unmask(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) - | (1 << bit), LS1X_INTC_INTIEN(n)); -} - -static int ls1x_irq_settype(struct irq_data *d, unsigned int type) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - switch (type) { - case IRQ_TYPE_LEVEL_HIGH: - __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n)) - | (1 << bit), LS1X_INTC_INTPOL(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n)) - & ~(1 << bit), LS1X_INTC_INTEDGE(n)); - break; - case IRQ_TYPE_LEVEL_LOW: - __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n)) - & ~(1 << bit), LS1X_INTC_INTPOL(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n)) - & ~(1 << bit), LS1X_INTC_INTEDGE(n)); - break; - case IRQ_TYPE_EDGE_RISING: - __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n)) - | (1 << bit), LS1X_INTC_INTPOL(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n)) - | (1 << bit), LS1X_INTC_INTEDGE(n)); - break; - case IRQ_TYPE_EDGE_FALLING: - __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n)) - & ~(1 << bit), LS1X_INTC_INTPOL(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n)) - | (1 << bit), LS1X_INTC_INTEDGE(n)); - break; - case IRQ_TYPE_EDGE_BOTH: - __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n)) - & ~(1 << bit), LS1X_INTC_INTPOL(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n)) - | (1 << bit), LS1X_INTC_INTEDGE(n)); - break; - case IRQ_TYPE_NONE: - break; - default: - return -EINVAL; - } - - return 0; -} - -static struct irq_chip ls1x_irq_chip = { - .name = "LS1X-INTC", - .irq_ack = ls1x_irq_ack, - .irq_mask = ls1x_irq_mask, - .irq_mask_ack = ls1x_irq_mask_ack, - .irq_unmask = ls1x_irq_unmask, - .irq_set_type = ls1x_irq_settype, -}; - -static void ls1x_irq_dispatch(int n) -{ - u32 int_status, irq; - - /* Get pending sources, masked by current enables */ - int_status = __raw_readl(LS1X_INTC_INTISR(n)) & - __raw_readl(LS1X_INTC_INTIEN(n)); - - if (int_status) { - irq = LS1X_IRQ(n, __ffs(int_status)); - do_IRQ(irq); - } -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending; - - pending = read_c0_cause() & read_c0_status() & ST0_IM; - - if (pending & CAUSEF_IP7) - do_IRQ(TIMER_IRQ); - else if (pending & CAUSEF_IP2) - ls1x_irq_dispatch(0); /* INT0 */ - else if (pending & CAUSEF_IP3) - ls1x_irq_dispatch(1); /* INT1 */ - else if (pending & CAUSEF_IP4) - ls1x_irq_dispatch(2); /* INT2 */ - else if (pending & CAUSEF_IP5) - ls1x_irq_dispatch(3); /* INT3 */ - else if (pending & CAUSEF_IP6) - ls1x_irq_dispatch(4); /* INT4 */ - else - spurious_interrupt(); - -} - -static void __init ls1x_irq_init(int base) -{ - int n; - - /* Disable interrupts and clear pending, - * setup all IRQs as high level triggered - */ - for (n = 0; n < INTN; n++) { - __raw_writel(0x0, LS1X_INTC_INTIEN(n)); - __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n)); - __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n)); - /* set DMA0, DMA1 and DMA2 to edge trigger */ - __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n)); - } - - - for (n = base; n < NR_IRQS; n++) { - irq_set_chip_and_handler(n, &ls1x_irq_chip, - handle_level_irq); - } - - if (request_irq(INT0_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL)) - pr_err("Failed to request irq %d (cascade)\n", INT0_IRQ); - if (request_irq(INT1_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL)) - pr_err("Failed to request irq %d (cascade)\n", INT1_IRQ); - if (request_irq(INT2_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL)) - pr_err("Failed to request irq %d (cascade)\n", INT2_IRQ); - if (request_irq(INT3_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL)) - pr_err("Failed to request irq %d (cascade)\n", INT3_IRQ); -#if defined(CONFIG_LOONGSON1_LS1C) - if (request_irq(INT4_IRQ, no_action, IRQF_NO_THREAD, "cascade", NULL)) - pr_err("Failed to request irq %d (cascade)\n", INT4_IRQ); -#endif -} - -void __init arch_init_irq(void) -{ - mips_cpu_irq_init(); - ls1x_irq_init(LS1X_IRQ_BASE); -} diff --git a/arch/mips/loongson32/init.c b/arch/mips/loongson32/init.c index 1aada785a4a3..d8ef5362c74b 100644 --- a/arch/mips/loongson32/init.c +++ b/arch/mips/loongson32/init.c @@ -76,3 +76,8 @@ void __init plat_time_init(void) timer_probe(); } + +void __init arch_init_irq(void) +{ + irqchip_init(); +} -- 2.39.2