linux/arch/cris/include/arch-v10/arch/irq.h
<<
>>
Prefs
   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 <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);
  78void set_break_vector(int n, irqvectptr addr);
  79
  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
  97 * crisv10_mask_irq and crisv10_unmask_irq */
  98
  99#define BLOCK_IRQ(mask,nr) \
 100  "move.d " #mask ",$r0\n\t" \
 101  "move.d $r0,[0xb00000d8]\n\t"
 102
 103#define UNBLOCK_IRQ(mask) \
 104  "move.d " #mask ",$r0\n\t" \
 105  "move.d $r0,[0xb00000dc]\n\t"
 106
 107#define IRQ_NAME2(nr) nr##_interrupt(void)
 108#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
 109#define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr)
 110#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
 111
 112  /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls
 113   * do_IRQ (with irq disabled still). after that it unblocks and jumps to
 114   * ret_from_intr (entry.S)
 115   *
 116   * The reason the IRQ is blocked is to allow an sti() before the handler which
 117   * will acknowledge the interrupt is run.
 118   */
 119
 120#define BUILD_IRQ(nr,mask) \
 121void IRQ_NAME(nr); \
 122__asm__ ( \
 123          ".text\n\t" \
 124          "IRQ" #nr "_interrupt:\n\t" \
 125          SAVE_ALL \
 126          BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \
 127          "moveq "#nr",$r10\n\t" \
 128          "move.d $sp,$r11\n\t" \
 129          "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
 130          UNBLOCK_IRQ(mask) \
 131          "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
 132          "jump ret_from_intr\n\t");
 133
 134/* This is subtle. The timer interrupt is crucial and it should not be disabled for 
 135 * too long. However, if it had been a normal interrupt as per BUILD_IRQ, it would
 136 * have been BLOCK'ed, and then softirq's are run before we return here to UNBLOCK.
 137 * If the softirq's take too much time to run, the timer irq won't run and the 
 138 * watchdog will kill us.
 139 *
 140 * Furthermore, if a lot of other irq's occur before we return here, the multiple_irq
 141 * handler is run and it prioritizes the timer interrupt. However if we had BLOCK'ed
 142 * it here, we would not get the multiple_irq at all.
 143 *
 144 * The non-blocking here is based on the knowledge that the timer interrupt is 
 145 * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not
 146 * be an sti() before the timer irq handler is run to acknowledge the interrupt.
 147 */
 148
 149#define BUILD_TIMER_IRQ(nr,mask) \
 150void IRQ_NAME(nr); \
 151__asm__ ( \
 152          ".text\n\t" \
 153          "IRQ" #nr "_interrupt:\n\t" \
 154          SAVE_ALL \
 155          "moveq "#nr",$r10\n\t" \
 156          "move.d $sp,$r11\n\t" \
 157          "jsr do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
 158          "moveq 0,$r9\n\t" /* make ret_from_intr realise we came from an irq */ \
 159          "jump ret_from_intr\n\t");
 160
 161#endif
 162