root/arch/mips/loongson32/common/irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ls1x_irq_ack
  2. ls1x_irq_mask
  3. ls1x_irq_mask_ack
  4. ls1x_irq_unmask
  5. ls1x_irq_settype
  6. ls1x_irq_dispatch
  7. plat_irq_dispatch
  8. ls1x_irq_init
  9. arch_init_irq

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
   4  */
   5 
   6 #include <linux/interrupt.h>
   7 #include <linux/irq.h>
   8 #include <asm/irq_cpu.h>
   9 
  10 #include <loongson1.h>
  11 #include <irq.h>
  12 
  13 #define LS1X_INTC_REG(n, x) \
  14                 ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x)))
  15 
  16 #define LS1X_INTC_INTISR(n)             LS1X_INTC_REG(n, 0x0)
  17 #define LS1X_INTC_INTIEN(n)             LS1X_INTC_REG(n, 0x4)
  18 #define LS1X_INTC_INTSET(n)             LS1X_INTC_REG(n, 0x8)
  19 #define LS1X_INTC_INTCLR(n)             LS1X_INTC_REG(n, 0xc)
  20 #define LS1X_INTC_INTPOL(n)             LS1X_INTC_REG(n, 0x10)
  21 #define LS1X_INTC_INTEDGE(n)            LS1X_INTC_REG(n, 0x14)
  22 
  23 static void ls1x_irq_ack(struct irq_data *d)
  24 {
  25         unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  26         unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  27 
  28         __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
  29                         | (1 << bit), LS1X_INTC_INTCLR(n));
  30 }
  31 
  32 static void ls1x_irq_mask(struct irq_data *d)
  33 {
  34         unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  35         unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  36 
  37         __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  38                         & ~(1 << bit), LS1X_INTC_INTIEN(n));
  39 }
  40 
  41 static void ls1x_irq_mask_ack(struct irq_data *d)
  42 {
  43         unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  44         unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  45 
  46         __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  47                         & ~(1 << bit), LS1X_INTC_INTIEN(n));
  48         __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
  49                         | (1 << bit), LS1X_INTC_INTCLR(n));
  50 }
  51 
  52 static void ls1x_irq_unmask(struct irq_data *d)
  53 {
  54         unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  55         unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  56 
  57         __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
  58                         | (1 << bit), LS1X_INTC_INTIEN(n));
  59 }
  60 
  61 static int ls1x_irq_settype(struct irq_data *d, unsigned int type)
  62 {
  63         unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
  64         unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
  65 
  66         switch (type) {
  67         case IRQ_TYPE_LEVEL_HIGH:
  68                 __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  69                         | (1 << bit), LS1X_INTC_INTPOL(n));
  70                 __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  71                         & ~(1 << bit), LS1X_INTC_INTEDGE(n));
  72                 break;
  73         case IRQ_TYPE_LEVEL_LOW:
  74                 __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  75                         & ~(1 << bit), LS1X_INTC_INTPOL(n));
  76                 __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  77                         & ~(1 << bit), LS1X_INTC_INTEDGE(n));
  78                 break;
  79         case IRQ_TYPE_EDGE_RISING:
  80                 __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  81                         | (1 << bit), LS1X_INTC_INTPOL(n));
  82                 __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  83                         | (1 << bit), LS1X_INTC_INTEDGE(n));
  84                 break;
  85         case IRQ_TYPE_EDGE_FALLING:
  86                 __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  87                         & ~(1 << bit), LS1X_INTC_INTPOL(n));
  88                 __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  89                         | (1 << bit), LS1X_INTC_INTEDGE(n));
  90                 break;
  91         case IRQ_TYPE_EDGE_BOTH:
  92                 __raw_writel(__raw_readl(LS1X_INTC_INTPOL(n))
  93                         & ~(1 << bit), LS1X_INTC_INTPOL(n));
  94                 __raw_writel(__raw_readl(LS1X_INTC_INTEDGE(n))
  95                         | (1 << bit), LS1X_INTC_INTEDGE(n));
  96                 break;
  97         case IRQ_TYPE_NONE:
  98                 break;
  99         default:
 100                 return -EINVAL;
 101         }
 102 
 103         return 0;
 104 }
 105 
 106 static struct irq_chip ls1x_irq_chip = {
 107         .name           = "LS1X-INTC",
 108         .irq_ack        = ls1x_irq_ack,
 109         .irq_mask       = ls1x_irq_mask,
 110         .irq_mask_ack   = ls1x_irq_mask_ack,
 111         .irq_unmask     = ls1x_irq_unmask,
 112         .irq_set_type   = ls1x_irq_settype,
 113 };
 114 
 115 static void ls1x_irq_dispatch(int n)
 116 {
 117         u32 int_status, irq;
 118 
 119         /* Get pending sources, masked by current enables */
 120         int_status = __raw_readl(LS1X_INTC_INTISR(n)) &
 121                         __raw_readl(LS1X_INTC_INTIEN(n));
 122 
 123         if (int_status) {
 124                 irq = LS1X_IRQ(n, __ffs(int_status));
 125                 do_IRQ(irq);
 126         }
 127 }
 128 
 129 asmlinkage void plat_irq_dispatch(void)
 130 {
 131         unsigned int pending;
 132 
 133         pending = read_c0_cause() & read_c0_status() & ST0_IM;
 134 
 135         if (pending & CAUSEF_IP7)
 136                 do_IRQ(TIMER_IRQ);
 137         else if (pending & CAUSEF_IP2)
 138                 ls1x_irq_dispatch(0); /* INT0 */
 139         else if (pending & CAUSEF_IP3)
 140                 ls1x_irq_dispatch(1); /* INT1 */
 141         else if (pending & CAUSEF_IP4)
 142                 ls1x_irq_dispatch(2); /* INT2 */
 143         else if (pending & CAUSEF_IP5)
 144                 ls1x_irq_dispatch(3); /* INT3 */
 145         else if (pending & CAUSEF_IP6)
 146                 ls1x_irq_dispatch(4); /* INT4 */
 147         else
 148                 spurious_interrupt();
 149 
 150 }
 151 
 152 static struct irqaction cascade_irqaction = {
 153         .handler = no_action,
 154         .name = "cascade",
 155         .flags = IRQF_NO_THREAD,
 156 };
 157 
 158 static void __init ls1x_irq_init(int base)
 159 {
 160         int n;
 161 
 162         /* Disable interrupts and clear pending,
 163          * setup all IRQs as high level triggered
 164          */
 165         for (n = 0; n < INTN; n++) {
 166                 __raw_writel(0x0, LS1X_INTC_INTIEN(n));
 167                 __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n));
 168                 __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n));
 169                 /* set DMA0, DMA1 and DMA2 to edge trigger */
 170                 __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n));
 171         }
 172 
 173 
 174         for (n = base; n < NR_IRQS; n++) {
 175                 irq_set_chip_and_handler(n, &ls1x_irq_chip,
 176                                          handle_level_irq);
 177         }
 178 
 179         setup_irq(INT0_IRQ, &cascade_irqaction);
 180         setup_irq(INT1_IRQ, &cascade_irqaction);
 181         setup_irq(INT2_IRQ, &cascade_irqaction);
 182         setup_irq(INT3_IRQ, &cascade_irqaction);
 183 #if defined(CONFIG_LOONGSON1_LS1C)
 184         setup_irq(INT4_IRQ, &cascade_irqaction);
 185 #endif
 186 }
 187 
 188 void __init arch_init_irq(void)
 189 {
 190         mips_cpu_irq_init();
 191         ls1x_irq_init(LS1X_IRQ_BASE);
 192 }

/* [<][>][^][v][top][bottom][index][help] */