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