On Tue, 22 Jan 2002, Jun Sun wrote: > The best way is to provide hw_irq_controller structure for the extended CPU > IRQ feature. See arch/mips/kernel/irq_cpu.c file and its related config > option. Attached is such a file. Jason /* Copyright 2002 Jason Gunthorpe <jgg@debian.org> Modified from arch/mips/kernel/irq_cpu.S: Copyright 2001 MontaVista Software Inc. Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 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. This is an addendum to irq_cpu to support the additional RM7000 interrupt sources. irq_cpu handles the lower 8 interrupts, this does the remaining 6. */ #include <linux/irq.h> #include <linux/types.h> #include <linux/kernel.h> #include <asm/mipsregs.h> /* Move me to asm-mips/mipsregs.h */ #define __BUILD_SET_CP0_SET1(name,register) \ extern __inline__ unsigned int \ set_cp0_##name(unsigned int set) \ { \ unsigned int res; \ \ res = read_32bit_cp0_set1_register(register); \ res |= set; \ write_32bit_cp0_set1_register(register, res); \ \ return res; \ } \ \ extern __inline__ unsigned int \ clear_cp0_##name(unsigned int clear) \ { \ unsigned int res; \ \ res = read_32bit_cp0_set1_register(register); \ res &= ~clear; \ write_32bit_cp0_set1_register(register, res); \ \ return res; \ } \ \ extern __inline__ unsigned int \ change_cp0_##name(unsigned int change, unsigned int new) \ { \ unsigned int res; \ \ res = read_32bit_cp0_set1_register(register); \ res &= ~change; \ res |= (new & change); \ if(change) \ write_32bit_cp0_set1_register(register, res); \ \ return res; \ } __BUILD_SET_CP0_SET1(s1_intcontrol,CP0_S1_INTCONTROL) static int mips_rm7kcpu_irq_base; static void mips_rm7kcpu_irq_enable(unsigned int irq) { set_cp0_s1_intcontrol(1 << (irq - mips_rm7kcpu_irq_base + 8)); } static void mips_rm7kcpu_irq_disable(unsigned int irq) { clear_cp0_s1_intcontrol(1 << (irq - mips_rm7kcpu_irq_base + 8)); } static unsigned int mips_rm7kcpu_irq_startup(unsigned int irq) { mips_rm7kcpu_irq_enable(irq); return 0; } #define mips_rm7kcpu_irq_shutdown mips_rm7kcpu_irq_disable static void mips_rm7kcpu_irq_ack(unsigned int irq) { /* disable this interrupt - so that we safe proceed to the handler */ mips_rm7kcpu_irq_disable(irq); } static void mips_rm7kcpu_irq_end(unsigned int irq) { mips_rm7kcpu_irq_enable(irq); } static hw_irq_controller mips_rm7kcpu_irq_controller = { "RM7KCPU_irq", mips_rm7kcpu_irq_startup, mips_rm7kcpu_irq_shutdown, mips_rm7kcpu_irq_enable, mips_rm7kcpu_irq_disable, mips_rm7kcpu_irq_ack, mips_rm7kcpu_irq_end, NULL /* no affinity stuff for UP */ }; void mips_rm7kcpu_irq_init(u32 irq_base) { extern irq_desc_t irq_desc[]; u32 i; for (i= irq_base; i< irq_base+6; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].handler = &mips_rm7kcpu_irq_controller; } mips_rm7kcpu_irq_base = irq_base; // Enable TE, the dedicated timer IRQ. It shows up as irq_base + 4 set_cp0_s1_intcontrol(1 << 7); }