Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / include / asm-v850 / v850e_intc.h
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__ */