rtl83xx: make use of biot's irq.c
authorJohn Crispin <john@phrozen.org>
Wed, 25 Nov 2020 07:51:35 +0000 (08:51 +0100)
committerJohn Crispin <john@phrozen.org>
Wed, 25 Nov 2020 07:51:35 +0000 (08:51 +0100)
Signed-off-by: John Crispin <john@phrozen.org>
target/linux/rtl838x/dts/rtl838x.dtsi
target/linux/rtl838x/files-5.4/arch/mips/include/asm/mach-rtl838x/irq.h
target/linux/rtl838x/files-5.4/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h
target/linux/rtl838x/files-5.4/arch/mips/rtl838x/irq.c

index 75cb613b2fe195bcc1e4f3cb957dea7ea264d3bd..ec4a523c14f40a6f01f190563305bd7725a2d1fa 100644 (file)
@@ -65,7 +65,7 @@
                #address-cells = <0>;
                #interrupt-cells = <1>;
                interrupt-controller;
-               compatible = "rtl838x,icu";
+               compatible = "rtl83xx,icu";
                reg = <0xb8003000 0x20>;
        };
 
index e821111c5d36efc8f585534f36a64f571246b889..580c3d8d61db0ef2060f70fec817d97309e4758b 100644 (file)
@@ -1,10 +1,66 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef __ASM_MACH_RTL838X_IRQ_H
-#define __ASM_MACH_RTL838X_IRQ_H
+// SPDX-License-Identifier: GPL-2.0-only
 
-#define MIPS_CPU_IRQ_BASE      0
-#define NR_IRQS                        64
+#ifndef _RTL83XX_IRQ_H_
+#define _RTL83XX_IRQ_H_
 
+#define NR_IRQS 32
 #include_next <irq.h>
 
-#endif /* __ASM_MACH_ATH79_IRQ_H */
+/* Global Interrupt Mask Register */
+#define RTL83XX_ICTL_GIMR      0x00
+/* Global Interrupt Status Register */
+#define RTL83XX_ICTL_GISR      0x04
+
+#define RTL83XX_IRQ_CPU_BASE   0
+#define RTL83XX_IRQ_CPU_NUM    8
+#define RTL83XX_IRQ_ICTL_BASE  (RTL83XX_IRQ_CPU_BASE + RTL83XX_IRQ_CPU_NUM)
+#define RTL83XX_IRQ_ICTL_NUM   32
+
+/* Cascaded interrupts */
+#define RTL83XX_ICTL1_IRQ      (RTL83XX_IRQ_CPU_BASE + 2)
+#define RTL83XX_ICTL2_IRQ      (RTL83XX_IRQ_CPU_BASE + 3)
+#define RTL83XX_ICTL3_IRQ      (RTL83XX_IRQ_CPU_BASE + 4)
+#define RTL83XX_ICTL4_IRQ      (RTL83XX_IRQ_CPU_BASE + 5)
+#define RTL83XX_ICTL5_IRQ      (RTL83XX_IRQ_CPU_BASE + 6)
+
+/* Interrupt routing register */
+#define RTL83XX_IRR0           0x08
+#define RTL83XX_IRR1           0x0c
+#define RTL83XX_IRR2           0x10
+#define RTL83XX_IRR3           0x14
+
+/* Cascade map */
+#define UART0_CASCADE          2
+#define UART1_CASCADE          1
+#define TC0_CASCADE            5
+#define TC1_CASCADE            1
+#define OCPTO_CASCADE          1
+#define HLXTO_CASCADE          1
+#define SLXTO_CASCADE          1
+#define NIC_CASCADE            4
+#define GPIO_ABCD_CASCADE      4
+#define GPIO_EFGH_CASCADE      4
+#define RTC_CASCADE            4
+#define        SWCORE_CASCADE          3
+#define WDT_IP1_CASCADE                4
+#define WDT_IP2_CASCADE                5
+
+/* Pack cascade map into interrupt routing registers */
+#define RTL83XX_IRR0_SETTING (\
+       (UART0_CASCADE          << 28) | \
+       (UART1_CASCADE          << 24) | \
+       (TC0_CASCADE            << 20) | \
+       (TC1_CASCADE            << 16) | \
+       (OCPTO_CASCADE          << 12) | \
+       (HLXTO_CASCADE          << 8)  | \
+       (SLXTO_CASCADE          << 4)  | \
+       (NIC_CASCADE            << 0))
+#define RTL83XX_IRR1_SETTING (\
+       (GPIO_ABCD_CASCADE      << 28) | \
+       (GPIO_EFGH_CASCADE      << 24) | \
+       (RTC_CASCADE            << 20) | \
+       (SWCORE_CASCADE         << 16))
+#define RTL83XX_IRR2_SETTING   0
+#define RTL83XX_IRR3_SETTING   0
+
+#endif /* _RTL83XX_IRQ_H_ */
index 2cabbb4103b69079720cc8de4b0b373bdb0c7306..f89adcc12736f87283ef74343ba872ec56263a46 100644 (file)
 #define RTL838X_IRQ_ICTL_BASE  (RTL838X_IRQ_CPU_BASE + RTL838X_IRQ_CPU_NUM)
 #define RTL838X_IRQ_ICTL_NUM   32
 
