diff options
author | Geert Uytterhoeven <geert@linux-m68k.org> | 2011-04-21 16:50:52 -0400 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2011-11-08 16:35:49 -0500 |
commit | 4936f63cb790e265eb30a1e1630bb90bd6af0e7a (patch) | |
tree | 9cd5da60334940b4d6b190a10262f02823b06aa5 /arch | |
parent | 5a2394534b160ce18f9a705cf9de40e77648f8a2 (diff) |
m68k/irq: Add genirq support
Disabled on all platforms for now
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
[v1] Acked-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/m68k/Kconfig | 17 | ||||
-rw-r--r-- | arch/m68k/include/asm/hardirq.h | 5 | ||||
-rw-r--r-- | arch/m68k/include/asm/irq.h | 41 | ||||
-rw-r--r-- | arch/m68k/kernel/Makefile | 9 | ||||
-rw-r--r-- | arch/m68k/kernel/ints.c | 52 |
5 files changed, 112 insertions, 12 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 6c28582fb98f..a7597e119ab0 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -84,6 +84,23 @@ config MMU_SUN3 | |||
84 | bool | 84 | bool |
85 | depends on MMU && !MMU_MOTOROLA | 85 | depends on MMU && !MMU_MOTOROLA |
86 | 86 | ||
87 | config USE_GENERIC_HARDIRQS | ||
88 | bool "Use genirq" | ||
89 | depends on MMU | ||
90 | depends on !AMIGA | ||
91 | depends on !ATARI | ||
92 | depends on !MAC | ||
93 | depends on !APOLLO | ||
94 | depends on !MVME147 | ||
95 | depends on !MVME16x | ||
96 | depends on !BVME6000 | ||
97 | depends on !HP300 | ||
98 | depends on !SUN3X | ||
99 | depends on !Q40 | ||
100 | depends on !SUN3 | ||
101 | select HAVE_GENERIC_HARDIRQS | ||
102 | select GENERIC_IRQ_SHOW | ||
103 | |||
87 | menu "Platform setup" | 104 | menu "Platform setup" |
88 | 105 | ||
89 | source arch/m68k/Kconfig.cpu | 106 | source arch/m68k/Kconfig.cpu |
diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h index 870e5347155b..db30ed276878 100644 --- a/arch/m68k/include/asm/hardirq.h +++ b/arch/m68k/include/asm/hardirq.h | |||
@@ -18,6 +18,11 @@ | |||
18 | 18 | ||
19 | #ifdef CONFIG_MMU | 19 | #ifdef CONFIG_MMU |
20 | 20 | ||
21 | static inline void ack_bad_irq(unsigned int irq) | ||
22 | { | ||
23 | pr_crit("unexpected IRQ trap at vector %02x\n", irq); | ||
24 | } | ||
25 | |||
21 | /* entry.S is sensitive to the offsets of these fields */ | 26 | /* entry.S is sensitive to the offsets of these fields */ |
22 | typedef struct { | 27 | typedef struct { |
23 | unsigned int __softirq_pending; | 28 | unsigned int __softirq_pending; |
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 9a2bae8ef5b7..518e61f2fccb 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h | |||
@@ -27,11 +27,6 @@ | |||
27 | 27 | ||
28 | #ifdef CONFIG_MMU | 28 | #ifdef CONFIG_MMU |
29 | 29 | ||
30 | #include <linux/linkage.h> | ||
31 | #include <linux/hardirq.h> | ||
32 | #include <linux/irqreturn.h> | ||
33 | #include <linux/spinlock_types.h> | ||
34 | |||
35 | /* | 30 | /* |
36 | * Interrupt source definitions | 31 | * Interrupt source definitions |
37 | * General interrupt sources are the level 1-7. | 32 | * General interrupt sources are the level 1-7. |
@@ -54,10 +49,6 @@ | |||
54 | 49 | ||
55 | #define IRQ_USER 8 | 50 | #define IRQ_USER 8 |
56 | 51 | ||
57 | extern unsigned int irq_canonicalize(unsigned int irq); | ||
58 | |||
59 | struct pt_regs; | ||
60 | |||
61 | /* | 52 | /* |
62 | * various flags for request_irq() - the Amiga now uses the standard | 53 | * various flags for request_irq() - the Amiga now uses the standard |
63 | * mechanism like all other architectures - IRQF_DISABLED and | 54 | * mechanism like all other architectures - IRQF_DISABLED and |
@@ -71,6 +62,15 @@ struct pt_regs; | |||
71 | #define IRQ_FLG_STD (0x8000) /* internally used */ | 62 | #define IRQ_FLG_STD (0x8000) /* internally used */ |
72 | #endif | 63 | #endif |
73 | 64 | ||
65 | #ifndef CONFIG_GENERIC_HARDIRQS | ||
66 | |||
67 | #include <linux/linkage.h> | ||
68 | #include <linux/hardirq.h> | ||
69 | #include <linux/irqreturn.h> | ||
70 | #include <linux/spinlock_types.h> | ||
71 | |||
72 | struct pt_regs; | ||
73 | |||
74 | /* | 74 | /* |
75 | * This structure is used to chain together the ISRs for a particular | 75 | * This structure is used to chain together the ISRs for a particular |
76 | * interrupt source (if it supports chaining). | 76 | * interrupt source (if it supports chaining). |
@@ -121,10 +121,33 @@ extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); | |||
121 | extern void generic_handle_irq(unsigned int); | 121 | extern void generic_handle_irq(unsigned int); |
122 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs); | 122 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs); |
123 | 123 | ||
124 | #else /* CONFIG_GENERIC_HARDIRQS */ | ||
125 | |||
126 | struct irq_data; | ||
127 | struct irq_chip; | ||
128 | struct irq_desc; | ||
129 | extern unsigned int m68k_irq_startup(struct irq_data *data); | ||
130 | extern unsigned int m68k_irq_startup_irq(unsigned int irq); | ||
131 | extern void m68k_irq_shutdown(struct irq_data *data); | ||
132 | extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, | ||
133 | struct pt_regs *)); | ||
134 | extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, | ||
135 | void (*handler)(unsigned int, | ||
136 | struct pt_regs *)); | ||
137 | extern void m68k_setup_irq_controller(struct irq_chip *, | ||
138 | void (*handle)(unsigned int irq, | ||
139 | struct irq_desc *desc), | ||
140 | unsigned int irq, unsigned int cnt); | ||
141 | |||
142 | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||
143 | |||
144 | extern unsigned int irq_canonicalize(unsigned int irq); | ||
145 | |||
124 | #else | 146 | #else |
125 | #define irq_canonicalize(irq) (irq) | 147 | #define irq_canonicalize(irq) (irq) |
126 | #endif /* CONFIG_MMU */ | 148 | #endif /* CONFIG_MMU */ |
127 | 149 | ||
128 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs); | 150 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs); |
151 | extern atomic_t irq_err_count; | ||
129 | 152 | ||
130 | #endif /* _M68K_IRQ_H_ */ | 153 | #endif /* _M68K_IRQ_H_ */ |
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index e7f0f2e5ad44..141425785c4e 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile | |||
@@ -9,13 +9,18 @@ extra-y += vmlinux.lds | |||
9 | obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ | 9 | obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ |
10 | sys_m68k.o syscalltable.o time.o traps.o | 10 | sys_m68k.o syscalltable.o time.o traps.o |
11 | 11 | ||
12 | obj-$(CONFIG_MMU) += ints.o devres.o vectors.o | 12 | obj-$(CONFIG_MMU) += ints.o vectors.o |
13 | devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o | 13 | devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o |
14 | 14 | ||
15 | ifndef CONFIG_MMU_SUN3 | 15 | ifndef CONFIG_MMU_SUN3 |
16 | obj-y += dma.o | 16 | obj-y += dma.o |
17 | endif | 17 | endif |
18 | ifndef CONFIG_MMU | 18 | ifndef CONFIG_MMU |
19 | obj-y += init_task.o irq.o | 19 | obj-y += init_task.o |
20 | endif | ||
21 | ifdef CONFIG_GENERIC_HARDIRQS | ||
22 | obj-y += irq.o | ||
23 | else | ||
24 | obj-y += devres.o | ||
20 | endif | 25 | endif |
21 | 26 | ||
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index f6a469865125..cea439f9819b 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c | |||
@@ -31,6 +31,7 @@ extern u32 auto_irqhandler_fixup[]; | |||
31 | extern u32 user_irqhandler_fixup[]; | 31 | extern u32 user_irqhandler_fixup[]; |
32 | extern u16 user_irqvec_fixup[]; | 32 | extern u16 user_irqvec_fixup[]; |
33 | 33 | ||
34 | #ifndef CONFIG_GENERIC_HARDIRQS | ||
34 | /* table for system interrupt handlers */ | 35 | /* table for system interrupt handlers */ |
35 | static struct irq_data *irq_list[NR_IRQS]; | 36 | static struct irq_data *irq_list[NR_IRQS]; |
36 | static struct irq_chip *irq_chip[NR_IRQS]; | 37 | static struct irq_chip *irq_chip[NR_IRQS]; |
@@ -41,6 +42,8 @@ static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip) | |||
41 | irq_chip[irq] = chip; | 42 | irq_chip[irq] = chip; |
42 | return 0; | 43 | return 0; |
43 | } | 44 | } |
45 | #define irq_set_chip_and_handler(irq, chip, dummy) irq_set_chip(irq, chip) | ||
46 | #endif /* !CONFIG_GENERIC_HARDIRQS */ | ||
44 | 47 | ||
45 | static int m68k_first_user_vec; | 48 | static int m68k_first_user_vec; |
46 | 49 | ||
@@ -56,8 +59,10 @@ static struct irq_chip user_irq_chip = { | |||
56 | .irq_shutdown = m68k_irq_shutdown, | 59 | .irq_shutdown = m68k_irq_shutdown, |
57 | }; | 60 | }; |
58 | 61 | ||
62 | #ifndef CONFIG_GENERIC_HARDIRQS | ||
59 | #define NUM_IRQ_NODES 100 | 63 | #define NUM_IRQ_NODES 100 |
60 | static struct irq_data nodes[NUM_IRQ_NODES]; | 64 | static struct irq_data nodes[NUM_IRQ_NODES]; |
65 | #endif /* !CONFIG_GENERIC_HARDIRQS */ | ||
61 | 66 | ||
62 | /* | 67 | /* |
63 | * void init_IRQ(void) | 68 | * void init_IRQ(void) |
@@ -81,7 +86,7 @@ void __init init_IRQ(void) | |||
81 | } | 86 | } |
82 | 87 | ||
83 | for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) | 88 | for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) |
84 | irq_set_chip(i, &auto_irq_chip); | 89 | irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq); |
85 | 90 | ||
86 | mach_init_IRQ(); | 91 | mach_init_IRQ(); |
87 | } | 92 | } |
@@ -128,6 +133,35 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, | |||
128 | flush_icache(); | 133 | flush_icache(); |
129 | } | 134 | } |
130 | 135 | ||
136 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
137 | |||
138 | /** | ||
139 | * m68k_setup_irq_controller | ||
140 | * @chip: irq chip which controls specified irq | ||
141 | * @handle: flow handler which handles specified irq | ||
142 | * @irq: first irq to be managed by the controller | ||
143 | * @cnt: number of irqs to be managed by the controller | ||
144 | * | ||
145 | * Change the controller for the specified range of irq, which will be used to | ||
146 | * manage these irq. auto/user irq already have a default controller, which can | ||
147 | * be changed as well, but the controller probably should use m68k_irq_startup/ | ||
148 | * m68k_irq_shutdown. | ||
149 | */ | ||
150 | void m68k_setup_irq_controller(struct irq_chip *chip, | ||
151 | irq_flow_handler_t handle, unsigned int irq, | ||
152 | unsigned int cnt) | ||
153 | { | ||
154 | int i; | ||
155 | |||
156 | for (i = 0; i < cnt; i++) { | ||
157 | irq_set_chip(irq + i, chip); | ||
158 | if (handle) | ||
159 | irq_set_handler(irq + i, handle); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | #else /* !CONFIG_GENERIC_HARDIRQS */ | ||
164 | |||
131 | /** | 165 | /** |
132 | * m68k_setup_irq_chip | 166 | * m68k_setup_irq_chip |
133 | * @contr: irq controller which controls specified irq | 167 | * @contr: irq controller which controls specified irq |
@@ -316,6 +350,8 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); | |||
316 | 350 | ||
317 | EXPORT_SYMBOL(disable_irq_nosync); | 351 | EXPORT_SYMBOL(disable_irq_nosync); |
318 | 352 | ||
353 | #endif /* !CONFIG_GENERIC_HARDIRQS */ | ||
354 | |||
319 | unsigned int m68k_irq_startup_irq(unsigned int irq) | 355 | unsigned int m68k_irq_startup_irq(unsigned int irq) |
320 | { | 356 | { |
321 | if (irq <= IRQ_AUTO_7) | 357 | if (irq <= IRQ_AUTO_7) |
@@ -341,6 +377,8 @@ void m68k_irq_shutdown(struct irq_data *data) | |||
341 | } | 377 | } |
342 | 378 | ||
343 | 379 | ||
380 | #ifndef CONFIG_GENERIC_HARDIRQS | ||
381 | |||
344 | /* | 382 | /* |
345 | * Do we need these probe functions on the m68k? | 383 | * Do we need these probe functions on the m68k? |
346 | * | 384 | * |
@@ -367,6 +405,7 @@ int probe_irq_off (unsigned long irqs) | |||
367 | } | 405 | } |
368 | 406 | ||
369 | EXPORT_SYMBOL(probe_irq_off); | 407 | EXPORT_SYMBOL(probe_irq_off); |
408 | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||
370 | 409 | ||
371 | unsigned int irq_canonicalize(unsigned int irq) | 410 | unsigned int irq_canonicalize(unsigned int irq) |
372 | { | 411 | { |
@@ -379,6 +418,7 @@ unsigned int irq_canonicalize(unsigned int irq) | |||
379 | 418 | ||
380 | EXPORT_SYMBOL(irq_canonicalize); | 419 | EXPORT_SYMBOL(irq_canonicalize); |
381 | 420 | ||
421 | #ifndef CONFIG_GENERIC_HARDIRQS | ||
382 | void generic_handle_irq(unsigned int irq) | 422 | void generic_handle_irq(unsigned int irq) |
383 | { | 423 | { |
384 | struct irq_data *node; | 424 | struct irq_data *node; |
@@ -428,3 +468,13 @@ void init_irq_proc(void) | |||
428 | /* Insert /proc/irq driver here */ | 468 | /* Insert /proc/irq driver here */ |
429 | } | 469 | } |
430 | #endif | 470 | #endif |
471 | |||
472 | #else /* CONFIG_GENERIC_HARDIRQS */ | ||
473 | |||
474 | asmlinkage void handle_badint(struct pt_regs *regs) | ||
475 | { | ||
476 | atomic_inc(&irq_err_count); | ||
477 | pr_warn("unexpected interrupt from %u\n", regs->vector); | ||
478 | } | ||
479 | |||
480 | #endif /* CONFIG_GENERIC_HARDIRQS */ | ||