rtl838x: Add irq settings for RTL839x SoCs
authorBirger Koblitz <git@birger-koblitz.de>
Fri, 25 Sep 2020 04:49:51 +0000 (06:49 +0200)
committerJohn Crispin <john@phrozen.org>
Thu, 15 Oct 2020 06:23:46 +0000 (08:23 +0200)
This adds correct interrupt routing settings for IRQs on the RTL839x SoCs.
It also speeds up irq handling based on work by biot for all SoCs.

Signed-off-by: Birger Koblitz <git@birger-koblitz.de>
target/linux/rtl838x/files-5.4/arch/mips/include/asm/mach-rtl838x/mach-rtl838x.h
target/linux/rtl838x/files-5.4/arch/mips/rtl838x/irq.c

index cece36635c694ee239a54f139c2cd7899e957fb4..4050661d3333e6c0a137bcc0cf1d60a001644a85 100644 (file)
 #define rtl838x_w32(val, reg)  __raw_writel(val, reg)
 #define rtl838x_w32_mask(clear, set, reg) rtl838x_w32((rtl838x_r32(reg) & ~(clear)) | (set), reg)
 
+#define rtl838x_r8(reg)                __raw_readb(reg)
+#define rtl838x_w8(val, reg)   __raw_writeb(val, reg)
+
 #define sw_r32(reg)            __raw_readl(RTL838X_SW_BASE + reg)
 #define sw_w32(val, reg)       __raw_writel(val, RTL838X_SW_BASE + reg)
 #define sw_w32_mask(clear, set, reg)   \
                                sw_w32((sw_r32(reg) & ~(clear)) | (set), reg)
-
 #define sw_r64(reg)            ((((u64)__raw_readl(RTL838X_SW_BASE + reg)) << 32) | \
                                __raw_readl(RTL838X_SW_BASE + reg + 4))
 
 
 #define IRR1                   (0x0c)
 
-#define IRR1_SETTING           ((GPIO_ABCD_RS << 28) | \
+#define IRR1_SETTING_RTL838X   ((GPIO_ABCD_RS << 28) | \
                                 (GPIO_EFGH_RS << 24) | \
                                 (RTC_RS       << 20) | \
                                 (SWCORE_RS    << 16)   \
                                )
+#define IRR1_SETTING_RTL839X   ((GPIO_ABCD_RS << 28) | \
+                                (SWCORE_RS    << 16)   \
+                               )
+
 
 #define IRR2                   (0x10)
 #define IRR2_SETTING           0
index 34e90982b2d1d8b4b512efe6d44fa149bc061f69..0c3a311d1d9c73ae408bf6395575dbdd30621a97 100644 (file)
@@ -29,36 +29,7 @@ extern struct rtl838x_soc_info soc_info;
 static DEFINE_RAW_SPINLOCK(irq_lock);
 
 extern irqreturn_t c0_compare_interrupt(int irq, void *dev_id);
-unsigned int rtl838x_ictl_irq_dispatch1(void);
-unsigned int rtl838x_ictl_irq_dispatch2(void);
-unsigned int rtl838x_ictl_irq_dispatch3(void);
-unsigned int rtl838x_ictl_irq_dispatch4(void);
-unsigned int rtl838x_ictl_irq_dispatch5(void);
-
-static struct irqaction irq_cascade1 = {
-       .handler = no_action,
-       .name = "RTL838X IRQ cascade1",
-};
-
-static struct irqaction irq_cascade2 = {
-       .handler = no_action,
-       .name = "RTL838X IRQ cascade2",
-};
-
-static struct irqaction irq_cascade3 = {
-       .handler = no_action,
-       .name = "RTL838X IRQ cascade3",
-};
-
-static struct irqaction irq_cascade4 = {
-       .handler = no_action,
-       .name = "RTL838X IRQ cascade4",
-};
 
-static struct irqaction irq_cascade5 = {
-       .handler = no_action,
-       .name = "RTL838X IRQ cascade5",
-};
 
 static void rtl838x_ictl_enable_irq(struct irq_data *i)
 {
@@ -69,12 +40,6 @@ static void rtl838x_ictl_enable_irq(struct irq_data *i)
        raw_spin_unlock_irqrestore(&irq_lock, flags);
 }
 