+#define RTL83XX_IRQ_UART0               31
+#define RTL83XX_IRQ_UART1               30
+#define RTL83XX_IRQ_TC0                 29
+#define RTL83XX_IRQ_TC1                 28
+#define RTL83XX_IRQ_OCPTO               27
+#define RTL83XX_IRQ_HLXTO               26
+#define RTL83XX_IRQ_SLXTO               25
+#define RTL83XX_IRQ_NIC                 24
+#define RTL83XX_IRQ_GPIO_ABCD           23
+#define RTL83XX_IRQ_GPIO_EFGH           22
+#define RTL83XX_IRQ_RTC                 21
+#define RTL83XX_IRQ_SWCORE              20
+#define RTL83XX_IRQ_WDT_IP1             19
+#define RTL83XX_IRQ_WDT_IP2             18
+
+
 /*
  * MIPS32R2 counter
  */
index a2b24fd343bfd08667ca6e6a3fdc7ad43b0a1e8f..8e19b090105418de34644778cc81d606bfbde189 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Realtek RTL838X architecture specific IRQ handling
+ * Realtek RTL83XX architecture specific IRQ handling
  *
  * Copyright  (C) 2020 B. Koblitz
  * based on the original BSP
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/irqchip.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
 #include <linux/spinlock.h>
-
+#include <linux/of_address.h>
 #include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
+#include <asm/cevt-r4k.h>
+
 #include <mach-rtl83xx.h>
+#include "irq.h"
 
-extern struct rtl83xx_soc_info soc_info;
 
-#define icu_r32(reg)                   rtl83xx_r32(soc_info.icu_base + reg)
-#define icu_w32(val, reg)              rtl83xx_w32(val, soc_info.icu_base + reg)
-#define icu_w32_mask(clear, set, reg)  rtl83xx_w32_mask(clear, set, soc_info.icu_base + reg)
+#define REG(x)         (rtl83xx_ictl_base + x)
 
-static DEFINE_RAW_SPINLOCK(irq_lock);
+extern struct rtl83xx_soc_info soc_info;
 
-extern irqreturn_t c0_compare_interrupt(int irq, void *dev_id);
+static DEFINE_RAW_SPINLOCK(irq_lock);
+static void __iomem *rtl83xx_ictl_base;
 
 
-static void rtl838x_ictl_enable_irq(struct irq_data *i)
+static void rtl83xx_ictl_enable_irq(struct irq_data *i)
 {
        unsigned long flags;
+       u32 value;
 
        raw_spin_lock_irqsave(&irq_lock, flags);
-       icu_w32_mask(0, 1 << i->irq, GIMR);
-       raw_spin_unlock_irqrestore(&irq_lock, flags);
-}
 
