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