diff options
author | Chris Zankel <czankel@tensilica.com> | 2006-12-10 05:18:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-10 12:55:39 -0500 |
commit | fd43fe19b830d6cd0eba08a6c6a5f71a6bd9c1b0 (patch) | |
tree | 5225910274cbf362143a80b95b6b38c4a7d22e6d /arch/xtensa/kernel | |
parent | 5fcf7bb73f66cc1c4ad90788b0f367c4d6852b75 (diff) |
[PATCH] xtensa: fix irq and misc fixes
Update the architecture specific interrupt handling code for Xtensa to support
the new API. Use generic BUG macros in bug.h, and some minor fixes.
Signed-off-by: Chris Zankel <chris@zankel.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/irq.c | 107 | ||||
-rw-r--r-- | arch/xtensa/kernel/time.c | 8 | ||||
-rw-r--r-- | arch/xtensa/kernel/vmlinux.lds.S | 1 |
3 files changed, 57 insertions, 59 deletions
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 1cf744ee0959..c9ea73b7031b 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Xtensa built-in interrupt controller and some generic functions copied | 4 | * Xtensa built-in interrupt controller and some generic functions copied |
5 | * from i386. | 5 | * from i386. |
6 | * | 6 | * |
7 | * Copyright (C) 2002 - 2005 Tensilica, Inc. | 7 | * Copyright (C) 2002 - 2006 Tensilica, Inc. |
8 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 8 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar |
9 | * | 9 | * |
10 | * | 10 | * |
@@ -22,11 +22,6 @@ | |||
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include <asm/platform.h> | 23 | #include <asm/platform.h> |
24 | 24 | ||
25 | static void enable_xtensa_irq(unsigned int irq); | ||
26 | static void disable_xtensa_irq(unsigned int irq); | ||
27 | static void mask_and_ack_xtensa(unsigned int irq); | ||
28 | static void end_xtensa_irq(unsigned int irq); | ||
29 | |||
30 | static unsigned int cached_irq_mask; | 25 | static unsigned int cached_irq_mask; |
31 | 26 | ||
32 | atomic_t irq_err_count; | 27 | atomic_t irq_err_count; |
@@ -46,8 +41,16 @@ void ack_bad_irq(unsigned int irq) | |||
46 | * handlers). | 41 | * handlers). |
47 | */ | 42 | */ |
48 | 43 | ||
49 | unsigned int do_IRQ(int irq, struct pt_regs *regs) | 44 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs) |
50 | { | 45 | { |
46 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
47 | struct irq_desc *desc = irq_desc + irq; | ||
48 | |||
49 | if (irq >= NR_IRQS) { | ||
50 | printk(KERN_EMERG "%s: cannot handle IRQ %d\n", | ||
51 | __FUNCTION__, irq); | ||
52 | } | ||
53 | |||
51 | irq_enter(); | 54 | irq_enter(); |
52 | 55 | ||
53 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | 56 | #ifdef CONFIG_DEBUG_STACKOVERFLOW |
@@ -63,12 +66,10 @@ unsigned int do_IRQ(int irq, struct pt_regs *regs) | |||
63 | sp - sizeof(struct thread_info)); | 66 | sp - sizeof(struct thread_info)); |
64 | } | 67 | } |
65 | #endif | 68 | #endif |
66 | 69 | desc->handle_irq(irq, desc); | |
67 | __do_IRQ(irq, regs); | ||
68 | 70 | ||
69 | irq_exit(); | 71 | irq_exit(); |
70 | 72 | set_irq_regs(old_regs); | |
71 | return 1; | ||
72 | } | 73 | } |
73 | 74 | ||
74 | /* | 75 | /* |
@@ -118,72 +119,68 @@ skip: | |||
118 | } | 119 | } |
119 | return 0; | 120 | return 0; |
120 | } | 121 | } |
121 | /* shutdown is same as "disable" */ | ||
122 | #define shutdown_xtensa_irq disable_xtensa_irq | ||
123 | 122 | ||
124 | static unsigned int startup_xtensa_irq(unsigned int irq) | 123 | static void xtensa_irq_mask(unsigned int irq) |
125 | { | ||
126 | enable_xtensa_irq(irq); | ||
127 | return 0; /* never anything pending */ | ||
128 | } | ||
129 | |||
130 | static struct hw_interrupt_type xtensa_irq_type = { | ||
131 | "Xtensa-IRQ", | ||
132 | startup_xtensa_irq, | ||
133 | shutdown_xtensa_irq, | ||
134 | enable_xtensa_irq, | ||
135 | disable_xtensa_irq, | ||
136 | mask_and_ack_xtensa, | ||
137 | end_xtensa_irq | ||
138 | }; | ||
139 | |||
140 | static inline void mask_irq(unsigned int irq) | ||
141 | { | 124 | { |
142 | cached_irq_mask &= ~(1 << irq); | 125 | cached_irq_mask &= ~(1 << irq); |
143 | set_sr (cached_irq_mask, INTENABLE); | 126 | set_sr (cached_irq_mask, INTENABLE); |
144 | } | 127 | } |
145 | 128 | ||
146 | static inline void unmask_irq(unsigned int irq) | 129 | static void xtensa_irq_unmask(unsigned int irq) |
147 | { | 130 | { |
148 | cached_irq_mask |= 1 << irq; | 131 | cached_irq_mask |= 1 << irq; |
149 | set_sr (cached_irq_mask, INTENABLE); | 132 | set_sr (cached_irq_mask, INTENABLE); |
150 | } | 133 | } |
151 | 134 | ||
152 | static void disable_xtensa_irq(unsigned int irq) | 135 | static void xtensa_irq_ack(unsigned int irq) |
153 | { | 136 | { |
154 | unsigned long flags; | 137 | set_sr(1 << irq, INTCLEAR); |
155 | local_save_flags(flags); | ||
156 | mask_irq(irq); | ||
157 | local_irq_restore(flags); | ||
158 | } | 138 | } |
159 | 139 | ||
160 | static void enable_xtensa_irq(unsigned int irq) | 140 | static int xtensa_irq_retrigger(unsigned int irq) |
161 | { | 141 | { |
162 | unsigned long flags; | 142 | set_sr (1 << irq, INTSET); |
163 | local_save_flags(flags); | 143 | return 1; |
164 | unmask_irq(irq); | ||
165 | local_irq_restore(flags); | ||
166 | } | ||
167 | |||
168 | static void mask_and_ack_xtensa(unsigned int irq) | ||
169 | { | ||
170 | disable_xtensa_irq(irq); | ||
171 | } | 144 | } |
172 | 145 | ||
173 | static void end_xtensa_irq(unsigned int irq) | ||
174 | { | ||
175 | enable_xtensa_irq(irq); | ||
176 | } | ||
177 | 146 | ||
147 | static struct irq_chip xtensa_irq_chip = { | ||
148 | .name = "xtensa", | ||
149 | .mask = xtensa_irq_mask, | ||
150 | .unmask = xtensa_irq_unmask, | ||
151 | .ack = xtensa_irq_ack, | ||
152 | .retrigger = xtensa_irq_retrigger, | ||
153 | }; | ||
178 | 154 | ||
179 | void __init init_IRQ(void) | 155 | void __init init_IRQ(void) |
180 | { | 156 | { |
181 | int i; | 157 | int index; |
182 | 158 | ||
183 | for (i=0; i < XTENSA_NR_IRQS; i++) | 159 | for (index = 0; index < XTENSA_NR_IRQS; index++) { |
184 | irq_desc[i].chip = &xtensa_irq_type; | 160 | int mask = 1 << index; |
185 | 161 | ||
186 | cached_irq_mask = 0; | 162 | if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) |
163 | set_irq_chip_and_handler(index, &xtensa_irq_chip, | ||
164 | handle_simple_irq); | ||
187 | 165 | ||
188 | platform_init_irq(); | 166 | else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) |
167 | set_irq_chip_and_handler(index, &xtensa_irq_chip, | ||
168 | handle_edge_irq); | ||
169 | |||
170 | else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) | ||
171 | set_irq_chip_and_handler(index, &xtensa_irq_chip, | ||
172 | handle_level_irq); | ||
173 | |||
174 | else if (mask & XCHAL_INTTYPE_MASK_TIMER) | ||
175 | set_irq_chip_and_handler(index, &xtensa_irq_chip, | ||
176 | handle_edge_irq); | ||
177 | |||
178 | else /* XCHAL_INTTYPE_MASK_WRITE_ERROR */ | ||
179 | /* XCHAL_INTTYPE_MASK_NMI */ | ||
180 | |||
181 | set_irq_chip_and_handler(index, &xtensa_irq_chip, | ||
182 | handle_level_irq); | ||
183 | } | ||
184 | |||
185 | cached_irq_mask = 0; | ||
189 | } | 186 | } |
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 37347e369987..a350431363a0 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
@@ -47,7 +47,7 @@ unsigned long long sched_clock(void) | |||
47 | return (unsigned long long)jiffies * (1000000000 / HZ); | 47 | return (unsigned long long)jiffies * (1000000000 / HZ); |
48 | } | 48 | } |
49 | 49 | ||
50 | static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 50 | static irqreturn_t timer_interrupt(int irq, void *dev_id); |
51 | static struct irqaction timer_irqaction = { | 51 | static struct irqaction timer_irqaction = { |
52 | .handler = timer_interrupt, | 52 | .handler = timer_interrupt, |
53 | .flags = IRQF_DISABLED, | 53 | .flags = IRQF_DISABLED, |
@@ -150,7 +150,7 @@ EXPORT_SYMBOL(do_gettimeofday); | |||
150 | * The timer interrupt is called HZ times per second. | 150 | * The timer interrupt is called HZ times per second. |
151 | */ | 151 | */ |
152 | 152 | ||
153 | irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) | 153 | irqreturn_t timer_interrupt (int irq, void *dev_id) |
154 | { | 154 | { |
155 | 155 | ||
156 | unsigned long next; | 156 | unsigned long next; |
@@ -160,9 +160,9 @@ irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) | |||
160 | again: | 160 | again: |
161 | while ((signed long)(get_ccount() - next) > 0) { | 161 | while ((signed long)(get_ccount() - next) > 0) { |
162 | 162 | ||
163 | profile_tick(CPU_PROFILING, regs); | 163 | profile_tick(CPU_PROFILING); |
164 | #ifndef CONFIG_SMP | 164 | #ifndef CONFIG_SMP |
165 | update_process_times(user_mode(regs)); | 165 | update_process_times(user_mode(get_irq_regs())); |
166 | #endif | 166 | #endif |
167 | 167 | ||
168 | write_seqlock(&xtime_lock); | 168 | write_seqlock(&xtime_lock); |
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index cfe75f528725..e01131fec69e 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm-generic/vmlinux.lds.h> | 17 | #include <asm-generic/vmlinux.lds.h> |
18 | 18 | ||
19 | #define _NOCLANGUAGE | 19 | #define _NOCLANGUAGE |
20 | #undef __ASSEMBLER__ | ||
20 | #include <xtensa/config/core.h> | 21 | #include <xtensa/config/core.h> |
21 | #include <xtensa/config/system.h> | 22 | #include <xtensa/config/system.h> |
22 | OUTPUT_ARCH(xtensa) | 23 | OUTPUT_ARCH(xtensa) |