-static void rtl838x_ictl_disable_irq(struct irq_data *i)
-{
-       unsigned long flags;
+       value = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR));
+       value |= BIT(i->irq);
+       rtl83xx_w32(value, REG(RTL83XX_ICTL_GIMR));
 
-       raw_spin_lock_irqsave(&irq_lock, flags);
-       icu_w32_mask(1 << i->irq, 0, GIMR);
        raw_spin_unlock_irqrestore(&irq_lock, flags);
 }
 
-static void rtl838x_ictl_eoi_irq(struct irq_data *i)
+static void rtl83xx_ictl_disable_irq(struct irq_data *i)
 {
        unsigned long flags;
+       u32 value;
 
        raw_spin_lock_irqsave(&irq_lock, flags);
-       icu_w32_mask(0, 1 << i->irq, GIMR);
+
+       value = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR));
+       value &= ~BIT(i->irq);
+       rtl83xx_w32(value, REG(RTL83XX_ICTL_GIMR));
+
        raw_spin_unlock_irqrestore(&irq_lock, flags);
 }
 
-static struct irq_chip rtl838x_ictl_irq = {
+static struct irq_chip rtl83xx_ictl_irq = {
        .name = "RTL83xx",
-       .irq_enable = rtl838x_ictl_enable_irq,
-       .irq_disable = rtl838x_ictl_disable_irq,
-       .irq_ack = rtl838x_ictl_disable_irq,
-       .irq_mask = rtl838x_ictl_disable_irq,
-       .irq_unmask = rtl838x_ictl_enable_irq,
-       .irq_eoi = rtl838x_ictl_eoi_irq,
+       .irq_enable = rtl83xx_ictl_enable_irq,
+       .irq_disable = rtl83xx_ictl_disable_irq,
+       .irq_ack = rtl83xx_ictl_disable_irq,
+       .irq_mask = rtl83xx_ictl_disable_irq,
+       .irq_unmask = rtl83xx_ictl_enable_irq,
+       .irq_eoi = rtl83xx_ictl_enable_irq,
 };
 
-/*
- *  RTL8390/80/28 Interrupt Scheme
- *
- *  Source       IRQ      CPU INT
- *  --------   -------    -------
- *  UART0          31        IP3
- *  UART1          30        IP2
- *  TIMER0         29        IP6
- *  TIMER1         28        IP2
- *  OCPTO          27        IP2
- *  HLXTO          26        IP2
- *  SLXTO          25        IP2
- *  NIC            24        IP5
- *  GPIO_ABCD      23        IP5
- *  SWCORE         20        IP4
- */
-
 asmlinkage void plat_irq_dispatch(void)
 {
        unsigned int pending, ext_int;
 
-       pending =  read_c0_cause();
+       pending =  read_c0_cause() & read_c0_status() & ST0_IM;
 
        if (pending & CAUSEF_IP7) {
                c0_compare_interrupt(7, NULL);
+
        } else if (pending & CAUSEF_IP6) {
-               do_IRQ(TC0_IRQ);
+               do_IRQ(RTL83XX_IRQ_TC0);
+
        } else if (pending & CAUSEF_IP5) {
-               ext_int = icu_r32(GIMR) & icu_r32(GISR);
-               if (ext_int & NIC_IP)
-                       do_IRQ(NIC_IRQ);
-               else if (ext_int & GPIO_ABCD_IP)
-                       do_IRQ(GPIO_ABCD_IRQ);
-               else if ((ext_int & GPIO_EFGH_IP) && (soc_info.family == RTL8328_FAMILY_ID))
-                       do_IRQ(GPIO_EFGH_IRQ);
+               ext_int = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)) & rtl83xx_r32(REG(RTL83XX_ICTL_GISR));
+               if (ext_int & BIT(RTL83XX_IRQ_NIC))
+                       do_IRQ(RTL83XX_IRQ_NIC);
+               else if (ext_int & BIT(RTL83XX_IRQ_GPIO_ABCD))
+                       do_IRQ(RTL83XX_IRQ_GPIO_ABCD);
+               else if ((ext_int & BIT(RTL83XX_IRQ_GPIO_EFGH)) && (soc_info.family == RTL8328_FAMILY_ID))
+                       do_IRQ(RTL83XX_IRQ_GPIO_EFGH);
                else
                        spurious_interrupt();
+
        } else if (pending & CAUSEF_IP4) {
-               do_IRQ(SWCORE_IRQ);
+               do_IRQ(RTL83XX_IRQ_SWCORE);
+
        } else if (pending & CAUSEF_IP3) {
-               do_IRQ(UART0_IRQ);
+               do_IRQ(RTL83XX_IRQ_UART0);
+
        } else if (pending & CAUSEF_IP2) {
-               ext_int = icu_r32(GIMR) & icu_r32(GISR);
-               if (ext_int & TC1_IP)
-                       do_IRQ(TC1_IRQ);
-               else if (ext_int & UART1_IP)
-                       do_IRQ(UART1_IRQ);
+               ext_int = rtl83xx_r32(REG(RTL83XX_ICTL_GIMR)) & rtl83xx_r32(REG(RTL83XX_ICTL_GISR));
+               if (ext_int & BIT(RTL83XX_IRQ_TC1))
+                       do_IRQ(RTL83XX_IRQ_TC1);
+               else if (ext_int & BIT(RTL83XX_IRQ_UART1))
+                       do_IRQ(RTL83XX_IRQ_UART1);
                else
                        spurious_interrupt();
+
        } else {
                spurious_interrupt();
        }
