diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/Kconfig | 3 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/Makefile | 5 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/maskreg.c | 99 |
3 files changed, 105 insertions, 2 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ddf2cc56868c..d90fb893bea9 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -313,6 +313,9 @@ config CPU_HAS_INTEVT | |||
313 | config CPU_HAS_PINT_IRQ | 313 | config CPU_HAS_PINT_IRQ |
314 | bool | 314 | bool |
315 | 315 | ||
316 | config CPU_HAS_MASKREG_IRQ | ||
317 | bool | ||
318 | |||
316 | config CPU_HAS_INTC2_IRQ | 319 | config CPU_HAS_INTC2_IRQ |
317 | bool | 320 | bool |
318 | 321 | ||
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile index e3cccea15e1d..1c034c283f59 100644 --- a/arch/sh/kernel/cpu/irq/Makefile +++ b/arch/sh/kernel/cpu/irq/Makefile | |||
@@ -3,5 +3,6 @@ | |||
3 | # | 3 | # |
4 | obj-y += ipr.o imask.o | 4 | obj-y += ipr.o imask.o |
5 | 5 | ||
6 | obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o | 6 | obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o |
7 | obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o | 7 | obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o |
8 | obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o | ||
diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c new file mode 100644 index 000000000000..1cc0de15e4a6 --- /dev/null +++ b/arch/sh/kernel/cpu/irq/maskreg.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * Interrupt handling for Simple external interrupt mask register | ||
3 | * | ||
4 | * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp> | ||
5 | * | ||
6 | * This is for the machine which have single 16 bit register | ||
7 | * for masking external IRQ individually. | ||
8 | * Each bit of the register is for masking each interrupt. | ||
9 | * | ||
10 | * This file may be copied or modified under the terms of the GNU | ||
11 | * General Public License. See linux/COPYING for more information. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/io.h> | ||
18 | |||
19 | /* address of external interrupt mask register */ | ||
20 | unsigned long irq_mask_register; | ||
21 | |||
22 | /* forward declaration */ | ||
23 | static unsigned int startup_maskreg_irq(unsigned int irq); | ||
24 | static void shutdown_maskreg_irq(unsigned int irq); | ||
25 | static void enable_maskreg_irq(unsigned int irq); | ||
26 | static void disable_maskreg_irq(unsigned int irq); | ||
27 | static void mask_and_ack_maskreg(unsigned int); | ||
28 | static void end_maskreg_irq(unsigned int irq); | ||
29 | |||
30 | /* hw_interrupt_type */ | ||
31 | static struct hw_interrupt_type maskreg_irq_type = { | ||
32 | .typename = "Mask Register", | ||
33 | .startup = startup_maskreg_irq, | ||
34 | .shutdown = shutdown_maskreg_irq, | ||
35 | .enable = enable_maskreg_irq, | ||
36 | .disable = disable_maskreg_irq, | ||
37 | .ack = mask_and_ack_maskreg, | ||
38 | .end = end_maskreg_irq | ||
39 | }; | ||
40 | |||
41 | /* actual implementatin */ | ||
42 | static unsigned int startup_maskreg_irq(unsigned int irq) | ||
43 | { | ||
44 | enable_maskreg_irq(irq); | ||
45 | return 0; /* never anything pending */ | ||
46 | } | ||
47 | |||
48 | static void shutdown_maskreg_irq(unsigned int irq) | ||
49 | { | ||
50 | disable_maskreg_irq(irq); | ||
51 | } | ||
52 | |||
53 | static void disable_maskreg_irq(unsigned int irq) | ||
54 | { | ||
55 | unsigned long flags; | ||
56 | unsigned short val, mask = 0x01 << irq; | ||
57 | |||
58 | BUG_ON(!irq_mask_register); | ||
59 | |||
60 | /* Set "irq"th bit */ | ||
61 | local_irq_save(flags); | ||
62 | val = ctrl_inw(irq_mask_register); | ||
63 | val |= mask; | ||
64 | ctrl_outw(val, irq_mask_register); | ||
65 | local_irq_restore(flags); | ||
66 | } | ||
67 | |||
68 | static void enable_maskreg_irq(unsigned int irq) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | unsigned short val, mask = ~(0x01 << irq); | ||
72 | |||
73 | BUG_ON(!irq_mask_register); | ||
74 | |||
75 | /* Clear "irq"th bit */ | ||
76 | local_irq_save(flags); | ||
77 | val = ctrl_inw(irq_mask_register); | ||
78 | val &= mask; | ||
79 | ctrl_outw(val, irq_mask_register); | ||
80 | local_irq_restore(flags); | ||
81 | } | ||
82 | |||
83 | static void mask_and_ack_maskreg(unsigned int irq) | ||
84 | { | ||
85 | disable_maskreg_irq(irq); | ||
86 | } | ||
87 | |||
88 | static void end_maskreg_irq(unsigned int irq) | ||
89 | { | ||
90 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
91 | enable_maskreg_irq(irq); | ||
92 | } | ||
93 | |||
94 | void make_maskreg_irq(unsigned int irq) | ||
95 | { | ||
96 | disable_irq_nosync(irq); | ||
97 | irq_desc[irq].handler = &maskreg_irq_type; | ||
98 | disable_maskreg_irq(irq); | ||
99 | } | ||