1/* 2 * Interrupt handling for Simple external interrupt mask register 3 * 4 * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp> 5 * 6 * This is for the machine which have single 16 bit register 7 * for masking external IRQ individually. 8 * Each bit of the register is for masking each interrupt. 9 * 10 * This file may be copied or modified under the terms of the GNU 11 * General Public License. See linux/COPYING for more information. 12 */ 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/irq.h> 16#include <asm/system.h> 17#include <asm/io.h> 18 19/* address of external interrupt mask register */ 20unsigned long irq_mask_register; 21 22/* forward declaration */ 23static unsigned int startup_maskreg_irq(unsigned int irq); 24static void shutdown_maskreg_irq(unsigned int irq); 25static void enable_maskreg_irq(unsigned int irq); 26static void disable_maskreg_irq(unsigned int irq); 27static void mask_and_ack_maskreg(unsigned int); 28static void end_maskreg_irq(unsigned int irq); 29 30/* hw_interrupt_type */ 31static struct hw_interrupt_type maskreg_irq_type = { 32 .typename = "Mask Register", 33 .startup = startup_maskreg_irq, 34 .shutdown = shutdown_maskreg_irq, 35 .enable = enable_maskreg_irq, 36 .disable = disable_maskreg_irq, 37 .ack = mask_and_ack_maskreg, 38 .end = end_maskreg_irq 39}; 40 41/* actual implementation */ 42static unsigned int startup_maskreg_irq(unsigned int irq) 43{ 44 enable_maskreg_irq(irq); 45 return 0; /* never anything pending */ 46} 47 48static void shutdown_maskreg_irq(unsigned int irq) 49{ 50 disable_maskreg_irq(irq); 51} 52 53static void disable_maskreg_irq(unsigned int irq) 54{ 55 unsigned short val, mask = 0x01 << irq; 56 57 BUG_ON(!irq_mask_register); 58 59 /* Set "irq"th bit */ 60 val = ctrl_inw(irq_mask_register); 61 val |= mask; 62 ctrl_outw(val, irq_mask_register); 63} 64 65static void enable_maskreg_irq(unsigned int irq) 66{ 67 unsigned short val, mask = ~(0x01 << irq); 68 69 BUG_ON(!irq_mask_register); 70 71 /* Clear "irq"th bit */ 72 val = ctrl_inw(irq_mask_register); 73 val &= mask; 74 ctrl_outw(val, irq_mask_register); 75} 76 77static void mask_and_ack_maskreg(unsigned int irq) 78{ 79 disable_maskreg_irq(irq); 80} 81 82static void end_maskreg_irq(unsigned int irq) 83{ 84 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 85 enable_maskreg_irq(irq); 86} 87 88void make_maskreg_irq(unsigned int irq) 89{ 90 disable_irq_nosync(irq); 91 irq_desc[irq].handler = &maskreg_irq_type; 92 disable_maskreg_irq(irq); 93} 94