1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2bf3a00f8SPaul Mundt /*
3bf3a00f8SPaul Mundt * arch/sh/kernel/cpu/irq/imask.c
4bf3a00f8SPaul Mundt *
5bf3a00f8SPaul Mundt * Copyright (C) 1999, 2000 Niibe Yutaka
6bf3a00f8SPaul Mundt *
7bf3a00f8SPaul Mundt * Simple interrupt handling using IMASK of SR register.
8bf3a00f8SPaul Mundt *
9bf3a00f8SPaul Mundt */
10bf3a00f8SPaul Mundt /* NOTE: Will not work on level 15 */
11bf3a00f8SPaul Mundt #include <linux/ptrace.h>
12bf3a00f8SPaul Mundt #include <linux/errno.h>
13bf3a00f8SPaul Mundt #include <linux/kernel_stat.h>
14bf3a00f8SPaul Mundt #include <linux/signal.h>
15bf3a00f8SPaul Mundt #include <linux/sched.h>
16bf3a00f8SPaul Mundt #include <linux/interrupt.h>
17bf3a00f8SPaul Mundt #include <linux/init.h>
18bf3a00f8SPaul Mundt #include <linux/bitops.h>
19bf3a00f8SPaul Mundt #include <linux/spinlock.h>
20bf3a00f8SPaul Mundt #include <linux/cache.h>
21bf3a00f8SPaul Mundt #include <linux/irq.h>
2255620c86SPaul Mundt #include <linux/bitmap.h>
23bf3a00f8SPaul Mundt #include <asm/irq.h>
24bf3a00f8SPaul Mundt
25bf3a00f8SPaul Mundt /* Bitmap of IRQ masked */
26bf3a00f8SPaul Mundt #define IMASK_PRIORITY 15
27bf3a00f8SPaul Mundt
2855620c86SPaul Mundt static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY);
2955620c86SPaul Mundt static int interrupt_priority;
30bf3a00f8SPaul Mundt
set_interrupt_registers(int ip)3155620c86SPaul Mundt static inline void set_interrupt_registers(int ip)
32bf3a00f8SPaul Mundt {
33bf3a00f8SPaul Mundt unsigned long __dummy;
34bf3a00f8SPaul Mundt
359d4436a6SYoshinori Sato asm volatile(
369d4436a6SYoshinori Sato #ifdef CONFIG_CPU_HAS_SR_RB
379d4436a6SYoshinori Sato "ldc %2, r6_bank\n\t"
389d4436a6SYoshinori Sato #endif
39bf3a00f8SPaul Mundt "stc sr, %0\n\t"
40bf3a00f8SPaul Mundt "and #0xf0, %0\n\t"
41bf3a00f8SPaul Mundt "shlr2 %0\n\t"
42bf3a00f8SPaul Mundt "cmp/eq #0x3c, %0\n\t"
43bf3a00f8SPaul Mundt "bt/s 1f ! CLI-ed\n\t"
44bf3a00f8SPaul Mundt " stc sr, %0\n\t"
45bf3a00f8SPaul Mundt "and %1, %0\n\t"
46bf3a00f8SPaul Mundt "or %2, %0\n\t"
47bf3a00f8SPaul Mundt "ldc %0, sr\n"
48bf3a00f8SPaul Mundt "1:"
49bf3a00f8SPaul Mundt : "=&z" (__dummy)
50bf3a00f8SPaul Mundt : "r" (~0xf0), "r" (ip << 4)
51bf3a00f8SPaul Mundt : "t");
52bf3a00f8SPaul Mundt }
53bf3a00f8SPaul Mundt
mask_imask_irq(struct irq_data * data)54949bf166SPaul Mundt static void mask_imask_irq(struct irq_data *data)
55bf3a00f8SPaul Mundt {
56949bf166SPaul Mundt unsigned int irq = data->irq;
57949bf166SPaul Mundt
583709ab8dSPaul Mundt clear_bit(irq, imask_mask);
59bf3a00f8SPaul Mundt if (interrupt_priority < IMASK_PRIORITY - irq)
60bf3a00f8SPaul Mundt interrupt_priority = IMASK_PRIORITY - irq;
61bf3a00f8SPaul Mundt set_interrupt_registers(interrupt_priority);
62bf3a00f8SPaul Mundt }
63bf3a00f8SPaul Mundt
unmask_imask_irq(struct irq_data * data)64949bf166SPaul Mundt static void unmask_imask_irq(struct irq_data *data)
65bf3a00f8SPaul Mundt {
66949bf166SPaul Mundt unsigned int irq = data->irq;
67949bf166SPaul Mundt
683709ab8dSPaul Mundt set_bit(irq, imask_mask);
6955620c86SPaul Mundt interrupt_priority = IMASK_PRIORITY -
7055620c86SPaul Mundt find_first_zero_bit(imask_mask, IMASK_PRIORITY);
71bf3a00f8SPaul Mundt set_interrupt_registers(interrupt_priority);
72bf3a00f8SPaul Mundt }
73bf3a00f8SPaul Mundt
7455620c86SPaul Mundt static struct irq_chip imask_irq_chip = {
75648f1534SThomas Gleixner .name = "SR.IMASK",
76949bf166SPaul Mundt .irq_mask = mask_imask_irq,
77949bf166SPaul Mundt .irq_unmask = unmask_imask_irq,
78949bf166SPaul Mundt .irq_mask_ack = mask_imask_irq,
7955620c86SPaul Mundt };
80bf3a00f8SPaul Mundt
make_imask_irq(unsigned int irq)81bf3a00f8SPaul Mundt void make_imask_irq(unsigned int irq)
82bf3a00f8SPaul Mundt {
83fcb8918fSThomas Gleixner irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq,
84fcb8918fSThomas Gleixner "level");
85bf3a00f8SPaul Mundt }
86