Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | /* * include/asm-v850/v850e_intc.h -- V850E CPU interrupt controller (INTC) * * Copyright (C) 2001,02,03 NEC Electronics Corporation * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this * archive for more details. * * Written by Miles Bader <miles@gnu.org> */ #ifndef __V850_V850E_INTC_H__ #define __V850_V850E_INTC_H__ /* There are 4 16-bit `Interrupt Mask Registers' located contiguously starting from this base. Each interrupt uses a single bit to indicated enabled/disabled status. */ #define V850E_INTC_IMR_BASE_ADDR 0xFFFFF100 #define V850E_INTC_IMR_ADDR(irq) (V850E_INTC_IMR_BASE_ADDR + ((irq) >> 3)) #define V850E_INTC_IMR_BIT(irq) ((irq) & 0x7) /* Each maskable interrupt has a single-byte control register at this address. */ #define V850E_INTC_IC_BASE_ADDR 0xFFFFF110 #define V850E_INTC_IC_ADDR(irq) (V850E_INTC_IC_BASE_ADDR + ((irq) << 1)) #define V850E_INTC_IC(irq) (*(volatile u8 *)V850E_INTC_IC_ADDR(irq)) /* Encode priority PR for storing in an interrupt control register. */ #define V850E_INTC_IC_PR(pr) (pr) /* Interrupt disable bit in an interrupt control register. */ #define V850E_INTC_IC_MK_BIT 6 #define V850E_INTC_IC_MK (1 << V850E_INTC_IC_MK_BIT) /* Interrupt pending flag in an interrupt control register. */ #define V850E_INTC_IC_IF_BIT 7 #define V850E_INTC_IC_IF (1 << V850E_INTC_IC_IF_BIT) /* The ISPR (In-service priority register) contains one bit for each interrupt priority level, which is set to one when that level is currently being serviced (and thus blocking any interrupts of equal or lesser level). */ #define V850E_INTC_ISPR_ADDR 0xFFFFF1FA #define V850E_INTC_ISPR (*(volatile u8 *)V850E_INTC_ISPR_ADDR) #ifndef __ASSEMBLY__ /* Enable interrupt handling for interrupt IRQ. */ static inline void v850e_intc_enable_irq (unsigned irq) { __asm__ __volatile__ ("clr1 %0, [%1]" :: "r" (V850E_INTC_IMR_BIT (irq)), "r" (V850E_INTC_IMR_ADDR (irq)) : "memory"); } /* Disable interrupt handling for interrupt IRQ. Note that any interrupts received while disabled will be delivered once the interrupt is enabled again, unless they are explicitly cleared using `v850e_intc_clear_pending_irq'. */ static inline void v850e_intc_disable_irq (unsigned irq) { __asm__ __volatile__ ("set1 %0, [%1]" :: "r" (V850E_INTC_IMR_BIT (irq)), "r" (V850E_INTC_IMR_ADDR (irq)) : "memory"); } /* Return true if interrupt handling for interrupt IRQ is enabled. */ static inline int v850e_intc_irq_enabled (unsigned irq) { int rval; __asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0" : "=r" (rval) : "r" (V850E_INTC_IMR_BIT (irq)), "r" (V850E_INTC_IMR_ADDR (irq))); return rval; } /* Disable irqs from 0 until LIMIT. LIMIT must be a multiple of 8. */ static inline void _v850e_intc_disable_irqs (unsigned limit) { unsigned long addr; for (addr = V850E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8) *(char *)addr = 0xFF; } /* Disable all irqs. This is purposely a macro, because NUM_MACH_IRQS will be only be defined later. */ #define v850e_intc_disable_irqs() _v850e_intc_disable_irqs (NUM_MACH_IRQS) /* Clear any pending interrupts for IRQ. */ static inline void v850e_intc_clear_pending_irq (unsigned irq) { __asm__ __volatile__ ("clr1 %0, 0[%1]" :: "i" (V850E_INTC_IC_IF_BIT), "r" (V850E_INTC_IC_ADDR (irq)) : "memory"); } /* Return true if interrupt IRQ is pending (but disabled). */ static inline int v850e_intc_irq_pending (unsigned irq) { int rval; __asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0" : "=r" (rval) : "i" (V850E_INTC_IC_IF_BIT), "r" (V850E_INTC_IC_ADDR (irq))); return rval; } struct v850e_intc_irq_init { const char *name; /* name of interrupt type */ /* Range of kernel irq numbers for this type: BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM */ unsigned base, num, interval; unsigned priority; /* interrupt priority to assign */ }; struct hw_interrupt_type; /* fwd decl */ /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array INITS (which is terminated by an entry with the name field == 0). */ extern void v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits, struct hw_interrupt_type *hw_irq_types); #endif /* !__ASSEMBLY__ */ #endif /* __V850_V850E_INTC_H__ */ |