-static unsigned int rtl838x_ictl_startup_irq(struct irq_data *i)
-{
-       rtl838x_ictl_enable_irq(i);
-       return 0;
-}
-
 static void rtl838x_ictl_disable_irq(struct irq_data *i)
 {
        unsigned long flags;
@@ -94,9 +59,7 @@ static void rtl838x_ictl_eoi_irq(struct irq_data *i)
 }
 
 static struct irq_chip rtl838x_ictl_irq = {
-       .name = "RTL838X",
-       .irq_startup = rtl838x_ictl_startup_irq,
-       .irq_shutdown = rtl838x_ictl_disable_irq,
+       .name = "RTL83xx",
        .irq_enable = rtl838x_ictl_enable_irq,
        .irq_disable = rtl838x_ictl_disable_irq,
        .irq_ack = rtl838x_ictl_disable_irq,
@@ -106,113 +69,57 @@ static struct irq_chip rtl838x_ictl_irq = {
 };
 
 /*
- *   RTL8390/80/28 Interrupt Scheme
+ *  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
+ *  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
  */
 
-unsigned int rtl838x_ictl_irq_dispatch1(void)
-{
-       /* Identify shared IRQ  */
-       unsigned int extint_ip = icu_r32(GIMR) & icu_r32(GISR);
-
-       if (extint_ip & TC1_IP)
-               do_IRQ(TC1_IRQ);
-       else if (extint_ip & UART1_IP)
-               do_IRQ(UART1_IRQ);
-       else
-               spurious_interrupt();
-
-       return IRQ_HANDLED;
-}
-
-unsigned int rtl838x_ictl_irq_dispatch2(void)
-{
-       do_IRQ(UART0_IRQ);
-       return IRQ_HANDLED;
-}
-
-unsigned int rtl838x_ictl_irq_dispatch3(void)
-{
-       do_IRQ(SWCORE_IRQ);
-       return IRQ_HANDLED;
-}
-
-unsigned int rtl838x_ictl_irq_dispatch4(void)
-{
-       /* Identify shared IRQ */
-       unsigned int extint_ip = icu_r32(GIMR) & icu_r32(GISR);
-
-       if (extint_ip & NIC_IP)
-               do_IRQ(NIC_IRQ);
-       else if (extint_ip & GPIO_ABCD_IP)
-               do_IRQ(GPIO_ABCD_IRQ);
-       else if ((extint_ip & GPIO_EFGH_IP) && (soc_info.family == RTL8328_FAMILY_ID))
-               do_IRQ(GPIO_EFGH_IRQ);
-       else
-               spurious_interrupt();
-
-       return IRQ_HANDLED;
-}
-
-unsigned int rtl838x_ictl_irq_dispatch5(void)
-{
-       do_IRQ(TC0_IRQ);
-       return IRQ_HANDLED;
-}
-
 asmlinkage void plat_irq_dispatch(void)
 {
-       unsigned int pending;
+       unsigned int pending, ext_int;
 
-       pending =  read_c0_cause() & read_c0_status() & ST0_IM;
+       pending =  read_c0_cause();
 
-       if (pending & CAUSEF_IP7)
+       if (pending & CAUSEF_IP7) {
                c0_compare_interrupt(7, NULL);
-       else if (pending & CAUSEF_IP6)
-               rtl838x_ictl_irq_dispatch5();
-       else if (pending & CAUSEF_IP5)
-               rtl838x_ictl_irq_dispatch4();
-       else if (pending & CAUSEF_IP4)
-               rtl838x_ictl_irq_dispatch3();
-       else if (pending & CAUSEF_IP3)
-               rtl838x_ictl_irq_dispatch2();
-       else if (pending & CAUSEF_IP2)
-               rtl838x_ictl_irq_dispatch1();
-       else
+       } else if (pending & CAUSEF_IP6) {
+               do_IRQ(TC0_IRQ);
+       } 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);
+               else
+                       spurious_interrupt();
+       } else if (pending & CAUSEF_IP4) {
+               do_IRQ(SWCORE_IRQ);
+       } else if (pending & CAUSEF_IP3) {
+               do_IRQ(UART0_IRQ);
+       } 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);
+               else
+                       spurious_interrupt();
+       } else {
                spurious_interrupt();
-}
-
-static void __init rtl838x_ictl_irq_init(unsigned int irq_base)
-{
-       int i;
-
-       for (i = 0; i < RTL838X_IRQ_ICTL_NUM; i++)
-               irq_set_chip_and_handler(irq_base + i, &rtl838x_ictl_irq, handle_level_irq);
-
-       setup_irq(RTL838X_ICTL1_IRQ, &irq_cascade1);
-       setup_irq(RTL838X_ICTL2_IRQ, &irq_cascade2);
-       setup_irq(RTL838X_ICTL3_IRQ, &irq_cascade3);
-       setup_irq(RTL838X_ICTL4_IRQ, &irq_cascade4);
-       setup_irq(RTL838X_ICTL5_IRQ, &irq_cascade5);
-
-       /* Set GIMR, IRR */
-       icu_w32(TC0_IE | UART0_IE, GIMR);
-       icu_w32(IRR0_SETTING, IRR0);
-       icu_w32(IRR1_SETTING, IRR1);
-       icu_w32(IRR2_SETTING, IRR2);
-       icu_w32(IRR3_SETTING, IRR3);
+       }
 }
 
 static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
@@ -234,11 +141,12 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
        struct resource res;
 
        pr_info("Found Interrupt controller: %s (%s)\n", node->name, node->full_name);
-       if (of_address_to_resource(node, 0, &res)) {
+       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);
 
@@ -247,10 +155,44 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
        domain = irq_domain_add_simple(node, 32, 0, &irq_domain_ops, NULL);
 
        /* Setup all external HW irqs */
-       for (i = 8; i < 32; i++)
+       for (i = 8; i < RTL838X_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);
+       }
 
-       rtl838x_ictl_irq_init(RTL838X_IRQ_ICTL_BASE);
+       if (request_irq(RTL838X_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);
+       }
+       if (request_irq(RTL838X_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);
+       }
+       if (request_irq(RTL838X_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);
+       }
+       if (request_irq(RTL838X_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);
+       }
+       if (request_irq(RTL838X_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);
+       }
+
+       /* 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);
+
+       /* Enable timer0 and uart0 interrupts */
+       icu_w32(TC0_IE | UART0_IE, GIMR);
        return 0;
 }