]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 LT |
2 | /* |
3 | * Interrupt handling assembler and defines for Linux/CRISv10 | |
4 | */ | |
5 | ||
6 | #ifndef _ASM_ARCH_IRQ_H | |
7 | #define _ASM_ARCH_IRQ_H | |
8 | ||
556dcee7 | 9 | #include <arch/sv_addr_ag.h> |
1da177e4 LT |
10 | |
11 | #define NR_IRQS 32 | |
12 | ||
13 | /* The first vector number used for IRQs in v10 is really 0x20 */ | |
14 | /* but all the code and constants are offseted to make 0 the first */ | |
15 | #define FIRST_IRQ 0 | |
16 | ||
17 | #define SOME_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, some) /* 0 ? */ | |
18 | #define NMI_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, nmi) /* 1 */ | |
19 | #define TIMER0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer0) /* 2 */ | |
20 | #define TIMER1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, timer1) /* 3 */ | |
21 | /* mio, ata, par0, scsi0 on 4 */ | |
22 | /* par1, scsi1 on 5 */ | |
23 | #define NETWORK_STATUS_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, network) /* 6 */ | |
24 | ||
25 | #define SERIAL_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, serial) /* 8 */ | |
26 | #define PA_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, pa) /* 11 */ | |
27 | /* extdma0 and extdma1 is at irq 12 and 13 and/or same as dma5 and dma6 ? */ | |
28 | #define EXTDMA0_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma0) | |
29 | #define EXTDMA1_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, ext_dma1) | |
30 | ||
31 | /* dma0-9 is irq 16..25 */ | |
32 | /* 16,17: network */ | |
33 | #define DMA0_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma0) | |
34 | #define DMA1_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma1) | |
35 | #define NETWORK_DMA_TX_IRQ_NBR DMA0_TX_IRQ_NBR | |
36 | #define NETWORK_DMA_RX_IRQ_NBR DMA1_RX_IRQ_NBR | |
37 | ||
38 | /* 18,19: dma2 and dma3 shared by par0, scsi0, ser2 and ata */ | |
39 | #define DMA2_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma2) | |
40 | #define DMA3_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma3) | |
41 | #define SER2_DMA_TX_IRQ_NBR DMA2_TX_IRQ_NBR | |
42 | #define SER2_DMA_RX_IRQ_NBR DMA3_RX_IRQ_NBR | |
43 | ||
44 | /* 20,21: dma4 and dma5 shared by par1, scsi1, ser3 and extdma0 */ | |
45 | #define DMA4_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma4) | |
46 | #define DMA5_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma5) | |
47 | #define SER3_DMA_TX_IRQ_NBR DMA4_TX_IRQ_NBR | |
48 | #define SER3_DMA_RX_IRQ_NBR DMA5_RX_IRQ_NBR | |
49 | ||
50 | /* 22,23: dma6 and dma7 shared by ser0, extdma1 and mem2mem */ | |
51 | #define DMA6_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma6) | |
52 | #define DMA7_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma7) | |
53 | #define SER0_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR | |
54 | #define SER0_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR | |
55 | #define MEM2MEM_DMA_TX_IRQ_NBR DMA6_TX_IRQ_NBR | |
56 | #define MEM2MEM_DMA_RX_IRQ_NBR DMA7_RX_IRQ_NBR | |
57 | ||
58 | /* 24,25: dma8 and dma9 shared by ser1 and usb */ | |
59 | #define DMA8_TX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma8) | |
60 | #define DMA9_RX_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, dma9) | |
61 | #define SER1_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR | |
62 | #define SER1_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR | |
63 | #define USB_DMA_TX_IRQ_NBR DMA8_TX_IRQ_NBR | |
64 | #define USB_DMA_RX_IRQ_NBR DMA9_RX_IRQ_NBR | |
65 | ||
66 | /* usb: controller at irq 31 + uses DMA8 and DMA9 */ | |
67 | #define USB_HC_IRQ_NBR IO_BITNR(R_VECT_MASK_RD, usb) | |
68 | ||
69 | /* our fine, global, etrax irq vector! the pointer lives in the head.S file. */ | |
70 | ||
71 | typedef void (*irqvectptr)(void); | |
72 | ||
73 | struct etrax_interrupt_vector { | |
74 | irqvectptr v[256]; | |
75 | }; | |
76 | ||
77 | extern struct etrax_interrupt_vector *etrax_irv; | |
2e0cea1d | 78 | void set_int_vector(int n, irqvectptr addr); |
1da177e4 LT |
79 | void set_break_vector(int n, irqvectptr addr); |
80 | ||
1da177e4 LT |
81 | #define __STR(x) #x |
82 | #define STR(x) __STR(x) | |
83 | ||
84 | /* SAVE_ALL saves registers so they match pt_regs */ | |
85 | ||
86 | #define SAVE_ALL \ | |
87 | "move $irp,[$sp=$sp-16]\n\t" /* push instruction pointer and fake SBFS struct */ \ | |
88 | "push $srp\n\t" /* push subroutine return pointer */ \ | |
89 | "push $dccr\n\t" /* push condition codes */ \ | |
90 | "push $mof\n\t" /* push multiply overflow reg */ \ | |
91 | "di\n\t" /* need to disable irq's at this point */\ | |
92 | "subq 14*4,$sp\n\t" /* make room for r0-r13 */ \ | |
93 | "movem $r13,[$sp]\n\t" /* push the r0-r13 registers */ \ | |
94 | "push $r10\n\t" /* push orig_r10 */ \ | |
95 | "clear.d [$sp=$sp-4]\n\t" /* frametype - this is a normal stackframe */ | |
96 | ||
4150764f JN |
97 | /* BLOCK_IRQ and UNBLOCK_IRQ do the same as |
98 | * crisv10_mask_irq and crisv10_unmask_irq */ | |
1da177e4 LT |
99 | |
100 | #define BLOCK_IRQ(mask,nr) \ | |
101 | "move.d " #mask ",$r0\n\t" \ | |
4150764f JN |
102 | "move.d $r0,[0xb00000d8]\n\t" |
103 | ||
1da177e4 LT |
104 | #define UNBLOCK_IRQ(mask) \ |
105 | "move.d " #mask ",$r0\n\t" \ | |
4150764f | 106 | "move.d $r0,[0xb00000dc]\n\t" |
1da177e4 LT |
107 | |
108 | #define IRQ_NAME2(nr) nr##_interrupt(void) | |
109 | #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) | |
110 | #define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr) | |
111 | #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) | |
112 | ||
113 | /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls | |
114 | * do_IRQ (with irq disabled still). after that it unblocks and jumps to | |
115 | * ret_from_intr (entry.S) | |
116 | * | |
117 | * The reason the IRQ is blocked is to allow an sti() before the handler which | |
118 | * will acknowledge the interrupt is run. | |
119 | */ | |
120 | ||
121 | #define BUILD_IRQ(nr,mask) \ | |
122 | void IRQ_NAME(nr); \ | |
1da177e4 LT |
123 | __asm__ ( \ |
124 | ".text\n\t" \ | |
125 | "IRQ" #nr "_interrupt:\n\t" \ | |
126 | SAVE_ALL \ | |
1da177e4 LT |
127 | BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \ |
128 | "moveq "#nr",$r10\n\t" \ | |
129 | "move.d $sp,$r11\n\t" \ | |
130 | "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \ | |
131 | UNBLOCK_IRQ(mask) \ | |
132 | "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \ | |
2e0cea1d | 133 | "jump ret_from_intr\n\t"); |
1da177e4 LT |
134 | |
135 | /* This is subtle. The timer interrupt is crucial and it should not be disabled for | |
136 | * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would | |
137 | * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK. | |
138 | * If the softirq's take too much time to run, the timer irq won't run and the | |
139 | * watchdog will kill us. | |
140 | * | |
141 | * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq | |
142 | * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed | |
143 | * it here, we would not get the multiple_irq at all. | |
144 | * | |
64d8ad93 MO |
145 | * The non-blocking here is based on the knowledge that the timer interrupt runs |
146 | * with interrupts disabled, and therefore there will not be an sti() before the | |
147 | * timer irq handler is run to acknowledge the interrupt. | |
1da177e4 LT |
148 | */ |
149 | ||
150 | #define BUILD_TIMER_IRQ(nr,mask) \ | |
151 | void IRQ_NAME(nr); \ | |
1da177e4 LT |
152 | __asm__ ( \ |
153 | ".text\n\t" \ | |
154 | "IRQ" #nr "_interrupt:\n\t" \ | |
155 | SAVE_ALL \ | |
1da177e4 LT |
156 | "moveq "#nr",$r10\n\t" \ |
157 | "move.d $sp,$r11\n\t" \ | |
158 | "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \ | |
159 | "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \ | |
2e0cea1d | 160 | "jump ret_from_intr\n\t"); |
1da177e4 LT |
161 | |
162 | #endif |