~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/kernel/irq-msc01.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  *
  4  * Copyright (c) 2004 MIPS Inc
  5  * Author: chris@mips.com
  6  *
  7  * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org>
  8  */
  9 #include <linux/interrupt.h>
 10 #include <linux/kernel.h>
 11 #include <linux/sched.h>
 12 #include <linux/kernel_stat.h>
 13 #include <asm/io.h>
 14 #include <asm/irq.h>
 15 #include <asm/msc01_ic.h>
 16 #include <asm/traps.h>
 17 
 18 static unsigned long _icctrl_msc;
 19 #define MSC01_IC_REG_BASE       _icctrl_msc
 20 
 21 #define MSCIC_WRITE(reg, data)  do { *(volatile u32 *)(reg) = data; } while (0)
 22 #define MSCIC_READ(reg, data)   do { data = *(volatile u32 *)(reg); } while (0)
 23 
 24 static unsigned int irq_base;
 25 
 26 /* mask off an interrupt */
 27 static inline void mask_msc_irq(struct irq_data *d)
 28 {
 29         unsigned int irq = d->irq;
 30 
 31         if (irq < (irq_base + 32))
 32                 MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
 33         else
 34                 MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32));
 35 }
 36 
 37 /* unmask an interrupt */
 38 static inline void unmask_msc_irq(struct irq_data *d)
 39 {
 40         unsigned int irq = d->irq;
 41 
 42         if (irq < (irq_base + 32))
 43                 MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
 44         else
 45                 MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32));
 46 }
 47 
 48 /*
 49  * Masks and ACKs an IRQ
 50  */
 51 static void level_mask_and_ack_msc_irq(struct irq_data *d)
 52 {
 53         mask_msc_irq(d);
 54         if (!cpu_has_veic)
 55                 MSCIC_WRITE(MSC01_IC_EOI, 0);
 56 }
 57 
 58 /*
 59  * Masks and ACKs an IRQ
 60  */
 61 static void edge_mask_and_ack_msc_irq(struct irq_data *d)
 62 {
 63         unsigned int irq = d->irq;
 64 
 65         mask_msc_irq(d);
 66         if (!cpu_has_veic)
 67                 MSCIC_WRITE(MSC01_IC_EOI, 0);
 68         else {
 69                 u32 r;
 70                 MSCIC_READ(MSC01_IC_SUP+irq*8, r);
 71                 MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
 72                 MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
 73         }
 74 }
 75 
 76 /*
 77  * Interrupt handler for interrupts coming from SOC-it.
 78  */
 79 void ll_msc_irq(void)
 80 {
 81         unsigned int irq;
 82 
 83         /* read the interrupt vector register */
 84         MSCIC_READ(MSC01_IC_VEC, irq);
 85         if (irq < 64)
 86                 do_IRQ(irq + irq_base);
 87         else {
 88                 /* Ignore spurious interrupt */
 89         }
 90 }
 91 
 92 static void msc_bind_eic_interrupt(int irq, int set)
 93 {
 94         MSCIC_WRITE(MSC01_IC_RAMW,
 95                     (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF));
 96 }
 97 
 98 static struct irq_chip msc_levelirq_type = {
 99         .name = "SOC-it-Level",
100         .irq_ack = level_mask_and_ack_msc_irq,
101         .irq_mask = mask_msc_irq,
102         .irq_mask_ack = level_mask_and_ack_msc_irq,
103         .irq_unmask = unmask_msc_irq,
104         .irq_eoi = unmask_msc_irq,
105 };
106 
107 static struct irq_chip msc_edgeirq_type = {
108         .name = "SOC-it-Edge",
109         .irq_ack = edge_mask_and_ack_msc_irq,
110         .irq_mask = mask_msc_irq,
111         .irq_mask_ack = edge_mask_and_ack_msc_irq,
112         .irq_unmask = unmask_msc_irq,
113         .irq_eoi = unmask_msc_irq,
114 };
115 
116 
117 void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
118 {
119         _icctrl_msc = (unsigned long) ioremap(icubase, 0x40000);
120 
121         /* Reset interrupt controller - initialises all registers to 0 */
122         MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
123 
124         board_bind_eic_interrupt = &msc_bind_eic_interrupt;
125 
126         for (; nirq > 0; nirq--, imp++) {
127                 int n = imp->im_irq;
128 
129                 switch (imp->im_type) {
130                 case MSC01_IRQ_EDGE:
131                         irq_set_chip_and_handler_name(irqbase + n,
132                                                       &msc_edgeirq_type,
133                                                       handle_edge_irq,
134                                                       "edge");
135                         if (cpu_has_veic)
136                                 MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
137                         else
138                                 MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
139                         break;
140                 case MSC01_IRQ_LEVEL:
141                         irq_set_chip_and_handler_name(irqbase + n,
142                                                       &msc_levelirq_type,
143                                                       handle_level_irq,
144                                                       "level");
145                         if (cpu_has_veic)
146                                 MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
147                         else
148                                 MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl);
149                 }
150         }
151 
152         irq_base = irqbase;
153 
154         MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT);     /* Enable interrupt generation */
155 
156 }
157 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php