1/* 2 * arch/sh/kernel/cpu/irq/imask.c 3 * 4 * Copyright (C) 1999, 2000 Niibe Yutaka 5 * 6 * Simple interrupt handling using IMASK of SR register. 7 * 8 */ 9/* NOTE: Will not work on level 15 */ 10#include <linux/ptrace.h> 11#include <linux/errno.h> 12#include <linux/kernel_stat.h> 13#include <linux/signal.h> 14#include <linux/sched.h> 15#include <linux/interrupt.h> 16#include <linux/init.h> 17#include <linux/bitops.h> 18#include <linux/spinlock.h> 19#include <linux/cache.h> 20#include <linux/irq.h> 21#include <asm/system.h> 22#include <asm/irq.h> 23 24/* Bitmap of IRQ masked */ 25static unsigned long imask_mask = 0x7fff; 26static int interrupt_priority = 0; 27 28static void enable_imask_irq(unsigned int irq); 29static void disable_imask_irq(unsigned int irq); 30static void shutdown_imask_irq(unsigned int irq); 31static void mask_and_ack_imask(unsigned int); 32static void end_imask_irq(unsigned int irq); 33 34#define IMASK_PRIORITY 15 35 36static unsigned int startup_imask_irq(unsigned int irq) 37{ 38 /* Nothing to do */ 39 return 0; /* never anything pending */ 40} 41 42static struct hw_interrupt_type imask_irq_type = { 43 .typename = "SR.IMASK", 44 .startup = startup_imask_irq, 45 .shutdown = shutdown_imask_irq, 46 .enable = enable_imask_irq, 47 .disable = disable_imask_irq, 48 .ack = mask_and_ack_imask, 49 .end = end_imask_irq 50}; 51 52void static inline set_interrupt_registers(int ip) 53{ 54 unsigned long __dummy; 55 56 asm volatile( 57#ifdef CONFIG_CPU_HAS_SR_RB 58 "ldc %2, r6_bank\n\t" 59#endif 60 "stc sr, %0\n\t" 61 "and #0xf0, %0\n\t" 62 "shlr2 %0\n\t" 63 "cmp/eq #0x3c, %0\n\t" 64 "bt/s 1f ! CLI-ed\n\t" 65 " stc sr, %0\n\t" 66 "and %1, %0\n\t" 67 "or %2, %0\n\t" 68 "ldc %0, sr\n" 69 "1:" 70 : "=&z" (__dummy) 71 : "r" (~0xf0), "r" (ip << 4) 72 : "t"); 73} 74 75static void disable_imask_irq(unsigned int irq) 76{ 77 clear_bit(irq, &imask_mask); 78 if (interrupt_priority < IMASK_PRIORITY - irq) 79 interrupt_priority = IMASK_PRIORITY - irq; 80 81 set_interrupt_registers(interrupt_priority); 82} 83 84static void enable_imask_irq(unsigned int irq) 85{ 86 set_bit(irq, &imask_mask); 87 interrupt_priority = IMASK_PRIORITY - ffz(imask_mask); 88 89 set_interrupt_registers(interrupt_priority); 90} 91 92static void mask_and_ack_imask(unsigned int irq) 93{ 94 disable_imask_irq(irq); 95} 96 97static void end_imask_irq(unsigned int irq) 98{ 99 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 100 enable_imask_irq(irq); 101} 102 103static void shutdown_imask_irq(unsigned int irq) 104{ 105 /* Nothing to do */ 106} 107 108void make_imask_irq(unsigned int irq) 109{ 110 disable_irq_nosync(irq); 111 irq_desc[irq].chip = &imask_irq_type; 112 enable_irq(irq); 113} 114