1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Interrupt handing routines for NEC VR4100 series. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 2005-2007 Yoichi Yuasa <yuasa@linux-mips.org> 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun #include <linux/export.h> 8*4882a593Smuzhiyun #include <linux/interrupt.h> 9*4882a593Smuzhiyun #include <linux/irq.h> 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #include <asm/irq_cpu.h> 12*4882a593Smuzhiyun #include <asm/vr41xx/irq.h> 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun typedef struct irq_cascade { 15*4882a593Smuzhiyun int (*get_irq)(unsigned int); 16*4882a593Smuzhiyun } irq_cascade_t; 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned; 19*4882a593Smuzhiyun cascade_irq(unsigned int irq,int (* get_irq)(unsigned int))20*4882a593Smuzhiyunint cascade_irq(unsigned int irq, int (*get_irq)(unsigned int)) 21*4882a593Smuzhiyun { 22*4882a593Smuzhiyun int retval = 0; 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun if (irq >= NR_IRQS) 25*4882a593Smuzhiyun return -EINVAL; 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun if (irq_cascade[irq].get_irq != NULL) 28*4882a593Smuzhiyun free_irq(irq, NULL); 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun irq_cascade[irq].get_irq = get_irq; 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun if (get_irq != NULL) { 33*4882a593Smuzhiyun retval = request_irq(irq, no_action, IRQF_NO_THREAD, 34*4882a593Smuzhiyun "cascade", NULL); 35*4882a593Smuzhiyun if (retval < 0) 36*4882a593Smuzhiyun irq_cascade[irq].get_irq = NULL; 37*4882a593Smuzhiyun } 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun return retval; 40*4882a593Smuzhiyun } 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(cascade_irq); 43*4882a593Smuzhiyun irq_dispatch(unsigned int irq)44*4882a593Smuzhiyunstatic void irq_dispatch(unsigned int irq) 45*4882a593Smuzhiyun { 46*4882a593Smuzhiyun irq_cascade_t *cascade; 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun if (irq >= NR_IRQS) { 49*4882a593Smuzhiyun atomic_inc(&irq_err_count); 50*4882a593Smuzhiyun return; 51*4882a593Smuzhiyun } 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun cascade = irq_cascade + irq; 54*4882a593Smuzhiyun if (cascade->get_irq != NULL) { 55*4882a593Smuzhiyun struct irq_desc *desc = irq_to_desc(irq); 56*4882a593Smuzhiyun struct irq_data *idata = irq_desc_get_irq_data(desc); 57*4882a593Smuzhiyun struct irq_chip *chip = irq_desc_get_chip(desc); 58*4882a593Smuzhiyun int ret; 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun if (chip->irq_mask_ack) 61*4882a593Smuzhiyun chip->irq_mask_ack(idata); 62*4882a593Smuzhiyun else { 63*4882a593Smuzhiyun chip->irq_mask(idata); 64*4882a593Smuzhiyun chip->irq_ack(idata); 65*4882a593Smuzhiyun } 66*4882a593Smuzhiyun ret = cascade->get_irq(irq); 67*4882a593Smuzhiyun irq = ret; 68*4882a593Smuzhiyun if (ret < 0) 69*4882a593Smuzhiyun atomic_inc(&irq_err_count); 70*4882a593Smuzhiyun else 71*4882a593Smuzhiyun irq_dispatch(irq); 72*4882a593Smuzhiyun if (!irqd_irq_disabled(idata) && chip->irq_unmask) 73*4882a593Smuzhiyun chip->irq_unmask(idata); 74*4882a593Smuzhiyun } else 75*4882a593Smuzhiyun do_IRQ(irq); 76*4882a593Smuzhiyun } 77*4882a593Smuzhiyun plat_irq_dispatch(void)78*4882a593Smuzhiyunasmlinkage void plat_irq_dispatch(void) 79*4882a593Smuzhiyun { 80*4882a593Smuzhiyun unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun if (pending & CAUSEF_IP7) 83*4882a593Smuzhiyun do_IRQ(TIMER_IRQ); 84*4882a593Smuzhiyun else if (pending & 0x7800) { 85*4882a593Smuzhiyun if (pending & CAUSEF_IP3) 86*4882a593Smuzhiyun irq_dispatch(INT1_IRQ); 87*4882a593Smuzhiyun else if (pending & CAUSEF_IP4) 88*4882a593Smuzhiyun irq_dispatch(INT2_IRQ); 89*4882a593Smuzhiyun else if (pending & CAUSEF_IP5) 90*4882a593Smuzhiyun irq_dispatch(INT3_IRQ); 91*4882a593Smuzhiyun else if (pending & CAUSEF_IP6) 92*4882a593Smuzhiyun irq_dispatch(INT4_IRQ); 93*4882a593Smuzhiyun } else if (pending & CAUSEF_IP2) 94*4882a593Smuzhiyun irq_dispatch(INT0_IRQ); 95*4882a593Smuzhiyun else if (pending & CAUSEF_IP0) 96*4882a593Smuzhiyun do_IRQ(MIPS_SOFTINT0_IRQ); 97*4882a593Smuzhiyun else if (pending & CAUSEF_IP1) 98*4882a593Smuzhiyun do_IRQ(MIPS_SOFTINT1_IRQ); 99*4882a593Smuzhiyun else 100*4882a593Smuzhiyun spurious_interrupt(); 101*4882a593Smuzhiyun } 102*4882a593Smuzhiyun arch_init_irq(void)103*4882a593Smuzhiyunvoid __init arch_init_irq(void) 104*4882a593Smuzhiyun { 105*4882a593Smuzhiyun mips_cpu_irq_init(); 106*4882a593Smuzhiyun } 107