2 * linux/arch/h8300/platform/h8s/ints.c
4 * Yoshinori Sato <ysato@users.sourceforge.jp>
6 * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive
12 * Copyright 1996 Roman Zippel
13 * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/sched.h>
20 #include <linux/kernel_stat.h>
21 #include <linux/seq_file.h>
22 #include <linux/init.h>
23 #include <linux/bootmem.h>
24 #include <linux/random.h>
25 #include <linux/hardirq.h>
27 #include <asm/system.h>
29 #include <asm/traps.h>
31 #include <asm/setup.h>
33 #include <asm/regs267x.h>
34 #include <asm/errno.h>
37 * This structure has only 4 elements for speed reasons
39 typedef struct irq_handler
{
40 irqreturn_t (*handler
)(int, void *, struct pt_regs
*);
47 static irq_handler_t
*irq_list
[NR_IRQS
];
49 /* IRQ pin assignment */
51 unsigned char port_no
;
55 const static struct irq_pins irq_assign_table0
[16]={
56 {H8300_GPIO_P5
,H8300_GPIO_B0
},{H8300_GPIO_P5
,H8300_GPIO_B1
},
57 {H8300_GPIO_P5
,H8300_GPIO_B2
},{H8300_GPIO_P5
,H8300_GPIO_B3
},
58 {H8300_GPIO_P5
,H8300_GPIO_B4
},{H8300_GPIO_P5
,H8300_GPIO_B5
},
59 {H8300_GPIO_P5
,H8300_GPIO_B6
},{H8300_GPIO_P5
,H8300_GPIO_B7
},
60 {H8300_GPIO_P6
,H8300_GPIO_B0
},{H8300_GPIO_P6
,H8300_GPIO_B1
},
61 {H8300_GPIO_P6
,H8300_GPIO_B2
},{H8300_GPIO_P6
,H8300_GPIO_B3
},
62 {H8300_GPIO_P6
,H8300_GPIO_B4
},{H8300_GPIO_P6
,H8300_GPIO_B5
},
63 {H8300_GPIO_PF
,H8300_GPIO_B1
},{H8300_GPIO_PF
,H8300_GPIO_B2
},
66 const static struct irq_pins irq_assign_table1
[16]={
67 {H8300_GPIO_P8
,H8300_GPIO_B0
},{H8300_GPIO_P8
,H8300_GPIO_B1
},
68 {H8300_GPIO_P8
,H8300_GPIO_B2
},{H8300_GPIO_P8
,H8300_GPIO_B3
},
69 {H8300_GPIO_P8
,H8300_GPIO_B4
},{H8300_GPIO_P8
,H8300_GPIO_B5
},
70 {H8300_GPIO_PH
,H8300_GPIO_B2
},{H8300_GPIO_PH
,H8300_GPIO_B3
},
71 {H8300_GPIO_P2
,H8300_GPIO_B0
},{H8300_GPIO_P2
,H8300_GPIO_B1
},
72 {H8300_GPIO_P2
,H8300_GPIO_B2
},{H8300_GPIO_P2
,H8300_GPIO_B3
},
73 {H8300_GPIO_P2
,H8300_GPIO_B4
},{H8300_GPIO_P2
,H8300_GPIO_B5
},
74 {H8300_GPIO_P2
,H8300_GPIO_B6
},{H8300_GPIO_P2
,H8300_GPIO_B7
},
77 static short use_kmalloc
= 0;
79 extern unsigned long *interrupt_redirect_table
;
81 #define CPU_VECTOR ((unsigned long *)0x000000)
82 #define ADDR_MASK (0xffffff)
84 static inline unsigned long *get_vector_address(void)
86 volatile unsigned long *rom_vector
= CPU_VECTOR
;
87 unsigned long base
,tmp
;
90 base
= rom_vector
[EXT_IRQ0
] & ADDR_MASK
;
92 /* check romvector format */
93 for (vec_no
= EXT_IRQ1
; vec_no
<= EXT_IRQ15
; vec_no
++) {
94 if ((base
+(vec_no
- EXT_IRQ0
)*4) != (rom_vector
[vec_no
] & ADDR_MASK
))
98 /* ramvector base address */
101 /* writerble check */
102 tmp
= ~(*(unsigned long *)base
);
103 (*(unsigned long *)base
) = tmp
;
104 if ((*(unsigned long *)base
) != tmp
)
106 return (unsigned long *)base
;
109 void __init
init_IRQ(void)
111 #if defined(CONFIG_RAMKERNEL)
113 unsigned long *ramvec
,*ramvec_p
;
114 unsigned long break_vec
;
116 ramvec
= get_vector_address();
118 panic("interrupt vector serup failed.");
120 printk("virtual vector at 0x%08lx\n",(unsigned long)ramvec
);
122 #if defined(CONFIG_GDB_DEBUG)
123 /* save orignal break vector */
124 break_vec
= ramvec
[TRAP3_VEC
];
126 break_vec
= VECTOR(trace_break
);
129 /* create redirect table */
130 for (ramvec_p
= ramvec
, i
= 0; i
< NR_IRQS
; i
++)
131 *ramvec_p
++ = REDIRECT(interrupt_entry
);
133 /* set special vector */
134 ramvec
[TRAP0_VEC
] = VECTOR(system_call
);
135 ramvec
[TRAP3_VEC
] = break_vec
;
136 interrupt_redirect_table
= ramvec
;
139 for (i
= 0; i
< NR_IRQS
; i
++) {
141 printk("\n%p: ",ramvec_p
);
142 printk("%p ",*ramvec_p
);
150 int request_irq(unsigned int irq
,
151 irqreturn_t (*handler
)(int, void *, struct pt_regs
*),
152 unsigned long flags
, const char *devname
, void *dev_id
)
154 unsigned short ptn
= 1 << (irq
- EXT_IRQ0
);
155 irq_handler_t
*irq_handle
;
156 if (irq
< 0 || irq
>= NR_IRQS
) {
157 printk("Incorrect IRQ %d from %s\n", irq
, devname
);
161 return -EBUSY
; /* already used */
162 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
) {
163 /* initialize IRQ pin */
164 unsigned int port_no
,bit_no
;
165 if (*(volatile unsigned short *)ITSR
& ptn
) {
166 port_no
= irq_assign_table1
[irq
- EXT_IRQ0
].port_no
;
167 bit_no
= irq_assign_table1
[irq
- EXT_IRQ0
].bit_no
;
169 port_no
= irq_assign_table0
[irq
- EXT_IRQ0
].port_no
;
170 bit_no
= irq_assign_table0
[irq
- EXT_IRQ0
].bit_no
;
172 if (H8300_GPIO_RESERVE(port_no
, bit_no
) == 0)
173 return -EBUSY
; /* pin already use */
174 H8300_GPIO_DDR(port_no
, bit_no
, H8300_GPIO_INPUT
);
175 *(volatile unsigned short *)ISR
&= ~ptn
; /* ISR clear */
179 irq_handle
= (irq_handler_t
*)kmalloc(sizeof(irq_handler_t
), GFP_ATOMIC
);
181 /* use bootmem allocater */
182 irq_handle
= (irq_handler_t
*)alloc_bootmem(sizeof(irq_handler_t
));
183 irq_handle
= (irq_handler_t
*)((unsigned long)irq_handle
| 0x80000000);
186 if (irq_handle
== NULL
)
189 irq_handle
->handler
= handler
;
190 irq_handle
->flags
= flags
;
191 irq_handle
->count
= 0;
192 irq_handle
->dev_id
= dev_id
;
193 irq_handle
->devname
= devname
;
194 irq_list
[irq
] = irq_handle
;
195 if (irq_handle
->flags
& SA_SAMPLE_RANDOM
)
196 rand_initialize_irq(irq
);
198 /* enable interrupt */
199 /* compatible i386 */
200 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
)
201 *(volatile unsigned short *)IER
|= ptn
;
205 EXPORT_SYMBOL(request_irq
);
207 void free_irq(unsigned int irq
, void *dev_id
)
211 if (irq_list
[irq
]->dev_id
!= dev_id
)
212 printk("%s: Removing probably wrong IRQ %d from %s\n",
213 __FUNCTION__
, irq
, irq_list
[irq
]->devname
);
214 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
) {
215 /* disable interrupt & release IRQ pin */
216 unsigned short port_no
,bit_no
;
217 *(volatile unsigned short *)ISR
&= ~(1 << (irq
- EXT_IRQ0
));
218 *(volatile unsigned short *)IER
|= 1 << (irq
- EXT_IRQ0
);
219 if (*(volatile unsigned short *)ITSR
& (1 << (irq
- EXT_IRQ0
))) {
220 port_no
= irq_assign_table1
[irq
- EXT_IRQ0
].port_no
;
221 bit_no
= irq_assign_table1
[irq
- EXT_IRQ0
].bit_no
;
223 port_no
= irq_assign_table0
[irq
- EXT_IRQ0
].port_no
;
224 bit_no
= irq_assign_table0
[irq
- EXT_IRQ0
].bit_no
;
226 H8300_GPIO_FREE(port_no
, bit_no
);
228 if (((unsigned long)irq_list
[irq
] & 0x80000000) == 0) {
229 kfree(irq_list
[irq
]);
230 irq_list
[irq
] = NULL
;
234 EXPORT_SYMBOL(free_irq
);
236 unsigned long probe_irq_on (void)
241 EXPORT_SYMBOL(probe_irq_on
);
243 int probe_irq_off (unsigned long irqs
)
248 EXPORT_SYMBOL(probe_irq_off
);
250 void enable_irq(unsigned int irq
)
252 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
)
253 *(volatile unsigned short *)IER
|= 1 << (irq
- EXT_IRQ0
);
256 void disable_irq(unsigned int irq
)
258 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
)
259 *(volatile unsigned short *)IER
&= ~(1 << (irq
- EXT_IRQ0
));
262 asmlinkage
void process_int(unsigned long vec
, struct pt_regs
*fp
)
266 /* compatible i386 */
267 if (vec
>= EXT_IRQ0
&& vec
<= EXT_IRQ15
)
268 *(volatile unsigned short *)ISR
&= ~(1 << (vec
- EXT_IRQ0
));
271 irq_list
[vec
]->handler(vec
, irq_list
[vec
]->dev_id
, fp
);
272 irq_list
[vec
]->count
++;
273 if (irq_list
[vec
]->flags
& SA_SAMPLE_RANDOM
)
274 add_interrupt_randomness(vec
);
282 int show_interrupts(struct seq_file
*p
, void *v
)
284 int i
= *(loff_t
*) v
;
286 if ((i
< NR_IRQS
) && (irq_list
[i
] !=NULL
)) {
287 seq_printf(p
, "%3d: %10u ",i
,irq_list
[i
]->count
);
288 seq_printf(p
, "%s\n", irq_list
[i
]->devname
);
294 void init_irq_proc(void)
298 static int __init
enable_kmalloc(void)
303 core_initcall(enable_kmalloc
);