Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | |
| 70 | typedef void (*irqvectptr)(void); |
| 71 | |
| 72 | struct etrax_interrupt_vector { |
| 73 | irqvectptr v[256]; |
| 74 | }; |
| 75 | |
| 76 | extern struct etrax_interrupt_vector *etrax_irv; |
Mikael Starvik | 2e0cea1 | 2005-07-27 11:44:36 -0700 | [diff] [blame] | 77 | void set_int_vector(int n, irqvectptr addr); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 | void set_break_vector(int n, irqvectptr addr); |
| 79 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 | #define __STR(x) #x |
| 81 | #define STR(x) __STR(x) |
| 82 | |
| 83 | /* SAVE_ALL saves registers so they match pt_regs */ |
| 84 | |
| 85 | #define SAVE_ALL \ |
| 86 | "move $irp,[$sp=$sp-16]\n\t" /* push instruction pointer and fake SBFS struct */ \ |
| 87 | "push $srp\n\t" /* push subroutine return pointer */ \ |
| 88 | "push $dccr\n\t" /* push condition codes */ \ |
| 89 | "push $mof\n\t" /* push multiply overflow reg */ \ |
| 90 | "di\n\t" /* need to disable irq's at this point */\ |
| 91 | "subq 14*4,$sp\n\t" /* make room for r0-r13 */ \ |
| 92 | "movem $r13,[$sp]\n\t" /* push the r0-r13 registers */ \ |
| 93 | "push $r10\n\t" /* push orig_r10 */ \ |
| 94 | "clear.d [$sp=$sp-4]\n\t" /* frametype - this is a normal stackframe */ |
| 95 | |
| 96 | /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq */ |
| 97 | |
| 98 | #define BLOCK_IRQ(mask,nr) \ |
| 99 | "move.d " #mask ",$r0\n\t" \ |
| 100 | "move.d $r0,[0xb00000d8]\n\t" |
| 101 | |
| 102 | #define UNBLOCK_IRQ(mask) \ |
| 103 | "move.d " #mask ",$r0\n\t" \ |
| 104 | "move.d $r0,[0xb00000dc]\n\t" |
| 105 | |
| 106 | #define IRQ_NAME2(nr) nr##_interrupt(void) |
| 107 | #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) |
| 108 | #define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr) |
| 109 | #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) |
| 110 | |
| 111 | /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls |
| 112 | * do_IRQ (with irq disabled still). after that it unblocks and jumps to |
| 113 | * ret_from_intr (entry.S) |
| 114 | * |
| 115 | * The reason the IRQ is blocked is to allow an sti() before the handler which |
| 116 | * will acknowledge the interrupt is run. |
| 117 | */ |
| 118 | |
| 119 | #define BUILD_IRQ(nr,mask) \ |
| 120 | void IRQ_NAME(nr); \ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 121 | __asm__ ( \ |
| 122 | ".text\n\t" \ |
| 123 | "IRQ" #nr "_interrupt:\n\t" \ |
| 124 | SAVE_ALL \ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 125 | BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \ |
| 126 | "moveq "#nr",$r10\n\t" \ |
| 127 | "move.d $sp,$r11\n\t" \ |
| 128 | "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \ |
| 129 | UNBLOCK_IRQ(mask) \ |
| 130 | "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \ |
Mikael Starvik | 2e0cea1 | 2005-07-27 11:44:36 -0700 | [diff] [blame] | 131 | "jump ret_from_intr\n\t"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | |
| 133 | /* This is subtle. The timer interrupt is crucial and it should not be disabled for |
| 134 | * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would |
| 135 | * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK. |
| 136 | * If the softirq's take too much time to run, the timer irq won't run and the |
| 137 | * watchdog will kill us. |
| 138 | * |
| 139 | * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq |
| 140 | * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed |
| 141 | * it here, we would not get the multiple_irq at all. |
| 142 | * |
| 143 | * The non-blocking here is based on the knowledge that the timer interrupt is |
Thomas Gleixner | aa7135f | 2006-07-01 19:29:14 -0700 | [diff] [blame] | 144 | * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 145 | * be an sti() before the timer irq handler is run to acknowledge the interrupt. |
| 146 | */ |
| 147 | |
| 148 | #define BUILD_TIMER_IRQ(nr,mask) \ |
| 149 | void IRQ_NAME(nr); \ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 150 | __asm__ ( \ |
| 151 | ".text\n\t" \ |
| 152 | "IRQ" #nr "_interrupt:\n\t" \ |
| 153 | SAVE_ALL \ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 154 | "moveq "#nr",$r10\n\t" \ |
| 155 | "move.d $sp,$r11\n\t" \ |
| 156 | "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \ |
| 157 | "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \ |
Mikael Starvik | 2e0cea1 | 2005-07-27 11:44:36 -0700 | [diff] [blame] | 158 | "jump ret_from_intr\n\t"); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 159 | |
| 160 | #endif |