aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v10
diff options
context:
space:
mode:
authorJesper Nilsson <jesper.nilsson@axis.com>2007-11-14 20:00:59 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-14 21:45:45 -0500
commit7b275523aba522aa76891861ee32ba2456e5f146 (patch)
tree6b5fa5c7916af2d91b81ca1eec3352a63eabe3ab /arch/cris/arch-v10
parent633edf5a4fff0675851e377cc5f0c9072683a5f4 (diff)
cris build fixes: corrected and improved NMI and IRQ handling
Corrects compile errors and the following: - Remove oldset parameter from do_signal and do_notify_resume. - Modified to fit new consolidated IRQ handling code. - Reverse check order between external nmi and watchdog nmi to avoid false watchdog oops in case of a glitch on the nmi pin. - Return from an pin-generated NMI the same way as for other interrupts. - Moved blocking of ethernet rx/tx irq from ethernet interrupt handler to low-level asm interrupt handlers. Fixed in the multiple interrupt handler also. - Add space for thread local storage in thread_info struct. - Add NO_DMA to Kconfig, and include arch specific Kconfig using arch independent path. Include subsystem Kconfigs for pcmcia, usb, i2c, rtc and pci. Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com> Acked-by: Mikael Starvik <starvik@axis.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/cris/arch-v10')
-rw-r--r--arch/cris/arch-v10/drivers/Kconfig1
-rw-r--r--arch/cris/arch-v10/kernel/entry.S41
-rw-r--r--arch/cris/arch-v10/kernel/irq.c59
3 files changed, 78 insertions, 23 deletions
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
index 03e2e68f947d..e6fc8455a372 100644
--- a/arch/cris/arch-v10/drivers/Kconfig
+++ b/arch/cris/arch-v10/drivers/Kconfig
@@ -2,6 +2,7 @@ config ETRAX_ETHERNET
2 bool "Ethernet support" 2 bool "Ethernet support"
3 depends on ETRAX_ARCH_V10 3 depends on ETRAX_ARCH_V10
4 select NET_ETHERNET 4 select NET_ETHERNET
5 select MII
5 help 6 help
6 This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet 7 This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
7 controller. 8 controller.
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index bc9bed97f225..ec62c951fa3c 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -500,9 +500,8 @@ _work_notifysig:
500 ;; deal with pending signals and notify-resume requests 500 ;; deal with pending signals and notify-resume requests
501 501
502 move.d $r9, $r10 ; do_notify_resume syscall/irq param 502 move.d $r9, $r10 ; do_notify_resume syscall/irq param
503 moveq 0, $r11 ; oldset param - 0 in this case 503 move.d $sp, $r11 ; the regs param
504 move.d $sp, $r12 ; the regs param 504 move.d $r1, $r12 ; the thread_info_flags parameter
505 move.d $r1, $r13 ; the thread_info_flags parameter
506 jsr do_notify_resume 505 jsr do_notify_resume
507 506
508 ba _Rexit 507 ba _Rexit
@@ -678,13 +677,19 @@ IRQ1_interrupt:
678 push $r10 ; push orig_r10 677 push $r10 ; push orig_r10
679 clear.d [$sp=$sp-4] ; frametype == 0, normal frame 678 clear.d [$sp=$sp-4] ; frametype == 0, normal frame
680 679
680 ;; If there is a glitch on the NMI pin shorter than ~100ns
681 ;; (i.e. non-active by the time we get here) then the nmi_pin bit
682 ;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit
683 ;; is cleared by us however (when feeding the watchdog), which is why
684 ;; we use that bit to determine what brought us here.
685
681 move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog? 686 move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
682 and.d 0x80000000, $r1 687 and.d (1<<30), $r1
683 beq wdog 688 bne wdog
684 move.d $sp, $r10 689 move.d $sp, $r10
685 jsr handle_nmi 690 jsr handle_nmi
686 setf m ; Enable NMI again 691 setf m ; Enable NMI again
687 retb ; Return from NMI 692 ba _Rexit ; Return the standard way
688 nop 693 nop
689wdog: 694wdog:
690#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM) 695#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
@@ -775,22 +780,9 @@ multiple_interrupt:
775 push $r10 ; push orig_r10 780 push $r10 ; push orig_r10
776 clear.d [$sp=$sp-4] ; frametype == 0, normal frame 781 clear.d [$sp=$sp-4] ; frametype == 0, normal frame
777 782
778 moveq 2, $r2 ; first bit we care about is the timer0 irq 783 move.d $sp, $r10
779 move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq 784 jsr do_multiple_IRQ
780 move.d $r0, [R_VECT_MASK_CLR] ; Block all active IRQs
7811:
782 btst $r2, $r0 ; check for the irq given by bit r2
783 bpl 2f
784 move.d $r2, $r10 ; First argument to do_IRQ
785 move.d $sp, $r11 ; second argument to do_IRQ
786 jsr do_IRQ
7872:
788 addq 1, $r2 ; next vector bit
789 cmp.b 32, $r2
790 bne 1b ; process all irq's up to and including number 31
791 moveq 0, $r9 ; make ret_from_intr realise we came from an ir
792 785
793 move.d $r0, [R_VECT_MASK_SET] ; Unblock all the IRQs
794 jump ret_from_intr 786 jump ret_from_intr
795 787
796do_sigtrap: 788do_sigtrap:
@@ -837,6 +829,13 @@ _ugdb_handle_breakpoint:
837 ba do_sigtrap ; SIGTRAP the offending process. 829 ba do_sigtrap ; SIGTRAP the offending process.
838 pop $dccr ; Restore dccr in delay slot. 830 pop $dccr ; Restore dccr in delay slot.
839 831
832 .global kernel_execve
833kernel_execve:
834 move.d __NR_execve, $r9
835 break 13
836 ret
837 nop
838
840 .data 839 .data
841 840
842hw_bp_trigs: 841hw_bp_trigs:
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index 845c95f6e871..e06ab0050d37 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -12,10 +12,16 @@
12 */ 12 */
13 13
14#include <asm/irq.h> 14#include <asm/irq.h>
15#include <asm/current.h>
15#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/interrupt.h>
16#include <linux/kernel.h> 18#include <linux/kernel.h>
17#include <linux/init.h> 19#include <linux/init.h>
18 20
21/* From kgdb.c. */
22extern void kgdb_init(void);
23extern void breakpoint(void);
24
19#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); 25#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
20#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); 26#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
21 27
@@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000)
75BUILD_IRQ(13, 0x2000) 81BUILD_IRQ(13, 0x2000)
76void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ 82void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
77void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ 83void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
78BUILD_IRQ(16, 0x10000) 84BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */
79BUILD_IRQ(17, 0x20000) 85BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */
80BUILD_IRQ(18, 0x40000) 86BUILD_IRQ(18, 0x40000)
81BUILD_IRQ(19, 0x80000) 87BUILD_IRQ(19, 0x80000)
82BUILD_IRQ(20, 0x100000) 88BUILD_IRQ(20, 0x100000)
@@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */
147void do_sigtrap(void); /* from entry.S */ 153void do_sigtrap(void); /* from entry.S */
148void gdb_handle_breakpoint(void); /* from entry.S */ 154void gdb_handle_breakpoint(void); /* from entry.S */
149 155
156extern void do_IRQ(int irq, struct pt_regs * regs);
157
158/* Handle multiple IRQs */
159void do_multiple_IRQ(struct pt_regs* regs)
160{
161 int bit;
162 unsigned masked;
163 unsigned mask;
164 unsigned ethmask = 0;
165
166 /* Get interrupts to mask and handle */
167 mask = masked = *R_VECT_MASK_RD;
168
169 /* Never mask timer IRQ */
170 mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0));
171
172 /*
173 * If either ethernet interrupt (rx or tx) is active then block
174 * the other one too. Unblock afterwards also.
175 */
176 if (mask &
177 (IO_STATE(R_VECT_MASK_RD, dma0, active) |
178 IO_STATE(R_VECT_MASK_RD, dma1, active))) {
179 ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) |
180 IO_MASK(R_VECT_MASK_RD, dma1));
181 }
182
183 /* Block them */
184 *R_VECT_MASK_CLR = (mask | ethmask);
185
186 /* An extra irq_enter here to prevent softIRQs to run after
187 * each do_IRQ. This will decrease the interrupt latency.
188 */
189 irq_enter();
190
191 /* Handle all IRQs */
192 for (bit = 2; bit < 32; bit++) {
193 if (masked & (1 << bit)) {
194 do_IRQ(bit, regs);
195 }
196 }
197
198 /* This irq_exit() will trigger the soft IRQs. */
199 irq_exit();
200
201 /* Unblock the IRQs again */
202 *R_VECT_MASK_SET = (masked | ethmask);
203}
204
150/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and 205/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
151 setting the irq vector table. 206 setting the irq vector table.
152*/ 207*/