1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * arch/sh/kernel/cpu/irq/imask.c 4 * 5 * Copyright (C) 1999, 2000 Niibe Yutaka 6 * 7 * Simple interrupt handling using IMASK of SR register. 8 * 9 */ 10 /* NOTE: Will not work on level 15 */ 11 #include <linux/ptrace.h> 12 #include <linux/errno.h> 13 #include <linux/kernel_stat.h> 14 #include <linux/signal.h> 15 #include <linux/sched.h> 16 #include <linux/interrupt.h> 17 #include <linux/init.h> 18 #include <linux/bitops.h> 19 #include <linux/spinlock.h> 20 #include <linux/cache.h> 21 #include <linux/irq.h> 22 #include <linux/bitmap.h> 23 #include <asm/irq.h> 24 25 /* Bitmap of IRQ masked */ 26 #define IMASK_PRIORITY 15 27 28 static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY); 29 static int interrupt_priority; 30 31 static inline void set_interrupt_registers(int ip) 32 { 33 unsigned long __dummy; 34 35 asm volatile( 36 #ifdef CONFIG_CPU_HAS_SR_RB 37 "ldc %2, r6_bank\n\t" 38 #endif 39 "stc sr, %0\n\t" 40 "and #0xf0, %0\n\t" 41 "shlr2 %0\n\t" 42 "cmp/eq #0x3c, %0\n\t" 43 "bt/s 1f ! CLI-ed\n\t" 44 " stc sr, %0\n\t" 45 "and %1, %0\n\t" 46 "or %2, %0\n\t" 47 "ldc %0, sr\n" 48 "1:" 49 : "=&z" (__dummy) 50 : "r" (~0xf0), "r" (ip << 4) 51 : "t"); 52 } 53 54 static void mask_imask_irq(struct irq_data *data) 55 { 56 unsigned int irq = data->irq; 57 58 clear_bit(irq, imask_mask); 59 if (interrupt_priority < IMASK_PRIORITY - irq) 60 interrupt_priority = IMASK_PRIORITY - irq; 61 set_interrupt_registers(interrupt_priority); 62 } 63 64 static void unmask_imask_irq(struct irq_data *data) 65 { 66 unsigned int irq = data->irq; 67 68 set_bit(irq, imask_mask); 69 interrupt_priority = IMASK_PRIORITY - 70 find_first_zero_bit(imask_mask, IMASK_PRIORITY); 71 set_interrupt_registers(interrupt_priority); 72 } 73 74 static struct irq_chip imask_irq_chip = { 75 .name = "SR.IMASK", 76 .irq_mask = mask_imask_irq, 77 .irq_unmask = unmask_imask_irq, 78 .irq_mask_ack = mask_imask_irq, 79 }; 80 81 void make_imask_irq(unsigned int irq) 82 { 83 irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq, 84 "level"); 85 } 86