OSDN Git Service

irq-renesas-h8s: Fix external interrupt control.
authorYoshinori Sato <ysato@users.sourceforge.jp>
Wed, 15 Apr 2020 12:59:50 +0000 (21:59 +0900)
committerYoshinori Sato <ysato@users.sourceforge.jp>
Wed, 30 Mar 2022 09:57:17 +0000 (18:57 +0900)
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
drivers/irqchip/irq-renesas-h8s.c

index b69f2c8..0b8d9d7 100644 (file)
@@ -14,6 +14,8 @@
 static void *ipr_base;
 static void *icr_base;
 #define IPRA (ipr_base)
+#define IER  (icr_base + 2)
+#define ISR  (icr_base + 4)
 
 static const unsigned char ipr_table[] = {
        0x03, 0x02, 0x01, 0x00, 0x13, 0x12, 0x11, 0x10, /* 16 - 23 */
@@ -37,13 +39,22 @@ static void h8s_disable_irq(struct irq_data *data)
        int pos;
        void __iomem *addr;
        unsigned short pri;
-       int irq = data->irq;
+       int irq = data->irq - 16;
+       unsigned short ier;
+
+       if (irq < 0)
+               return;
 
-       addr = IPRA + ((ipr_table[irq - 16] & 0xf0) >> 3);
-       pos = (ipr_table[irq - 16] & 0x0f) * 4;
+       addr = IPRA + ((ipr_table[irq] & 0xf0) >> 3);
+       pos = (ipr_table[irq] & 0x0f) * 4;
        pri = ~(0x000f << pos);
        pri &= __raw_readw(addr);
        __raw_writew(pri, addr);
+       if (irq < 16) {
+               ier = __raw_readw(IER);
+               ier &= ~(1 << irq);
+               __raw_writew(ier, IER);
+       }
 }
 
 static void h8s_enable_irq(struct irq_data *data)
@@ -51,27 +62,35 @@ static void h8s_enable_irq(struct irq_data *data)
        int pos;
        void __iomem *addr;
        unsigned short pri;
-       int irq = data->irq;
+       int irq = data->irq - 16;
+       unsigned short ier;
+
+       if (irq < 0)
+               return;
 
-       addr = IPRA + ((ipr_table[irq - 16] & 0xf0) >> 3);
-       pos = (ipr_table[irq - 16] & 0x0f) * 4;
+       addr = IPRA + ((ipr_table[irq] & 0xf0) >> 3);
+       pos = (ipr_table[irq] & 0x0f) * 4;
        pri = ~(0x000f << pos);
        pri &= __raw_readw(addr);
        pri |= 1 << pos;
        __raw_writew(pri, addr);
+       if (irq < 16) {
+               ier = __raw_readw(IER);
+               ier &= ~(1 << irq);
+               __raw_writew(ier, IER);
+       }
 }
 
 static void h8s_ack_irq(struct irq_data *data)
 {
-       void __iomem *isr_addr = icr_base + 4;
        int irq = data->irq;
        uint16_t isr;
 
        if (irq >= 16 && irq < 32) {
                irq -= 16;
-               isr = __raw_readw(isr_addr);
+               isr = __raw_readw(ISR);
                isr &= ~(1 << irq);
-               __raw_writew(isr, isr_addr);
+               __raw_writew(isr, ISR);
        }
 }
 
@@ -110,7 +129,7 @@ static int __init h8s_intc_of_init(struct device_node *intc,
        for (n = 0; n <= 'k' - 'a'; n++)
                __raw_writew(0x0000, IPRA + (n * 2));
 
-       __raw_writew(0xffff, icr_base + 2);
+       __raw_writew(0xffff, IER);
        domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL);
        BUG_ON(!domain);
        irq_set_default_host(domain);