/* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * Copyright (C) 2001 Ralf Baechle * * This file define the irq handler for MIPS CPU interrupts. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ /* * Almost all MIPS CPUs define 8 interrupt sources. They are typically * level triggered (i.e., cannot be cleared from CPU; must be cleared from * device). The first two are software interrupts which we don't really * use or support. The last one is usually the CPU timer interrupt if * counter register is present or, for CPUs with an external FPU, by * convention it's the FPU exception interrupt. * * Don't even think about using this on SMP. You have been warned. * * This file exports one global function: * void mips_cpu_irq_init(int irq_base); */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CONFIG_AVM_SIMPLE_PROFILING) #include #include #endif /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ /*------------------------------------------------------------------------------------------*\ * Aufbau des Interrupt Systems * * CAUSEF_IP0 * CAUSEF_IP1 * CAUSEF_IP2 ur8 hw interrupt 0 * CAUSEF_IP3 ur8 hw interrupt 1 * CAUSEF_IP4 * CAUSEF_IP5 * CAUSEF_IP6 * CAUSEF_IP7 timer interrupt * * Setup the IRQ description array. These will be mapped * as flat interrupts numbers. The mapping is as follows * * 0 - 7 MIPS CPU Exceptions (HW/SW) * 8 - 47 Primary Interrupts (Avalanche) * 48- 79 Secondary Interrupts (Avalanche) * 80- 111 Low Vlynq Interrupts (Vlynq) * 112- 143 PCI Interrupts * \*------------------------------------------------------------------------------------------*/ //#define DEBUG_UR8_IRQ #ifndef DEBUG_UR8_IRQ #define DEBUG_PRINTK(...) #else #define DEBUG_PRINTK(...) printk(__VA_ARGS__) #endif //#define FIND_FUNNY_IRQS /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int irq_prio[41], irq_prio_pointer = 0; /*------------------------------------------------------------------------------------------*\ * Diese Funktionen muesen geschuetzt aufgerufen werden ! \*------------------------------------------------------------------------------------------*/ static inline void priority_push(unsigned int prio) { irq_prio[irq_prio_pointer++] = prio; } /*------------------------------------------------------------------------------------------*\ * Diese Funktionen muesen geschuetzt aufgerufen werden ! \*------------------------------------------------------------------------------------------*/ static inline unsigned int priority_pop(void) { unsigned int prio; if(irq_prio_pointer == 0) prio = 40; else prio = irq_prio[--irq_prio_pointer]; return prio; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static int mips_cpu_irq_base; static int mips_cpu_double_clear_mask[2]; static spinlock_t ur8_irq_lock = SPIN_LOCK_UNLOCKED; static struct { unsigned char used; unsigned char irq; } ur8_pacing_list[4]; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static inline void unmask_mips_irq(unsigned int irq) { irq -= mips_cpu_irq_base; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if(irq < MIPS_EXCEPTION_OFFSET) { DEBUG_PRINTK("[unmask_mips_irq] MIPS irq=%u\n", irq); clear_c0_cause(0x100 << irq); set_c0_status(0x100 << irq); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_PRIMARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; DEBUG_PRINTK("[unmask_mips_irq] PRIMARY irq=%u real=%u\n", irq, irq - (MIPS_EXCEPTION_OFFSET - 1)); irq -= MIPS_EXCEPTION_OFFSET; IRQ->enable_set_reg[irq / 32] = (1 << (irq % 32)); DEBUG_PRINTK("[unmask_mips_irq] set IRQ->enable_set_reg[%u] = (1 << (%u));\n", irq / 32, irq % 32); DEBUG_PRINTK("[unmask_mips_irq] channel[%u] = %u\n", irq, IRQ->channel_number_reg[irq]); DEBUG_PRINTK("[unmask_mips_irq] raw status[%u] = 0x%x\n", irq / 32, IRQ->status_clear_reg[irq / 32]); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_SECONDARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; DEBUG_PRINTK("[unmask_mips_irq] SECONDARY irq=%u real=%u\n", irq, irq - UR8_INT_END_PRIMARY); irq -= UR8_INT_END_PRIMARY; IRQ->exception_enable_set_reg = (1 << irq); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ #if defined(CONFIG_MIPS_VIRTUAL_IRQ) } else if(irq < UR8_INT_END_VIRTUAL) { irq -= UR8_INT_END_SECONDARY; vlynq_irq_enable(0, irq); #endif /*--- #if defined(CONFIG_MIPS_VIRTUAL_IRQ) ---*/ #if defined(CONFIG_PCI) && (CONFIG_AVM_PCI_DEVICE_COUNT > 0) } else if(irq < UR8_INT_PCI_END) { pci_irq_enable(irq - UR8_INT_PCI_BEGIN); #endif /*--- #if defined(CONFIG_PCI) ---*/ } { #ifdef DEBUG_UR8_IRQ struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; #endif DEBUG_PRINTK("[unmask_mips_irq]\n" "\tc0: mask 0x%x\n" "\tIRQ->enable_set_reg[0] = 0x%x\n" "\tIRQ->enable_set_reg[1] = 0x%x\n" "\tIRQ->exception_enable_set_reg = 0x%x\n", (read_c0_status() >> 10) & ((1 << 6) - 1), IRQ->enable_set_reg[0], IRQ->enable_set_reg[1], IRQ->exception_enable_set_reg); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static inline void mask_mips_irq(unsigned int irq) { DEBUG_PRINTK("[mask_mips_irq] irq=%u\n", irq); irq -= mips_cpu_irq_base; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if(irq < MIPS_EXCEPTION_OFFSET) { clear_c0_status(0x100 << irq); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_PRIMARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; irq -= MIPS_EXCEPTION_OFFSET; IRQ->enable_clear_reg[irq / 32] = (1 << (irq % 32)); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_SECONDARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; irq -= UR8_INT_END_PRIMARY; IRQ->exception_enable_clear_reg = (1 << irq); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ #if defined(CONFIG_MIPS_VIRTUAL_IRQ) } else if(irq < UR8_INT_END_VIRTUAL) { irq -= UR8_INT_END_SECONDARY; vlynq_irq_disable(0, irq); #endif /*--- #if defined(CONFIG_MIPS_VIRTUAL_IRQ) ---*/ #if defined(CONFIG_PCI) && (CONFIG_AVM_PCI_DEVICE_COUNT > 0) } else if(irq < UR8_INT_PCI_END) { pci_irq_disable(irq - UR8_INT_PCI_BEGIN); #endif /*--- #if defined(CONFIG_PCI) ---*/ } { #ifdef DEBUG_UR8_IRQ struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; #endif DEBUG_PRINTK("[mask_mips_irq]\n" "\tc0: mask 0x%x\n" "\tIRQ->enable_set_reg[0] = 0x%x\n" "\tIRQ->enable_set_reg[1] = 0x%x\n" "\tIRQ->exception_enable_set_reg = 0x%x\n", (read_c0_status() >> 10) & ((1 << 6) - 1), IRQ->enable_set_reg[0], IRQ->enable_set_reg[1], IRQ->exception_enable_set_reg); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static inline void mips_cpu_irq_enable(unsigned int irq) { unsigned long flags; DEBUG_PRINTK("[mips_cpu_irq_enable] irq=%u\n", irq); local_irq_save(flags); unmask_mips_irq(irq); local_irq_restore(flags); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void mips_cpu_irq_disable(unsigned int irq) { unsigned long flags; DEBUG_PRINTK("[mips_cpu_irq_disable] irq=%u\n", irq); local_irq_save(flags); mask_mips_irq(irq); local_irq_restore(flags); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static unsigned int mips_cpu_irq_startup(unsigned int irq) { DEBUG_PRINTK("[mips_cpu_irq_startup] irq=%u\n", irq); mips_cpu_irq_enable(irq); return 0; } /*------------------------------------------------------------------------------------------*\ * Initialize the IRQ pacing administration * * * * Argument: prescale: Prescale-Value to define the intervals to count IRQs * \*------------------------------------------------------------------------------------------*/ void ur8int_ctrl_irq_pacing_setup(unsigned int prescale) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; unsigned int i; for(i = 0; i < 4; i++) { ur8_pacing_list[i].used = 0; ur8_pacing_list[i].irq = 0; } IRQ->pacing_prescale_reg.Bits.IPACEP = prescale; } /*------------------------------------------------------------------------------------------*\ * Register the usage of pacing for an IRQ * * * * Argument: irq - The IRQ that should be paced * * * * Return: >=0: Handle, with which to call the pacing related functions * * -1 : IRQ is already registered * * -2 : No more pacing registers available * * -3 : Thengiven IRQ can not be set and is therefor rejected * \*------------------------------------------------------------------------------------------*/ int ur8int_ctrl_irq_pacing_register(unsigned int irq) { unsigned int i, handle = 99; int flags; if((irq < MIPS_EXCEPTION_OFFSET) || (irq >= UR8_INT_END_PRIMARY)) { printk(KERN_WARNING "[ur8int_ctrl_irq_pacing_register] This IRQ (%u) can not be set!\n", irq); return -3; } spin_lock_irqsave(&ur8_irq_lock, flags); /* First check, whether the IRQ got registered already */ for(i = 0; i < 4; i++) { if(ur8_pacing_list[i].used && (ur8_pacing_list[i].irq == irq)) { spin_unlock_irqrestore(&ur8_irq_lock, flags); printk(KERN_WARNING "[ur8int_ctrl_irq_pacing_register] IRQ %u already registered!\n", irq); return -1; } if(!ur8_pacing_list[i].used) handle = i; } if(handle == 99) { spin_unlock_irqrestore(&ur8_irq_lock, flags); printk(KERN_WARNING "[ur8int_ctrl_irq_pacing_register] All IRQ pacing registers already used!\n"); return -2; } ur8_pacing_list[handle].used = 1; ur8_pacing_list[handle].irq = irq; /* Configure pacing register */ ur8int_ctrl_irq_pacing_set(handle, 0); spin_unlock_irqrestore(&ur8_irq_lock, flags); return handle; } /*------------------------------------------------------------------------------------------*\ * Unregister the IRQ pacing for a given handle * * * * Argument: handle - Handle returned at register time * \*------------------------------------------------------------------------------------------*/ void ur8int_ctrl_irq_pacing_unregister(int handle) { if((handle < 0) || (handle > 3) || !ur8_pacing_list[handle].used) { printk(KERN_ERR "[ur8int_ctrl_irq_pacing_unregister] Handle %u is invalid!\n", handle); return; } /* Stop interrupt pacing for the given handle */ ur8int_ctrl_irq_pacing_set(handle, 0); ur8_pacing_list[handle].used = 0; } /*------------------------------------------------------------------------------------------*\ * Set the needed IRQ pacing * * * * Arguments: handle - Handle returned at registration time * * max - Summarize at most 'max' interrupts per time slot * * * * Return: 0 on success, -1 on invalid handle * \*------------------------------------------------------------------------------------------*/ int ur8int_ctrl_irq_pacing_set(int handle, unsigned int max) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; unsigned int irq; if((handle < 0) || (handle > 3) || !ur8_pacing_list[handle].used) { printk(KERN_ERR "[ur8int_ctrl_irq_pacing_set] Handle %u is invalid!\n", handle); return -1; } irq = ur8_pacing_list[handle].irq - MIPS_EXCEPTION_OFFSET; max &= (1 << 6) - 1; if(max == 1) max = 0; switch(handle) { case 0: if(max == 0) { IRQ->pacing_max_reg.Bits.IPACEN0 = 0; return 0; } IRQ->pacing_map_reg.Bits.IPACEMAP0 = irq; IRQ->pacing_max_reg.Bits.IPACEMAX0 = max; IRQ->pacing_max_reg.Bits.IPACEN0 = 1; break; case 1: if(max == 0) { IRQ->pacing_max_reg.Bits.IPACEN1 = 0; return 0; } IRQ->pacing_map_reg.Bits.IPACEMAP1 = irq; IRQ->pacing_max_reg.Bits.IPACEMAX1 = max; IRQ->pacing_max_reg.Bits.IPACEN1 = 1; break; case 2: if(max == 0) { IRQ->pacing_max_reg.Bits.IPACEN2 = 0; return 0; } IRQ->pacing_map_reg.Bits.IPACEMAP2 = irq; IRQ->pacing_max_reg.Bits.IPACEMAX2 = max; IRQ->pacing_max_reg.Bits.IPACEN2 = 1; break; case 3: if(max == 0) { IRQ->pacing_max_reg.Bits.IPACEN3 = 0; return 0; } IRQ->pacing_map_reg.Bits.IPACEMAP3 = irq; IRQ->pacing_max_reg.Bits.IPACEMAX3 = max; IRQ->pacing_max_reg.Bits.IPACEN3 = 1; break; } return 0; } EXPORT_SYMBOL(ur8int_ctrl_irq_pacing_register); EXPORT_SYMBOL(ur8int_ctrl_irq_pacing_unregister); EXPORT_SYMBOL(ur8int_ctrl_irq_pacing_set); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int ur8int_set_type(unsigned int irq, enum _ur8_interrupt_type_trigger level, enum _ur8_interrupt_type_polarity polarity) { /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if(irq < MIPS_EXCEPTION_OFFSET) { return 1; /*--- kein setzen möglich ---*/ /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_PRIMARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; irq -= MIPS_EXCEPTION_OFFSET; if(polarity == ur8_interrupt_type_active_low) { IRQ->polarity_reg[irq / 32] |= (1 << (irq % 32)); } else { IRQ->polarity_reg[irq / 32] &= ~(1 << (irq % 32)); } if(level == ur8_interrupt_type_level) { IRQ->type_reg[irq / 32] |= (1 << (irq % 32)); /*--- level trigger ---*/ } else { IRQ->type_reg[irq / 32] &= ~(1 << (irq % 32)); /*--- edge trigger ----*/ } if(level == ur8_interrupt_type_level) { mips_cpu_double_clear_mask[irq / 32] = (1 << (irq % 32)); } /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_SECONDARY) { return 1; /*--- kein setzen möglich ---*/ /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ #if defined(CONFIG_MIPS_VIRTUAL_IRQ) } else if(irq < UR8_INT_END_VIRTUAL) { irq -= UR8_INT_END_SECONDARY; vlynq_set_irq_type(irq, level, polarity); #endif /*--- #if defined(CONFIG_MIPS_VIRTUAL_IRQ) ---*/ } return 0; } EXPORT_SYMBOL(ur8int_set_type); #define mips_cpu_irq_shutdown mips_cpu_irq_disable /*------------------------------------------------------------------------------------------*\ * While we ack the interrupt interrupts are disabled and thus we don't need * to deal with concurrency issues. Same for mips_cpu_irq_end. \*------------------------------------------------------------------------------------------*/ static void mips_cpu_irq_ack(unsigned int irq) { DEBUG_PRINTK("[mips_cpu_irq_ack] irq=%u\n", irq); #if defined(CONFIG_AVM_SIMPLE_PROFILING) struct irq_desc *desc = irq_desc + irq; avm_simple_profiling_log(avm_profile_data_type_hw_irq_begin, (unsigned int)desc, irq); #endif /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ #if defined(FIND_FUNNY_IRQS) if(irq < MIPS_EXCEPTION_OFFSET) { } else if(irq < UR8_INT_END_PRIMARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; unsigned int _irq = irq - (MIPS_EXCEPTION_OFFSET); if(!(IRQ->status_set_reg[_irq / 32] & (1 << (_irq % 32)))) { printk("[ack] irq %u %u set but not present\n", _irq, irq); } } #endif /*--- #if defined(FIND_FUNNY_IRQS) ---*/ mask_mips_irq(irq); irq -= mips_cpu_irq_base; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ if(irq < MIPS_EXCEPTION_OFFSET) { /* Only necessary for soft interrupts */ clear_c0_cause(0x100 << irq); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_PRIMARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; irq -= MIPS_EXCEPTION_OFFSET; #if defined(FIND_FUNNY_IRQS) if(!(IRQ->status_clear_reg[irq / 32] & (1 << (irq % 32)))) { printk("[ack] irq %u set but not present in raw\n", irq); } #endif /*--- #if defined(FIND_FUNNY_IRQS) ---*/ IRQ->status_clear_reg[irq / 32] = (1 << (irq % 32)); #if defined(FIND_FUNNY_IRQS) if(IRQ->status_set_reg[irq / 32] & (1 << (irq % 32))) { printk("[ack] irq %u cleared but still present\n", irq); } if(irq == 2) { printk("[ack] irq %u raw status %x status %x\n", irq, IRQ->status_clear_reg[irq / 32], IRQ->status_set_reg[irq / 32] ); } #endif /*--- #if defined(FIND_FUNNY_IRQS) ---*/ #if 1 { unsigned long flags; local_irq_save(flags); priority_push(IRQ->priority_mask_index_reg & ((1 << 6) - 1)); IRQ->priority_mask_index_reg = irq - 1; local_irq_restore(flags); } #endif clear_c0_cause(0x100 << 2); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ } else if(irq < UR8_INT_END_SECONDARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; irq -= UR8_INT_START_SECONDARY; IRQ->exception_clear_status_reg = 1 << irq; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ #if defined(CONFIG_VLYNQ_SUPPORT) } else if(irq < UR8_INT_END_VIRTUAL) { irq -= UR8_INT_END_SECONDARY; vlynq_irq_ack(0, irq); #endif /*--- #if defined(CONFIG_VLYNQ_SUPPORT) ---*/ #if defined(CONFIG_PCI) && (CONFIG_AVM_PCI_DEVICE_COUNT > 0) /* no pci ack needed, mips_cpu_irq_end_dummy is called anyway } else if(irq < UR8_INT_PCI_END) { pci_irq_ack(irq - UR8_INT_PCI_BEGIN); */ #endif /*--- #if defined(CONFIG_PCI) ---*/ } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void mips_cpu_irq_end_dummy(unsigned int irq) { /* needed for pci optimization */ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void mips_cpu_irq_end(unsigned int irq) { DEBUG_PRINTK("[mips_cpu_irq_end] irq=%u\n", irq); #if defined(CONFIG_AVM_SIMPLE_PROFILING) struct irq_desc *desc = irq_desc + irq; avm_simple_profiling_log(avm_profile_data_type_hw_irq_end, (unsigned int)desc, irq); #endif /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ irq -= mips_cpu_irq_base; if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { if(irq < MIPS_EXCEPTION_OFFSET) { } else if(irq < UR8_INT_END_PRIMARY) { struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; unsigned int _irq = irq - (MIPS_EXCEPTION_OFFSET); #if defined(FIND_FUNNY_IRQS) if(irq != 15) { if(IRQ->status_clear_reg[_irq / 32] & (1 << (_irq % 32))) { printk("[end] new raw interrupt %u %u present ? \n", _irq, irq); } } if(IRQ->status_set_reg[_irq / 32] & (1 << (_irq % 32))) { printk("[end] new real interrupt %u %u present ? \n", _irq, irq); } #endif /*--- #if defined(FIND_FUNNY_IRQS) ---*/ if(mips_cpu_double_clear_mask[_irq / 32] & (1 << (_irq % 32))) { IRQ->status_clear_reg[_irq / 32] = (1 << (_irq % 32)); } #if 1 { unsigned long flags; local_irq_save(flags); IRQ->priority_mask_index_reg = priority_pop(); local_irq_restore(flags); } #endif #if defined(CONFIG_VLYNQ_SUPPORT) } else if(irq < UR8_INT_END_VIRTUAL) { #endif #if defined(CONFIG_PCI) && (CONFIG_AVM_PCI_DEVICE_COUNT > 0) /* no pci_irq_end needed } else if(irq < UR8_INT_PCI_END) { pci_irq_end(irq - UR8_INT_PCI_BEGIN); */ #endif } unmask_mips_irq(irq); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static struct irq_chip mips_cpu_irq_controller_system = { name: "UR8 System", startup: mips_cpu_irq_startup, shutdown: mips_cpu_irq_shutdown, enable: mips_cpu_irq_enable, disable: mips_cpu_irq_disable, ack: mips_cpu_irq_ack, mask: NULL, mask_ack: NULL, unmask: NULL, eoi: NULL, end: mips_cpu_irq_end, set_affinity: NULL,/* no affinity stuff for UP */ retrigger: NULL, set_type: NULL, set_wake: NULL, typename: NULL }; static struct irq_chip mips_cpu_irq_controller_primary = { name: "UR8 primary", startup: mips_cpu_irq_startup, shutdown: mips_cpu_irq_shutdown, enable: mips_cpu_irq_enable, disable: mips_cpu_irq_disable, ack: mips_cpu_irq_ack, mask: NULL, mask_ack: NULL, unmask: NULL, eoi: NULL, end: mips_cpu_irq_end, set_affinity: NULL, /* no affinity stuff for UP */ retrigger: NULL, set_type: NULL, set_wake: NULL, typename: NULL }; static struct irq_chip mips_cpu_irq_controller_secondary = { name: "UR8 secondary", startup: mips_cpu_irq_startup, shutdown: mips_cpu_irq_shutdown, enable: mips_cpu_irq_enable, disable: mips_cpu_irq_disable, ack: mips_cpu_irq_ack, mask: NULL, mask_ack: NULL, unmask: NULL, eoi: NULL, end: mips_cpu_irq_end, set_affinity: NULL, /* no affinity stuff for UP */ retrigger: NULL, set_type: NULL, set_wake: NULL, typename: NULL }; #if defined(CONFIG_VLYNQ_SUPPORT) static hw_irq_controller mips_cpu_irq_controller_vlynq = { name: "UR8 vlynq", startup: mips_cpu_irq_startup, shutdown: mips_cpu_irq_shutdown, enable: mips_cpu_irq_enable, disable: mips_cpu_irq_disable, ack: mips_cpu_irq_ack, end: mips_cpu_irq_end }; #endif /*--- #if defined(CONFIG_VLYNQ_SUPPORT) ---*/ #if defined(CONFIG_PCI) static hw_irq_controller mips_cpu_irq_controller_pci = { name: "UR8 pci", startup: mips_cpu_irq_startup, shutdown: mips_cpu_irq_shutdown, enable: mips_cpu_irq_enable, disable: mips_cpu_irq_disable, #if defined(CONFIG_AVM_SIMPLE_PROFILING) ack: mips_cpu_irq_ack, end: mips_cpu_irq_end #else ack: NULL, end: mips_cpu_irq_end_dummy /* NULL pointer would crash */ #endif }; #endif /*--- #if defined(CONFIG_PCI) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void __init mips_cpu_irq_init(int irq_base) { int i; #ifdef DEBUG_UR8_IRQ struct _irq_hw *IRQ = (struct _irq_hw *)UR8_IRQ_CTRL_BASE; #endif mips_cpu_double_clear_mask[0] = 0; mips_cpu_double_clear_mask[1] = 0; for (i = irq_base; i < 41 ; i++) { irq_prio[i] = 40; } DEBUG_PRINTK("[mips_cpu_irq_init]\n"); for (i = irq_base; i < irq_base + 8 ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].chip = &mips_cpu_irq_controller_system; } for ( ; i < irq_base + UR8_INT_END_PRIMARY ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].chip = &mips_cpu_irq_controller_primary; } for ( ; i < irq_base + UR8_INT_END_SECONDARY ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].chip = &mips_cpu_irq_controller_secondary; } #if defined(CONFIG_VLYNQ_SUPPORT) for ( ; i < irq_base + UR8_INT_END_VIRTUAL ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].chip = &mips_cpu_irq_controller_vlynq; } #endif /*--- #if defined(CONFIG_VLYNQ_SUPPORT) ---*/ #if defined(CONFIG_PCI) for ( ; i < irq_base + UR8_INT_PCI_END ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].chip = &mips_cpu_irq_controller_pci; } #endif /*--- #if defined(CONFIG_PCI) ---*/ mips_cpu_irq_base = irq_base; ur8int_ctrl_irq_pacing_setup((4 * ur8_get_clock(avm_clock_id_vbus)) / 1000000); }