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