@@ -124,82 +109,80 @@ asmlinkage void plat_irq_dispatch(void)
 
 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
-       irq_set_chip_and_handler(hw, &rtl838x_ictl_irq, handle_level_irq);
+       irq_set_chip_and_handler(hw, &rtl83xx_ictl_irq, handle_level_irq);
 
        return 0;
 }
 
 static const struct irq_domain_ops irq_domain_ops = {
-       .xlate = irq_domain_xlate_onecell,
        .map = intc_map,
+       .xlate = irq_domain_xlate_onecell,
 };
 
 int __init icu_of_init(struct device_node *node, struct device_node *parent)
 {
-       int i;
        struct irq_domain *domain;
-       struct resource res;
-
-       pr_info("Found Interrupt controller: %s (%s)\n", node->name, node->full_name);
-       if (of_address_to_resource(node, 0, &res))
-               panic("Failed to get icu memory range");
-
-       if (!request_mem_region(res.start, resource_size(&res), res.name))
-               pr_err("Failed to request icu memory\n");
-
-       soc_info.icu_base = ioremap(res.start, resource_size(&res));
-       pr_info("ICU Memory: %08x\n", (u32)soc_info.icu_base);
+       int i;
 
        mips_cpu_irq_init();
 
        domain = irq_domain_add_simple(node, 32, 0, &irq_domain_ops, NULL);
 
-       /* Setup all external HW irqs */
-       for (i = 8; i < RTL838X_IRQ_ICTL_NUM; i++) {
+       rtl83xx_ictl_base = of_iomap(node, 0);
+       if (!rtl83xx_ictl_base)
+               return -EIO;
+
+       for (i = 8; i < RTL83XX_IRQ_ICTL_NUM; i++) {
                irq_domain_associate(domain, i, i);
-               irq_set_chip_and_handler(RTL838X_IRQ_ICTL_BASE + i,
-                                        &rtl838x_ictl_irq, handle_level_irq);
+               irq_set_chip_and_handler(RTL83XX_IRQ_ICTL_BASE + i,
+                                        &rtl83xx_ictl_irq, handle_level_irq);
        }
 
-       if (request_irq(RTL838X_ICTL1_IRQ, no_action, IRQF_NO_THREAD,
+       if (request_irq(RTL83XX_ICTL1_IRQ, no_action, IRQF_NO_THREAD,
                        "IRQ cascade 1", NULL)) {
-               pr_err("request_irq() cascade 1 for irq %d failed\n", RTL838X_ICTL1_IRQ);
+               pr_err("request_irq() cascade 1 for irq %d failed\n", RTL83XX_ICTL1_IRQ);
        }
-       if (request_irq(RTL838X_ICTL2_IRQ, no_action, IRQF_NO_THREAD,
+       if (request_irq(RTL83XX_ICTL2_IRQ, no_action, IRQF_NO_THREAD,
                        "IRQ cascade 2", NULL)) {
-               pr_err("request_irq() cascade 2 for irq %d failed\n", RTL838X_ICTL2_IRQ);
+               pr_err("request_irq() cascade 2 for irq %d failed\n", RTL83XX_ICTL2_IRQ);
        }
-       if (request_irq(RTL838X_ICTL3_IRQ, no_action, IRQF_NO_THREAD,
+       if (request_irq(RTL83XX_ICTL3_IRQ, no_action, IRQF_NO_THREAD,
                        "IRQ cascade 3", NULL)) {
-               pr_err("request_irq() cascade 3 for irq %d failed\n", RTL838X_ICTL3_IRQ);
+               pr_err("request_irq() cascade 3 for irq %d failed\n", RTL83XX_ICTL3_IRQ);
        }
-       if (request_irq(RTL838X_ICTL4_IRQ, no_action, IRQF_NO_THREAD,
+       if (request_irq(RTL83XX_ICTL4_IRQ, no_action, IRQF_NO_THREAD,
                        "IRQ cascade 4", NULL)) {
-               pr_err("request_irq() cascade 4 for irq %d failed\n", RTL838X_ICTL4_IRQ);
+               pr_err("request_irq() cascade 4 for irq %d failed\n", RTL83XX_ICTL4_IRQ);
        }
-       if (request_irq(RTL838X_ICTL5_IRQ, no_action, IRQF_NO_THREAD,
+       if (request_irq(RTL83XX_ICTL5_IRQ, no_action, IRQF_NO_THREAD,
                        "IRQ cascade 5", NULL)) {
-               pr_err("request_irq() cascade 5 for irq %d failed\n", RTL838X_ICTL5_IRQ);
+               pr_err("request_irq() cascade 5 for irq %d failed\n", RTL83XX_ICTL5_IRQ);
        }
 
-       /* Set up interrupt routing scheme */
-       icu_w32(IRR0_SETTING, IRR0);
-       if (soc_info.family == RTL8380_FAMILY_ID)
-               icu_w32(IRR1_SETTING_RTL838X, IRR1);
-       else
-               icu_w32(IRR1_SETTING_RTL839X, IRR1);
-       icu_w32(IRR2_SETTING, IRR2);
-       icu_w32(IRR3_SETTING, IRR3);
+       /* Disable all cascaded interrupts */
+       rtl83xx_w32(0, REG(RTL83XX_ICTL_GIMR));
+
+       /* Set up interrupt routing */
+       rtl83xx_w32(RTL83XX_IRR0_SETTING, REG(RTL83XX_IRR0));
+       rtl83xx_w32(RTL83XX_IRR1_SETTING, REG(RTL83XX_IRR1));
+       rtl83xx_w32(RTL83XX_IRR2_SETTING, REG(RTL83XX_IRR2));
+       rtl83xx_w32(RTL83XX_IRR3_SETTING, REG(RTL83XX_IRR3));
+
+       /* Clear timer interrupt */
+       write_c0_compare(0);
+
+       /* Enable all CPU interrupts */
+       write_c0_status(read_c0_status() | ST0_IM);
 
        /* Enable timer0 and uart0 interrupts */
-       icu_w32(TC0_IE | UART0_IE, GIMR);
+       rtl83xx_w32(BIT(RTL83XX_IRQ_TC0) | BIT(RTL83XX_IRQ_UART0), REG(RTL83XX_ICTL_GIMR));
+
        return 0;
 }
 
 void __init arch_init_irq(void)
 {
-       /* do board-specific irq initialization */
        irqchip_init();
 }
 
-IRQCHIP_DECLARE(mips_cpu_intc, "rtl838x,icu", icu_of_init);
+IRQCHIP_DECLARE(mips_cpu_intc, "rtl83xx,icu", icu_of_init);