diff options
Diffstat (limited to 'arch/sh/kernel/cpu/irq')
-rw-r--r-- | arch/sh/kernel/cpu/irq/Makefile | 5 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/intc2.c | 6 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/ipr.c | 14 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/maskreg.c | 93 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/pint.c | 8 |
5 files changed, 108 insertions, 18 deletions
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/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index 30064bf6e154..e30e4b7aa70e 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c | |||
@@ -241,9 +241,9 @@ static struct intc2_init { | |||
241 | /* 110-111 reserved/unused */ | 241 | /* 110-111 reserved/unused */ |
242 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) | 242 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) |
243 | { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2}, | 243 | { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2}, |
244 | #ifdef CONFIG_SH_RTC | 244 | { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, |
245 | { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, | 245 | { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, |
246 | #endif | 246 | { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, |
247 | { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | 247 | { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, |
248 | { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | 248 | { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, |
249 | { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | 249 | { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, |
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 0f545941fb4f..f785822cd5de 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c | |||
@@ -57,31 +57,27 @@ static struct hw_interrupt_type ipr_irq_type = { | |||
57 | 57 | ||
58 | static void disable_ipr_irq(unsigned int irq) | 58 | static void disable_ipr_irq(unsigned int irq) |
59 | { | 59 | { |
60 | unsigned long val, flags; | 60 | unsigned long val; |
61 | unsigned int addr = ipr_data[irq].addr; | 61 | unsigned int addr = ipr_data[irq].addr; |
62 | unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift); | 62 | unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift); |
63 | 63 | ||
64 | /* Set the priority in IPR to 0 */ | 64 | /* Set the priority in IPR to 0 */ |
65 | local_irq_save(flags); | ||
66 | val = ctrl_inw(addr); | 65 | val = ctrl_inw(addr); |
67 | val &= mask; | 66 | val &= mask; |
68 | ctrl_outw(val, addr); | 67 | ctrl_outw(val, addr); |
69 | local_irq_restore(flags); | ||
70 | } | 68 | } |
71 | 69 | ||
72 | static void enable_ipr_irq(unsigned int irq) | 70 | static void enable_ipr_irq(unsigned int irq) |
73 | { | 71 | { |
74 | unsigned long val, flags; | 72 | unsigned long val; |
75 | unsigned int addr = ipr_data[irq].addr; | 73 | unsigned int addr = ipr_data[irq].addr; |
76 | int priority = ipr_data[irq].priority; | 74 | int priority = ipr_data[irq].priority; |
77 | unsigned short value = (priority << ipr_data[irq].shift); | 75 | unsigned short value = (priority << ipr_data[irq].shift); |
78 | 76 | ||
79 | /* Set priority in IPR back to original value */ | 77 | /* Set priority in IPR back to original value */ |
80 | local_irq_save(flags); | ||
81 | val = ctrl_inw(addr); | 78 | val = ctrl_inw(addr); |
82 | val |= value; | 79 | val |= value; |
83 | ctrl_outw(val, addr); | 80 | ctrl_outw(val, addr); |
84 | local_irq_restore(flags); | ||
85 | } | 81 | } |
86 | 82 | ||
87 | static void mask_and_ack_ipr(unsigned int irq) | 83 | static void mask_and_ack_ipr(unsigned int irq) |
@@ -89,6 +85,7 @@ static void mask_and_ack_ipr(unsigned int irq) | |||
89 | disable_ipr_irq(irq); | 85 | disable_ipr_irq(irq); |
90 | 86 | ||
91 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ | 87 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ |
88 | defined(CONFIG_CPU_SUBTYPE_SH7706) || \ | ||
92 | defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) | 89 | defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) |
93 | /* This is needed when we use edge triggered setting */ | 90 | /* This is needed when we use edge triggered setting */ |
94 | /* XXX: Is it really needed? */ | 91 | /* XXX: Is it really needed? */ |
@@ -123,7 +120,7 @@ void __init init_IRQ(void) | |||
123 | #ifndef CONFIG_CPU_SUBTYPE_SH7780 | 120 | #ifndef CONFIG_CPU_SUBTYPE_SH7780 |
124 | make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); | 121 | make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); |
125 | make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); | 122 | make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); |
126 | #if defined(CONFIG_SH_RTC) | 123 | #ifdef RTC_IRQ |
127 | make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); | 124 | make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); |
128 | #endif | 125 | #endif |
129 | 126 | ||
@@ -162,6 +159,7 @@ void __init init_IRQ(void) | |||
162 | #endif | 159 | #endif |
163 | 160 | ||
164 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ | 161 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ |
162 | defined(CONFIG_CPU_SUBTYPE_SH7706) || \ | ||
165 | defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) | 163 | defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) |
166 | /* | 164 | /* |
167 | * Initialize the Interrupt Controller (INTC) | 165 | * Initialize the Interrupt Controller (INTC) |
@@ -192,6 +190,8 @@ void __init init_IRQ(void) | |||
192 | /* Perform the machine specific initialisation */ | 190 | /* Perform the machine specific initialisation */ |
193 | if (sh_mv.mv_init_irq != NULL) | 191 | if (sh_mv.mv_init_irq != NULL) |
194 | sh_mv.mv_init_irq(); | 192 | sh_mv.mv_init_irq(); |
193 | |||
194 | irq_ctx_init(smp_processor_id()); | ||
195 | } | 195 | } |
196 | 196 | ||
197 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) | 197 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) |
diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c new file mode 100644 index 000000000000..492db31b3cab --- /dev/null +++ b/arch/sh/kernel/cpu/irq/maskreg.c | |||
@@ -0,0 +1,93 @@ | |||
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 short val, mask = 0x01 << irq; | ||
56 | |||
57 | BUG_ON(!irq_mask_register); | ||
58 | |||
59 | /* Set "irq"th bit */ | ||
60 | val = ctrl_inw(irq_mask_register); | ||
61 | val |= mask; | ||
62 | ctrl_outw(val, irq_mask_register); | ||
63 | } | ||
64 | |||
65 | static void enable_maskreg_irq(unsigned int irq) | ||
66 | { | ||
67 | unsigned short val, mask = ~(0x01 << irq); | ||
68 | |||
69 | BUG_ON(!irq_mask_register); | ||
70 | |||
71 | /* Clear "irq"th bit */ | ||
72 | val = ctrl_inw(irq_mask_register); | ||
73 | val &= mask; | ||
74 | ctrl_outw(val, irq_mask_register); | ||
75 | } | ||
76 | |||
77 | static void mask_and_ack_maskreg(unsigned int irq) | ||
78 | { | ||
79 | disable_maskreg_irq(irq); | ||
80 | } | ||
81 | |||
82 | static void end_maskreg_irq(unsigned int irq) | ||
83 | { | ||
84 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
85 | enable_maskreg_irq(irq); | ||
86 | } | ||
87 | |||
88 | void make_maskreg_irq(unsigned int irq) | ||
89 | { | ||
90 | disable_irq_nosync(irq); | ||
91 | irq_desc[irq].handler = &maskreg_irq_type; | ||
92 | disable_maskreg_irq(irq); | ||
93 | } | ||
diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c index 80cd8108d36a..17f47b373d6e 100644 --- a/arch/sh/kernel/cpu/irq/pint.c +++ b/arch/sh/kernel/cpu/irq/pint.c | |||
@@ -48,26 +48,22 @@ static struct hw_interrupt_type pint_irq_type = { | |||
48 | 48 | ||
49 | static void disable_pint_irq(unsigned int irq) | 49 | static void disable_pint_irq(unsigned int irq) |
50 | { | 50 | { |
51 | unsigned long val, flags; | 51 | unsigned long val; |
52 | 52 | ||
53 | local_irq_save(flags); | ||
54 | val = ctrl_inw(INTC_INTER); | 53 | val = ctrl_inw(INTC_INTER); |
55 | val &= ~(1 << (irq - PINT_IRQ_BASE)); | 54 | val &= ~(1 << (irq - PINT_IRQ_BASE)); |
56 | ctrl_outw(val, INTC_INTER); /* disable PINTn */ | 55 | ctrl_outw(val, INTC_INTER); /* disable PINTn */ |
57 | portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); | 56 | portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); |
58 | local_irq_restore(flags); | ||
59 | } | 57 | } |
60 | 58 | ||
61 | static void enable_pint_irq(unsigned int irq) | 59 | static void enable_pint_irq(unsigned int irq) |
62 | { | 60 | { |
63 | unsigned long val, flags; | 61 | unsigned long val; |
64 | 62 | ||
65 | local_irq_save(flags); | ||
66 | val = ctrl_inw(INTC_INTER); | 63 | val = ctrl_inw(INTC_INTER); |
67 | val |= 1 << (irq - PINT_IRQ_BASE); | 64 | val |= 1 << (irq - PINT_IRQ_BASE); |
68 | ctrl_outw(val, INTC_INTER); /* enable PINTn */ | 65 | ctrl_outw(val, INTC_INTER); /* enable PINTn */ |
69 | portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; | 66 | portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; |
70 | local_irq_restore(flags); | ||
71 | } | 67 | } |
72 | 68 | ||
73 | static void mask_and_ack_pint(unsigned int irq) | 69 | static void mask_and_ack_pint(unsigned int irq) |