2 * linux/arch/arm/kernel/entry-armv.S
4 * Copyright (C) 1996,1997,1998 Russell King.
5 * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Low-level vector interface routines
13 * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes
14 * it to save wrong values... Be aware!
16 #include <linux/config.h>
17 #include <linux/init.h>
19 #include <asm/thread_info.h>
21 #include <asm/ptrace.h>
23 #include "entry-header.S"
26 /* IOC / IOMD based hardware */
27 #include <asm/hardware/iomd.h>
29 .equ ioc_base_high, IOC_BASE & 0xff000000
30 .equ ioc_base_low, IOC_BASE & 0x00ff0000
32 mov r12, #ioc_base_high
34 orr r12, r12, #ioc_base_low
36 strb r12, [r12, #0x38] @ Disable FIQ register
39 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
40 mov r4, #ioc_base_high @ point at IOC
42 orr r4, r4, #ioc_base_low
44 ldrb \irqstat, [r4, #IOMD_IRQREQB] @ get high priority first
45 ldr \base, =irq_prio_h
48 ldreqb \irqstat, [r4, #IOMD_DMAREQ] @ get dma
49 addeq \base, \base, #256 @ irq_prio_h table size
53 ldreqb \irqstat, [r4, #IOMD_IRQREQA] @ get low priority
54 addeq \base, \base, #256 @ irq_prio_d table size
57 ldreqb \irqstat, [r4, #IOMD_IRQREQC]
58 addeq \base, \base, #256 @ irq_prio_l table size
62 ldreqb \irqstat, [r4, #IOMD_IRQREQD]
63 addeq \base, \base, #256 @ irq_prio_lc table size
66 2406: ldrneb \irqnr, [\base, \irqstat] @ get IRQ number
70 * Interrupt table (incorporates priority). Please note that we
71 * rely on the order of these tables (see above code).
74 irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
75 .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
76 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
77 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
78 .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
79 .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
80 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
81 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
82 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
83 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
84 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
85 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
86 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
87 .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
88 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
89 .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
91 irq_prio_d: .byte 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
92 .byte 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
93 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
94 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
95 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
96 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
97 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
98 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
99 .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
100 .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
101 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
102 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
103 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
104 .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
105 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
106 .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16
108 irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
109 .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
110 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
111 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
112 .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
113 .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
114 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
115 .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
116 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
117 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
118 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
119 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
120 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
121 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
122 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
123 .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
125 irq_prio_lc: .byte 24,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
126 .byte 28,24,25,24,26,26,26,26,27,27,27,27,27,27,27,27
127 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
128 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
129 .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
130 .byte 30,30,30,30,30,30,30,30,27,27,27,27,27,27,27,27
131 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
132 .byte 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29
133 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
134 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
135 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
136 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
137 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
138 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
139 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
140 .byte 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
143 irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
144 .byte 44,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
145 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
146 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
147 .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
148 .byte 46,46,46,46,46,46,46,46,43,43,43,43,43,43,43,43
149 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
150 .byte 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45
151 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
152 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
153 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
154 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
155 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
156 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
157 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
158 .byte 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
162 #elif defined(CONFIG_ARCH_EBSA110)
164 #define IRQ_STAT 0xff000000 /* read */
169 .macro get_irqnr_and_base, irqnr, stat, base, tmp
171 ldrb \stat, [\base] @ get interrupts
174 addeq \irqnr, \irqnr, #4
175 moveq \stat, \stat, lsr #4
177 addeq \irqnr, \irqnr, #2
178 moveq \stat, \stat, lsr #2
180 addeq \irqnr, \irqnr, #1
181 moveq \stat, \stat, lsr #1
182 tst \stat, #1 @ bit 0 should be set
185 .macro irq_prio_table
188 #elif defined(CONFIG_ARCH_SHARK)
193 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
197 strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */
198 ldrb \irqnr, [r4, #0x20] @irq = inb(0x20) & 7
199 and \irqstat, \irqnr, #0x80
202 and \irqnr, \irqnr, #7
205 43: mov \irqstat, #0x0C
206 strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
207 ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8
208 and \irqstat, \irqnr, #0x80
211 and \irqnr, \irqnr, #7
212 add \irqnr, \irqnr, #8
216 .macro irq_prio_table
219 #elif defined(CONFIG_FOOTBRIDGE)
220 #include <asm/hardware/dec21285.h>
225 .equ dc21285_high, ARMCSR_BASE & 0xff000000
226 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff
228 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
229 mov r4, #dc21285_high
231 orr r4, r4, #dc21285_low
233 ldr \irqstat, [r4, #0x180] @ get interrupts
235 mov \irqnr, #IRQ_SDRAMPARITY
236 tst \irqstat, #IRQ_MASK_SDRAMPARITY
239 tst \irqstat, #IRQ_MASK_UART_RX
240 movne \irqnr, #IRQ_CONRX
243 tst \irqstat, #IRQ_MASK_DMA1
244 movne \irqnr, #IRQ_DMA1
247 tst \irqstat, #IRQ_MASK_DMA2
248 movne \irqnr, #IRQ_DMA2
251 tst \irqstat, #IRQ_MASK_IN0
252 movne \irqnr, #IRQ_IN0
255 tst \irqstat, #IRQ_MASK_IN1
256 movne \irqnr, #IRQ_IN1
259 tst \irqstat, #IRQ_MASK_IN2
260 movne \irqnr, #IRQ_IN2
263 tst \irqstat, #IRQ_MASK_IN3
264 movne \irqnr, #IRQ_IN3
267 tst \irqstat, #IRQ_MASK_PCI
268 movne \irqnr, #IRQ_PCI
271 tst \irqstat, #IRQ_MASK_DOORBELLHOST
272 movne \irqnr, #IRQ_DOORBELLHOST
275 tst \irqstat, #IRQ_MASK_I2OINPOST
276 movne \irqnr, #IRQ_I2OINPOST
279 tst \irqstat, #IRQ_MASK_TIMER1
280 movne \irqnr, #IRQ_TIMER1
283 tst \irqstat, #IRQ_MASK_TIMER2
284 movne \irqnr, #IRQ_TIMER2
287 tst \irqstat, #IRQ_MASK_TIMER3
288 movne \irqnr, #IRQ_TIMER3
291 tst \irqstat, #IRQ_MASK_UART_TX
292 movne \irqnr, #IRQ_CONTX
295 tst \irqstat, #IRQ_MASK_PCI_ABORT
296 movne \irqnr, #IRQ_PCI_ABORT
299 tst \irqstat, #IRQ_MASK_PCI_SERR
300 movne \irqnr, #IRQ_PCI_SERR
303 tst \irqstat, #IRQ_MASK_DISCARD_TIMER
304 movne \irqnr, #IRQ_DISCARD_TIMER
307 tst \irqstat, #IRQ_MASK_PCI_DPERR
308 movne \irqnr, #IRQ_PCI_DPERR
311 tst \irqstat, #IRQ_MASK_PCI_PERR
312 movne \irqnr, #IRQ_PCI_PERR
316 .macro irq_prio_table
319 #elif defined(CONFIG_ARCH_NEXUSPCI)
324 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
325 ldr \irqstat, =INTCONT_BASE
326 ldr \base, =soft_irq_mask
327 ldr \irqstat, [\irqstat] @ get interrupts
330 and \irqstat, \irqstat, \base @ mask out disabled ones
331 1001: tst \irqstat, #1
332 addeq \irqnr, \irqnr, #1
333 moveq \irqstat, \irqstat, lsr #1
339 .macro irq_prio_table
347 #elif defined(CONFIG_ARCH_TBOX)
352 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
353 ldr \irqstat, =0xffff7000
354 ldr \irqstat, [\irqstat] @ get interrupts
355 ldr \base, =soft_irq_mask
358 and \irqstat, \irqstat, \base @ mask out disabled ones
359 1001: tst \irqstat, #1
360 addeq \irqnr, \irqnr, #1
361 moveq \irqstat, \irqstat, lsr #1
367 .macro irq_prio_table
375 #elif defined(CONFIG_ARCH_SA1100)
380 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
381 mov r4, #0xfa000000 @ ICIP = 0xfa050000
382 add r4, r4, #0x00050000
383 ldr \irqstat, [r4] @ get irqs
384 ldr \irqnr, [r4, #4] @ ICMR = 0xfa050004
385 ands \irqstat, \irqstat, \irqnr
389 moveq \irqstat, \irqstat, lsr #8
390 addeq \irqnr, \irqnr, #8
391 tsteq \irqstat, #0xff
392 moveq \irqstat, \irqstat, lsr #8
393 addeq \irqnr, \irqnr, #8
394 tsteq \irqstat, #0xff
395 moveq \irqstat, \irqstat, lsr #8
396 addeq \irqnr, \irqnr, #8
398 moveq \irqstat, \irqstat, lsr #4
399 addeq \irqnr, \irqnr, #4
401 moveq \irqstat, \irqstat, lsr #2
402 addeq \irqnr, \irqnr, #2
404 addeqs \irqnr, \irqnr, #1
408 .macro irq_prio_table
411 #elif defined(CONFIG_ARCH_L7200)
412 #include <asm/hardware.h>
414 .equ irq_base_addr, IO_BASE_2
419 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
420 mov \irqstat, #irq_base_addr @ Virt addr IRQ regs
421 add \irqstat, \irqstat, #0x00001000 @ Status reg
422 ldr \irqstat, [\irqstat, #0] @ get interrupts
424 1001: tst \irqstat, #1
425 addeq \irqnr, \irqnr, #1
426 moveq \irqstat, \irqstat, lsr #1
432 .macro irq_prio_table
435 #elif defined(CONFIG_ARCH_INTEGRATOR)
440 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
441 /* FIXME: should not be using soo many LDRs here */
442 ldr \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
443 mov \irqnr, #IRQ_PIC_START
444 ldr \irqstat, [\base, #IRQ_STATUS] @ get masked status
445 ldr \base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
447 ldreq \irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
448 moveq \irqnr, #IRQ_CIC_START
450 1001: tst \irqstat, #15
452 add \irqnr, \irqnr, #4
453 movs \irqstat, \irqstat, lsr #4
455 1002: tst \irqstat, #1
457 add \irqnr, \irqnr, #1
458 movs \irqstat, \irqstat, lsr #1
460 1003: /* EQ will be set if no irqs pending */
463 .macro irq_prio_table
466 #elif defined(CONFIG_ARCH_VERSATILE_PB)
471 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
472 ldr \base, =IO_ADDRESS(VERSATILE_VIC_BASE)
473 ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status
478 1001: tst \irqstat, #15
480 add \irqnr, \irqnr, #4
481 movs \irqstat, \irqstat, lsr #4
483 1002: tst \irqstat, #1
485 add \irqnr, \irqnr, #1
486 movs \irqstat, \irqstat, lsr #1
488 1003: /* EQ will be set if no irqs pending */
490 @ clz \irqnr, \irqstat
491 @1003: /* EQ will be set if we reach MAXIRQNUM */
494 .macro irq_prio_table
497 #elif defined(CONFIG_ARCH_CLPS711X)
499 #include <asm/hardware/clps7111.h>
504 #if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
505 #error INTSR stride != INTMR stride
508 .macro get_irqnr_and_base, irqnr, stat, base, mask
509 mov \base, #CLPS7111_BASE
510 ldr \stat, [\base, #INTSR1]
511 ldr \mask, [\base, #INTMR1]
513 mov \mask, \mask, lsl #16
514 and \stat, \stat, \mask, lsr #16
515 movs \stat, \stat, lsr #4
518 add \base, \base, #INTSR2 - INTSR1
519 ldr \stat, [\base, #INTSR1]
520 ldr \mask, [\base, #INTMR1]
522 mov \mask, \mask, lsl #16
523 and \stat, \stat, \mask, lsr #16
525 1001: tst \stat, #255
526 addeq \irqnr, \irqnr, #8
527 moveq \stat, \stat, lsr #8
529 addeq \irqnr, \irqnr, #4
530 moveq \stat, \stat, lsr #4
532 addeq \irqnr, \irqnr, #2
533 moveq \stat, \stat, lsr #2
535 addeq \irqnr, \irqnr, #1
536 moveq \stat, \stat, lsr #1
537 tst \stat, #1 @ bit 0 should be set
540 .macro irq_prio_table
543 #elif defined (CONFIG_ARCH_CAMELOT)
544 #include <asm/arch/platform.h>
545 #undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */
546 #include <asm/arch/int_ctrl00.h>
551 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
553 ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE))
554 ldr \irqnr,[\irqstat]
556 subne \irqnr,\irqnr,#1
561 .macro irq_prio_table
564 #elif defined(CONFIG_ARCH_IOP310) || defined(CONFIG_ARCH_ADIFCC)
569 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
570 mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC
571 mrc p13, 0, \base, c0, c0, 0 @ get INTCTL
573 tst \irqstat, #(1<<29) @ if INTSRC_BI
574 tstne \base, #(1<<3) @ and INTCTL_BM
575 movne \irqnr, #IRQ_XS80200_BCU
578 tst \irqstat, #(1<<28) @ if INTSRC_PI
579 tstne \base, #(1<<2) @ and INTCTL_PM
580 movne \irqnr, #IRQ_XS80200_PMU
583 tst \irqstat, #(1<<31) @ if INTSRC_FI
584 tstne \base, #(1<<0) @ and INTCTL_FM
585 movne \irqnr, #IRQ_XS80200_EXTFIQ
588 tst \irqstat, #(1<<30) @ if INTSRC_II
589 tstne \base, #(1<<1) @ and INTCTL_IM
590 movne \irqnr, #IRQ_XS80200_EXTIRQ
595 .macro irq_prio_table
598 #elif defined(CONFIG_ARCH_IOP321)
603 * Note: only deal with normal interrupts, not FIQ
605 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
607 mrc p6, 0, \irqstat, c8, c0, 0 @ Read IINTSRC
612 subs \irqnr,\base,\irqnr
613 add \irqnr,\irqnr,#IRQ_IOP321_DMA0_EOT
617 .macro irq_prio_table
620 #elif defined(CONFIG_ARCH_PXA)
625 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
626 mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000
627 add \base, \base, #0x00d00000
628 ldr \irqstat, [\base, #0] @ ICIP
629 ldr \irqnr, [\base, #4] @ ICMR
630 ands \irqnr, \irqstat, \irqnr
632 rsb \irqstat, \irqnr, #0
633 and \irqstat, \irqstat, \irqnr
635 rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
639 .macro irq_prio_table
642 #elif defined(CONFIG_ARCH_OMAP)
647 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
648 ldr \base, =IO_ADDRESS(OMAP_IH1_BASE)
649 ldr \irqnr, [\base, #IRQ_ITR]
650 ldr \tmp, [\base, #IRQ_MIR]
651 mov \irqstat, #0xffffffff
652 bic \tmp, \irqstat, \tmp
656 ldr \irqnr, [\base, #IRQ_SIR_FIQ]
658 ldreq \irqnr, [\base, #IRQ_SIR_IRQ]
659 cmpeq \irqnr, #INT_IH2_IRQ
660 ldreq \base, =IO_ADDRESS(OMAP_IH2_BASE)
661 ldreq \irqnr, [\base, #IRQ_SIR_IRQ]
662 addeqs \irqnr, \irqnr, #32
666 .macro irq_prio_table
669 #elif defined(CONFIG_ARCH_S3C2410)
670 /* S3C2410X IRQ Handler, <ben@simtec.co.uk> */
672 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
675 mov \tmp, #S3C2410_VA_IRQ
676 ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
679 beq 1002f @ external irq reg
681 beq 1003f @ lcd controller
683 @ debug check to see if interrupt reported is the same
688 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
689 mov \irqstat, \irqstat, lsr \irqnr
694 stmfd r13!, { r0 - r4 , r14 }
695 ldr r1, [ \tmp, #0x14 ] @ intoffset
696 ldr r2, [ \tmp, #0x10 ] @ INTPND
697 ldr r3, [ \tmp, #0x00 ] @ SRCPND
703 .ascii "<7>irq: err - bad offset %d, intpnd=%08x, srcpnd=%08x\n"
708 mov \tmp, #S3C2410_VA_IRQ
709 ldmfd r13!, { r0 - r4 , r14 }
711 @ try working out interript number for ourselves
713 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
715 movs \irqstat, \irqstat, lsr#1
716 bcs 30000b @ try and re-start the proccess
717 add \irqnr, \irqnr, #1
721 @ found no interrupt, set Z flag and leave
727 @ we base the s3c2410x interrupts at 16 and above to allow
728 @ isa peripherals to have their standard interrupts, also
729 @ ensure that Z flag is un-set on exit
731 @ note, we cannot be sure if we get IRQ_EINT0 (0) that
732 @ there is simply no interrupt pending, so in all other
733 @ cases we jump to say we have found something, otherwise
734 @ we check to see if the interrupt really is assrted
735 adds \irqnr, \irqnr, #IRQ_EINT0
736 teq \irqnr, #IRQ_EINT0
738 ldr \irqstat, [ \tmp, #0x10 ] @ INTPND
743 @ we get here from no main or external interrupts pending
745 add \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
746 ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND
747 ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK
749 bic \irqstat, \irqstat, \irqnr @ clear masked irqs
751 mov \irqnr, #IRQ_EINT4 @ start extint nos
752 mov \irqstat, \irqstat, lsr#4 @ ignore bottom 4 bits
754 movs \irqstat, \irqstat, lsr#1
756 add \irqnr, \irqnr, #1
757 cmp \irqnr, #IRQ_EINT23
760 @ found no interrupt, set Z flag and leave
765 @ lcd interrupt has been asserted...
766 add \tmp, \tmp, #S3C2410_VA_LCD - S3C2410_VA_IRQ
767 ldr \irqstat, [ \tmp, # 0x54 ] @ lcd int pending
770 movne \irqnr, #IRQ_LCD_FRAME
772 movne \irqnr, #IRQ_LCD_FIFO
774 @ fall through to exit with flags updated
776 1004: @ ensure Z flag clear in case our MOVS shifted out the last bit
783 /* currently don't need an disable_fiq macro */
788 /* we don't have an irq priority table */
789 .macro irq_prio_table
792 #elif defined(CONFIG_ARCH_LH7A400)
794 # if defined (CONFIG_ARCH_LH7A404)
795 # error "LH7A400 and LH7A404 are mutually exclusive"
800 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
802 mov \base, #io_p2v(0x80000000) @ APB registers
803 ldr \irqstat, [\base, #0x500] @ PIC INTSR
805 1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry
806 bcs 1008f @ Bit set; irq found
807 add \irqnr, \irqnr, #1
808 bne 1001b @ Until no bits
809 b 1009f @ Nothing? Hmm.
810 1008: movs \irqstat, #1 @ Force !Z
814 .macro irq_prio_table
817 #elif defined(CONFIG_ARCH_LH7A404)
822 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
823 mov \irqnr, #0 @ VIC1 irq base
824 mov \base, #io_p2v(0x80000000) @ APB registers
825 add \base, \base, #0x8000
826 ldr \tmp, [\base, #0x0030] @ VIC1_VECTADDR
827 tst \tmp, #VA_VECTORED @ Direct vectored
829 tst \tmp, #VA_VIC1DEFAULT @ Default vectored VIC1
830 ldrne \irqstat, [\base, #0] @ VIC1_IRQSTATUS
832 add \base, \base, #(0xa000 - 0x8000)
833 ldr \tmp, [\base, #0x0030] @ VIC2_VECTADDR
834 tst \tmp, #VA_VECTORED @ Direct vectored
836 ldr \irqstat, [\base, #0] @ VIC2_IRQSTATUS
837 mov \irqnr, #32 @ VIC2 irq base
839 1001: movs \irqstat, \irqstat, lsr #1 @ Shift into carry
840 bcs 1008f @ Bit set; irq found
841 add \irqnr, \irqnr, #1
842 bne 1001b @ Until no bits
843 b 1009f @ Nothing? Hmm.
844 1002: and \irqnr, \tmp, #0x3f @ Mask for valid bits
845 1008: movs \irqstat, #1 @ Force !Z
846 str \tmp, [\base, #0x0030] @ Clear vector
850 .macro irq_prio_table
854 #error Unknown architecture
858 * Invalid mode handlers
860 __pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
861 stmia sp, {r0 - lr} @ Save XXX r0 - lr
863 mov r1, #BAD_PREFETCH
866 __dabt_invalid: sub sp, sp, #S_FRAME_SIZE
867 stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact]
872 __irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame
873 stmfd sp, {r0 - lr} @ Save r0 - lr
878 __und_invalid: sub sp, sp, #S_FRAME_SIZE
881 mov r1, #BAD_UNDEFINSTR @ int reason
884 ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
886 stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
888 and r2, r6, #31 @ int mode
895 __dabt_svc: sub sp, sp, #S_FRAME_SIZE
896 stmia sp, {r0 - r12} @ save r0 - r12
898 add r0, sp, #S_FRAME_SIZE
899 ldmia r2, {r2 - r4} @ get pc, cpsr
902 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
903 mrs r9, cpsr @ Enable interrupts if they were
905 biceq r9, r9, #PSR_I_BIT @ previously
907 * This routine must not corrupt r9
910 ldr r4, .LCprocfns @ pass r2, r3 to
911 mov lr, pc @ processor code
912 ldr pc, [r4] @ call processor specific code
922 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
925 __irq_svc: sub sp, sp, #S_FRAME_SIZE
926 stmia sp, {r0 - r12} @ save r0 - r12
928 add r5, sp, #S_FRAME_SIZE
932 stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
933 #ifdef CONFIG_PREEMPT
935 ldr r9, [r8, #TI_PREEMPT] @ get preempt count
936 add r7, r9, #1 @ increment it
937 str r7, [r8, #TI_PREEMPT]
939 1: get_irqnr_and_base r0, r6, r5, lr
942 @ routine called with r0 = irq number, r1 = struct pt_regs *
946 #ifdef CONFIG_PREEMPT
947 ldr r0, [r8, #TI_FLAGS] @ get flags
948 tst r0, #_TIF_NEED_RESCHED
951 ldr r0, [r8, #TI_PREEMPT] @ read preempt value
953 str r9, [r8, #TI_PREEMPT] @ restore preempt count
954 strne r0, [r0, -r0] @ bug()
956 ldr r0, [sp, #S_PSR] @ irqs are already disabled
958 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
962 #ifdef CONFIG_PREEMPT
963 svc_preempt: teq r9, #0 @ was preempt count = 0
964 ldreq r6, .LCirq_stat
966 ldr r0, [r6, #4] @ local_irq_count
967 ldr r1, [r6, #8] @ local_bh_count
970 mov r7, #PREEMPT_ACTIVE
971 str r7, [r8, #TI_PREEMPT] @ set PREEMPT_ACTIVE
972 1: enable_irq r2 @ enable IRQs
974 disable_irq r0 @ disable IRQs
975 ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS
976 tst r0, #_TIF_NEED_RESCHED
977 beq preempt_return @ go again
982 __und_svc: sub sp, sp, #S_FRAME_SIZE
983 stmia sp, {r0 - r12} @ save r0 - r12
987 add r3, sp, #S_FRAME_SIZE
989 stmia r2, {r3 - r7} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
991 ldr r0, [r5, #-4] @ r0 = instruction
992 adrsvc al, r9, 1f @ r9 = normal FP return
993 bl call_fpe @ lr = undefined instr return
995 mov r0, sp @ struct pt_regs *regs
999 ldr lr, [sp, #S_PSR] @ Get SVC cpsr
1001 ldmia sp, {r0 - pc}^ @ Restore SVC registers
1004 __pabt_svc: sub sp, sp, #S_FRAME_SIZE
1005 stmia sp, {r0 - r12} @ save r0 - r12
1007 add r0, sp, #S_FRAME_SIZE
1008 ldmia r2, {r2 - r4} @ get pc, cpsr
1011 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
1012 mrs r9, cpsr @ Enable interrupts if they were
1014 biceq r9, r9, #PSR_I_BIT @ previously
1016 mov r0, r2 @ address (pc)
1018 bl do_PrefetchAbort @ call abort handler
1020 ldr r0, [sp, #S_PSR]
1022 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
1025 .LCirq: .word __temp_irq
1026 .LCund: .word __temp_und
1027 .LCabt: .word __temp_abt
1029 .LCprocfns: .word processor
1031 .LCfp: .word fp_enter
1032 #ifdef CONFIG_PREEMPT
1033 .LCirq_stat: .word irq_stat
1039 * User mode handlers
1042 __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1043 stmia sp, {r0 - r12} @ save r0 - r12
1046 ldmia r7, {r2 - r4} @ Get USR pc, cpsr
1047 stmia r5, {r2 - r4} @ Save USR pc, cpsr, old_r0
1049 alignment_trap r7, r7, __temp_abt
1052 ldr r4, .LCprocfns @ pass r2, r3 to
1053 mov lr, pc @ processor code
1054 ldr pc, [r4] @ call processor specific code
1056 bl CPU_ABORT_HANDLER
1058 enable_irq r2 @ Enable interrupts
1060 adrsvc al, lr, ret_from_exception
1064 __irq_usr: sub sp, sp, #S_FRAME_SIZE
1065 stmia sp, {r0 - r12} @ save r0 - r12
1068 ldmia r4, {r5 - r7} @ get saved PC, SPSR
1069 stmia r8, {r5 - r7} @ save pc, psr, old_r0
1071 alignment_trap r4, r7, __temp_irq
1073 #ifdef CONFIG_PREEMPT
1075 ldr r9, [r8, #TI_PREEMPT] @ get preempt count
1076 add r7, r9, #1 @ increment it
1077 str r7, [r8, #TI_PREEMPT]
1079 1: get_irqnr_and_base r0, r6, r5, lr
1083 @ routine called with r0 = irq number, r1 = struct pt_regs *
1086 #ifdef CONFIG_PREEMPT
1087 ldr r0, [r8, #TI_PREEMPT]
1089 str r9, [r8, #TI_PREEMPT]
1101 __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1102 stmia sp, {r0 - r12} @ Save r0 - r12
1106 stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
1107 stmdb r8, {sp, lr}^ @ Save user sp, lr
1108 alignment_trap r4, r7, __temp_und
1110 tst r6, #PSR_T_BIT @ Thumb mode?
1111 bne fpundefinstr @ ignore FP
1113 1: ldrt r0, [r4] @ r0 = instruction
1114 adrsvc al, r9, ret_from_exception @ r9 = normal FP return
1115 adrsvc al, lr, fpundefinstr @ lr = undefined instr return
1118 * The out of line fixup for the ldrt above.
1120 .section .fixup, "ax"
1123 .section __ex_table,"a"
1130 * Check whether the instruction is a co-processor instruction.
1131 * If yes, we need to call the relevant co-processor handler.
1133 * Note that we don't do a full check here for the co-processor
1134 * instructions; all instructions with bit 27 set are well
1135 * defined. The only instructions that should fault are the
1136 * co-processor instructions. However, we have to watch out
1137 * for the ARM6/ARM7 SWI bug.
1139 * Emulators may wish to make use of the following registers:
1140 * r0 - instruction opcode.
1141 * r10 - this threads thread_info structure.
1143 call_fpe: enable_irq r10 @ Enable interrupts
1144 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
1145 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
1146 and r8, r0, #0x0f000000 @ mask out op-code bits
1147 teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)?
1150 get_thread_info r10 @ get current thread
1151 and r8, r0, #0x00000f00 @ mask out CP number
1153 add r6, r10, #TI_USED_CP
1154 strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[]
1155 add pc, pc, r8, lsr #6
1159 b do_fpe @ CP#1 (FPE)
1160 b do_fpe @ CP#2 (FPE)
1168 mov pc, lr @ CP#10 (VFP)
1169 mov pc, lr @ CP#11 (VFP)
1172 mov pc, lr @ CP#14 (Debug)
1173 mov pc, lr @ CP#15 (Control)
1175 do_fpe: ldr r4, .LCfp
1176 add r10, r10, #TI_FPSTATE @ r10 = workspace
1177 ldr pc, [r4] @ Call FP module USR entry point
1180 * The FP module is called with these registers set:
1183 * r9 = normal "successful" return address
1184 * r10 = FP workspace
1185 * lr = unrecognised FP instruction return address
1193 fpundefinstr: mov r0, sp
1194 adrsvc al, lr, ret_from_exception
1198 __pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
1199 stmia sp, {r0 - r12} @ Save r0 - r12
1202 ldmia r4, {r5 - r7} @ Get USR pc, cpsr
1203 stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
1204 stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr
1205 alignment_trap r4, r7, __temp_abt
1207 enable_irq r0 @ Enable interrupts
1208 mov r0, r5 @ address (pc)
1210 bl do_PrefetchAbort @ call abort handler
1213 * This is the return code to user mode for abort handlers
1215 ENTRY(ret_from_exception)
1221 * Register switch for ARMv3 and ARMv4 processors
1222 * r0 = previous thread_info, r1 = next thread_info
1223 * previous and next are guaranteed not to be the same.
1226 add ip, r1, #TI_CPU_SAVE
1227 ldr r3, [r2, #TI_CPU_DOMAIN]!
1228 stmia ip, {r4 - sl, fp, sp, lr} @ Store most regs on stack
1229 mcr p15, 0, r3, c3, c0, 0 @ Set domain register
1230 ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
1234 * Vector stubs. NOTE that we only align 'vector_IRQ' to a cache line boundary,
1235 * and we rely on each stub being exactly 48 (1.5 cache lines) in size. This
1236 * means that we only ever load two cache lines for this code, or one if we're
1237 * lucky. We also copy this code to 0x200 so that we can use branches in the
1238 * vectors, rather than ldr's.
1243 * Interrupt dispatcher
1244 * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1247 @ save mode specific registers
1251 str lr, [r13] @ save lr_IRQ
1253 str lr, [r13, #4] @ save spsr_IRQ
1255 @ now branch to the relevant MODE handling routine
1258 bic r13, r13, #MODE_MASK
1259 orr r13, r13, #MODE_SVC
1260 msr spsr, r13 @ switch to SVC_32 mode
1263 ldr lr, [pc, lr, lsl #2]
1264 movs pc, lr @ Changes mode and branches
1266 .LCtab_irq: .word __irq_usr @ 0 (USR_26 / USR_32)
1267 .word __irq_invalid @ 1 (FIQ_26 / FIQ_32)
1268 .word __irq_invalid @ 2 (IRQ_26 / IRQ_32)
1269 .word __irq_svc @ 3 (SVC_26 / SVC_32)
1270 .word __irq_invalid @ 4
1271 .word __irq_invalid @ 5
1272 .word __irq_invalid @ 6
1273 .word __irq_invalid @ 7
1274 .word __irq_invalid @ 8
1275 .word __irq_invalid @ 9
1276 .word __irq_invalid @ a
1277 .word __irq_invalid @ b
1278 .word __irq_invalid @ c
1279 .word __irq_invalid @ d
1280 .word __irq_invalid @ e
1281 .word __irq_invalid @ f
1286 * Data abort dispatcher - dispatches it to the correct handler for the processor mode
1287 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1290 @ save mode specific registers
1298 @ now branch to the relevant MODE handling routine
1301 bic r13, r13, #MODE_MASK
1302 orr r13, r13, #MODE_SVC
1303 msr spsr, r13 @ switch to SVC_32 mode
1306 ldr lr, [pc, lr, lsl #2]
1307 movs pc, lr @ Changes mode and branches
1309 .LCtab_dabt: .word __dabt_usr @ 0 (USR_26 / USR_32)
1310 .word __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
1311 .word __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
1312 .word __dabt_svc @ 3 (SVC_26 / SVC_32)
1313 .word __dabt_invalid @ 4
1314 .word __dabt_invalid @ 5
1315 .word __dabt_invalid @ 6
1316 .word __dabt_invalid @ 7
1317 .word __dabt_invalid @ 8
1318 .word __dabt_invalid @ 9
1319 .word __dabt_invalid @ a
1320 .word __dabt_invalid @ b
1321 .word __dabt_invalid @ c
1322 .word __dabt_invalid @ d
1323 .word __dabt_invalid @ e
1324 .word __dabt_invalid @ f
1329 * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode
1330 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
1334 @ save mode specific registers
1338 str lr, [r13] @ save lr_ABT
1340 str lr, [r13, #4] @ save spsr_ABT
1342 @ now branch to the relevant MODE handling routine
1345 bic r13, r13, #MODE_MASK
1346 orr r13, r13, #MODE_SVC
1347 msr spsr, r13 @ switch to SVC_32 mode
1350 ldr lr, [pc, lr, lsl #2]
1353 .LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32)
1354 .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
1355 .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
1356 .word __pabt_svc @ 3 (SVC_26 / SVC_32)
1357 .word __pabt_invalid @ 4
1358 .word __pabt_invalid @ 5
1359 .word __pabt_invalid @ 6
1360 .word __pabt_invalid @ 7
1361 .word __pabt_invalid @ 8
1362 .word __pabt_invalid @ 9
1363 .word __pabt_invalid @ a
1364 .word __pabt_invalid @ b
1365 .word __pabt_invalid @ c
1366 .word __pabt_invalid @ d
1367 .word __pabt_invalid @ e
1368 .word __pabt_invalid @ f
1373 * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode
1374 * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
1378 @ save mode specific registers
1381 str lr, [r13] @ save lr_UND
1383 str lr, [r13, #4] @ save spsr_UND
1385 @ now branch to the relevant MODE handling routine
1388 bic r13, r13, #MODE_MASK
1389 orr r13, r13, #MODE_SVC
1390 msr spsr, r13 @ switch to SVC_32 mode
1393 ldr lr, [pc, lr, lsl #2]
1394 movs pc, lr @ Changes mode and branches
1396 .LCtab_und: .word __und_usr @ 0 (USR_26 / USR_32)
1397 .word __und_invalid @ 1 (FIQ_26 / FIQ_32)
1398 .word __und_invalid @ 2 (IRQ_26 / IRQ_32)
1399 .word __und_svc @ 3 (SVC_26 / SVC_32)
1400 .word __und_invalid @ 4
1401 .word __und_invalid @ 5
1402 .word __und_invalid @ 6
1403 .word __und_invalid @ 7
1404 .word __und_invalid @ 8
1405 .word __und_invalid @ 9
1406 .word __und_invalid @ a
1407 .word __und_invalid @ b
1408 .word __und_invalid @ c
1409 .word __und_invalid @ d
1410 .word __und_invalid @ e
1411 .word __und_invalid @ f
1415 /*=============================================================================
1417 *-----------------------------------------------------------------------------
1418 * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
1419 * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
1420 * Basically to switch modes, we *HAVE* to clobber one register... brain
1421 * damage alert! I don't think that we can execute any code in here in any
1422 * other mode than FIQ... Ok you can switch to another mode, but you can't
1423 * get out of that mode without clobbering one register.
1425 vector_FIQ: disable_fiq
1428 /*=============================================================================
1429 * Address exception handler
1430 *-----------------------------------------------------------------------------
1431 * These aren't too critical.
1432 * (they're not supposed to happen, and won't happen in 32-bit data mode).
1439 * We group all the following data together to optimise
1440 * for CPUs with separate I & D caches.
1444 .LCvswi: .word vector_swi
1446 .LCsirq: .word __temp_irq
1447 .LCsund: .word __temp_und
1448 .LCsabt: .word __temp_abt
1452 .equ __real_stubs_start, .LCvectors + 0x200
1454 .LCvectors: swi SYS_ERROR0
1455 b __real_stubs_start + (vector_undefinstr - __stubs_start)
1456 ldr pc, __real_stubs_start + (.LCvswi - __stubs_start)
1457 b __real_stubs_start + (vector_prefetch - __stubs_start)
1458 b __real_stubs_start + (vector_data - __stubs_start)
1459 b __real_stubs_start + (vector_addrexcptn - __stubs_start)
1460 b __real_stubs_start + (vector_IRQ - __stubs_start)
1461 b __real_stubs_start + (vector_FIQ - __stubs_start)
1464 stmfd sp!, {r4 - r6, lr}
1466 adr r1, .LCvectors @ set up the vectors
1467 ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr}
1468 stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr}
1471 adr r0, __stubs_start @ copy stubs to 0x200
1477 LOADREGS(fd, sp!, {r4 - r6, pc})
1482 * Do not reorder these, and do not insert extra data between...
1485 __temp_irq: .word 0 @ saved lr_irq
1486 .word 0 @ saved spsr_irq
1488 __temp_und: .word 0 @ Saved lr_und
1489 .word 0 @ Saved spsr_und
1491 __temp_abt: .word 0 @ Saved lr_abt
1492 .word 0 @ Saved spsr_abt
1496 .globl cr_no_alignment