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 <linux/bitmap.h> 22#include <asm/irq.h> 23 24/* Bitmap of IRQ masked */ 25#define IMASK_PRIORITY 15 26 27static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY); 28static int interrupt_priority; 29 30static inline void set_interrupt_registers(int ip) 31{ 32 unsigned long __dummy; 33 34 asm volatile( 35#ifdef CONFIG_CPU_HAS_SR_RB 36 "ldc %2, r6_bank\n\t" 37#endif 38 "stc sr, %0\n\t" 39 "and #0xf0, %0\n\t" 40 "shlr2 %0\n\t" 41 "cmp/eq #0x3c, %0\n\t" 42 "bt/s 1f ! CLI-ed\n\t" 43 " stc sr, %0\n\t" 44 "and %1, %0\n\t" 45 "or %2, %0\n\t" 46 "ldc %0, sr\n" 47 "1:" 48 : "=&z" (__dummy) 49 : "r" (~0xf0), "r" (ip << 4) 50 : "t"); 51} 52 53static void mask_imask_irq(struct irq_data *data) 54{ 55 unsigned int irq = data->irq; 56 57 clear_bit(irq, imask_mask); 58 if (interrupt_priority < IMASK_PRIORITY - irq) 59 interrupt_priority = IMASK_PRIORITY - irq; 60 set_interrupt_registers(interrupt_priority); 61} 62 63static void unmask_imask_irq(struct irq_data *data) 64{ 65 unsigned int irq = data->irq; 66 67 set_bit(irq, imask_mask); 68 interrupt_priority = IMASK_PRIORITY - 69 find_first_zero_bit(imask_mask, IMASK_PRIORITY); 70 set_interrupt_registers(interrupt_priority); 71} 72 73static struct irq_chip imask_irq_chip = { 74 .name = "SR.IMASK", 75 .irq_mask = mask_imask_irq, 76 .irq_unmask = unmask_imask_irq, 77 .irq_mask_ack = mask_imask_irq, 78}; 79 80void make_imask_irq(unsigned int irq) 81{ 82 irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq, 83 "level"); 84} 85