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/interrupt.h>
24 #include <linux/bootmem.h>
25 #include <linux/random.h>
26 #include <linux/hardirq.h>
28 #include <asm/system.h>
30 #include <asm/traps.h>
32 #include <asm/setup.h>
34 #include <asm/regs267x.h>
35 #include <asm/errno.h>
38 * This structure has only 4 elements for speed reasons
40 typedef struct irq_handler
{
41 irqreturn_t (*handler
)(int, void *, struct pt_regs
*);
48 static irq_handler_t
*irq_list
[NR_IRQS
];
50 /* IRQ pin assignment */
52 unsigned char port_no
;
56 static const struct irq_pins irq_assign_table0
[16]={
57 {H8300_GPIO_P5
,H8300_GPIO_B0
},{H8300_GPIO_P5
,H8300_GPIO_B1
},
58 {H8300_GPIO_P5
,H8300_GPIO_B2
},{H8300_GPIO_P5
,H8300_GPIO_B3
},
59 {H8300_GPIO_P5
,H8300_GPIO_B4
},{H8300_GPIO_P5
,H8300_GPIO_B5
},
60 {H8300_GPIO_P5
,H8300_GPIO_B6
},{H8300_GPIO_P5
,H8300_GPIO_B7
},
61 {H8300_GPIO_P6
,H8300_GPIO_B0
},{H8300_GPIO_P6
,H8300_GPIO_B1
},
62 {H8300_GPIO_P6
,H8300_GPIO_B2
},{H8300_GPIO_P6
,H8300_GPIO_B3
},
63 {H8300_GPIO_P6
,H8300_GPIO_B4
},{H8300_GPIO_P6
,H8300_GPIO_B5
},
64 {H8300_GPIO_PF
,H8300_GPIO_B1
},{H8300_GPIO_PF
,H8300_GPIO_B2
},
67 static const struct irq_pins irq_assign_table1
[16]={
68 {H8300_GPIO_P8
,H8300_GPIO_B0
},{H8300_GPIO_P8
,H8300_GPIO_B1
},
69 {H8300_GPIO_P8
,H8300_GPIO_B2
},{H8300_GPIO_P8
,H8300_GPIO_B3
},
70 {H8300_GPIO_P8
,H8300_GPIO_B4
},{H8300_GPIO_P8
,H8300_GPIO_B5
},
71 {H8300_GPIO_PH
,H8300_GPIO_B2
},{H8300_GPIO_PH
,H8300_GPIO_B3
},
72 {H8300_GPIO_P2
,H8300_GPIO_B0
},{H8300_GPIO_P2
,H8300_GPIO_B1
},
73 {H8300_GPIO_P2
,H8300_GPIO_B2
},{H8300_GPIO_P2
,H8300_GPIO_B3
},
74 {H8300_GPIO_P2
,H8300_GPIO_B4
},{H8300_GPIO_P2
,H8300_GPIO_B5
},
75 {H8300_GPIO_P2
,H8300_GPIO_B6
},{H8300_GPIO_P2
,H8300_GPIO_B7
},
78 static short use_kmalloc
= 0;
80 extern unsigned long *interrupt_redirect_table
;
82 #define CPU_VECTOR ((unsigned long *)0x000000)
83 #define ADDR_MASK (0xffffff)
85 static inline unsigned long *get_vector_address(void)
87 volatile unsigned long *rom_vector
= CPU_VECTOR
;
88 unsigned long base
,tmp
;
91 base
= rom_vector
[EXT_IRQ0
] & ADDR_MASK
;
93 /* check romvector format */
94 for (vec_no
= EXT_IRQ1
; vec_no
<= EXT_IRQ15
; vec_no
++) {
95 if ((base
+(vec_no
- EXT_IRQ0
)*4) != (rom_vector
[vec_no
] & ADDR_MASK
))
99 /* ramvector base address */
102 /* writerble check */
103 tmp
= ~(*(unsigned long *)base
);
104 (*(unsigned long *)base
) = tmp
;
105 if ((*(unsigned long *)base
) != tmp
)
107 return (unsigned long *)base
;
110 void __init
init_IRQ(void)
112 #if defined(CONFIG_RAMKERNEL)
114 unsigned long *ramvec
,*ramvec_p
;
115 unsigned long break_vec
;
117 ramvec
= get_vector_address();
119 panic("interrupt vector serup failed.");
121 printk("virtual vector at 0x%08lx\n",(unsigned long)ramvec
);
123 #if defined(CONFIG_GDB_DEBUG)
124 /* save original break vector */
125 break_vec
= ramvec
[TRAP3_VEC
];
127 break_vec
= VECTOR(trace_break
);
130 /* create redirect table */
131 for (ramvec_p
= ramvec
, i
= 0; i
< NR_IRQS
; i
++)
132 *ramvec_p
++ = REDIRECT(interrupt_entry
);
134 /* set special vector */
135 ramvec
[TRAP0_VEC
] = VECTOR(system_call
);
136 ramvec
[TRAP3_VEC
] = break_vec
;
137 interrupt_redirect_table
= ramvec
;
140 for (i
= 0; i
< NR_IRQS
; i
++) {
142 printk("\n%p: ",ramvec_p
);
143 printk("%p ",*ramvec_p
);
151 int request_irq(unsigned int irq
,
152 irqreturn_t (*handler
)(int, void *, struct pt_regs
*),
153 unsigned long flags
, const char *devname
, void *dev_id
)
155 unsigned short ptn
= 1 << (irq
- EXT_IRQ0
);
156 irq_handler_t
*irq_handle
;
157 if (irq
< 0 || irq
>= NR_IRQS
) {
158 printk("Incorrect IRQ %d from %s\n", irq
, devname
);
162 return -EBUSY
; /* already used */
163 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
) {
164 /* initialize IRQ pin */
165 unsigned int port_no
,bit_no
;
166 if (*(volatile unsigned short *)ITSR
& ptn
) {
167 port_no
= irq_assign_table1
[irq
- EXT_IRQ0
].port_no
;
168 bit_no
= irq_assign_table1
[irq
- EXT_IRQ0
].bit_no
;
170 port_no
= irq_assign_table0
[irq
- EXT_IRQ0
].port_no
;
171 bit_no
= irq_assign_table0
[irq
- EXT_IRQ0
].bit_no
;
173 if (H8300_GPIO_RESERVE(port_no
, bit_no
) == 0)
174 return -EBUSY
; /* pin already use */
175 H8300_GPIO_DDR(port_no
, bit_no
, H8300_GPIO_INPUT
);
176 *(volatile unsigned short *)ISR
&= ~ptn
; /* ISR clear */
180 irq_handle
= kmalloc(sizeof(irq_handler_t
), GFP_ATOMIC
);
182 /* use bootmem allocator */
183 irq_handle
= (irq_handler_t
*)alloc_bootmem(sizeof(irq_handler_t
));
184 irq_handle
= (irq_handler_t
*)((unsigned long)irq_handle
| 0x80000000);
187 if (irq_handle
== NULL
)
190 irq_handle
->handler
= handler
;
191 irq_handle
->flags
= flags
;
192 irq_handle
->count
= 0;
193 irq_handle
->dev_id
= dev_id
;
194 irq_handle
->devname
= devname
;
195 irq_list
[irq
] = irq_handle
;
196 if (irq_handle
->flags
& IRQF_SAMPLE_RANDOM
)
197 rand_initialize_irq(irq
);
199 /* enable interrupt */
200 /* compatible i386 */
201 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
)
202 *(volatile unsigned short *)IER
|= ptn
;
206 EXPORT_SYMBOL(request_irq
);
208 void free_irq(unsigned int irq
, void *dev_id
)
212 if (irq_list
[irq
]->dev_id
!= dev_id
)
213 printk("%s: Removing probably wrong IRQ %d from %s\n",
214 __FUNCTION__
, irq
, irq_list
[irq
]->devname
);
215 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
) {
216 /* disable interrupt & release IRQ pin */
217 unsigned short port_no
,bit_no
;
218 *(volatile unsigned short *)ISR
&= ~(1 << (irq
- EXT_IRQ0
));
219 *(volatile unsigned short *)IER
|= 1 << (irq
- EXT_IRQ0
);
220 if (*(volatile unsigned short *)ITSR
& (1 << (irq
- EXT_IRQ0
))) {
221 port_no
= irq_assign_table1
[irq
- EXT_IRQ0
].port_no
;
222 bit_no
= irq_assign_table1
[irq
- EXT_IRQ0
].bit_no
;
224 port_no
= irq_assign_table0
[irq
- EXT_IRQ0
].port_no
;
225 bit_no
= irq_assign_table0
[irq
- EXT_IRQ0
].bit_no
;
227 H8300_GPIO_FREE(port_no
, bit_no
);
229 if (((unsigned long)irq_list
[irq
] & 0x80000000) == 0) {
230 kfree(irq_list
[irq
]);
231 irq_list
[irq
] = NULL
;
235 EXPORT_SYMBOL(free_irq
);
237 unsigned long probe_irq_on (void)
242 EXPORT_SYMBOL(probe_irq_on
);
244 int probe_irq_off (unsigned long irqs
)
249 EXPORT_SYMBOL(probe_irq_off
);
251 void enable_irq(unsigned int irq
)
253 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
)
254 *(volatile unsigned short *)IER
|= 1 << (irq
- EXT_IRQ0
);
257 void disable_irq(unsigned int irq
)
259 if (irq
>= EXT_IRQ0
&& irq
<= EXT_IRQ15
)
260 *(volatile unsigned short *)IER
&= ~(1 << (irq
- EXT_IRQ0
));
263 asmlinkage
void process_int(unsigned long vec
, struct pt_regs
*fp
)
267 /* compatible i386 */
268 if (vec
>= EXT_IRQ0
&& vec
<= EXT_IRQ15
)
269 *(volatile unsigned short *)ISR
&= ~(1 << (vec
- EXT_IRQ0
));
272 irq_list
[vec
]->handler(vec
, irq_list
[vec
]->dev_id
, fp
);
273 irq_list
[vec
]->count
++;
274 if (irq_list
[vec
]->flags
& IRQF_SAMPLE_RANDOM
)
275 add_interrupt_randomness(vec
);
283 int show_interrupts(struct seq_file
*p
, void *v
)
285 int i
= *(loff_t
*) v
;
287 if ((i
< NR_IRQS
) && (irq_list
[i
] !=NULL
)) {
288 seq_printf(p
, "%3d: %10u ",i
,irq_list
[i
]->count
);
289 seq_printf(p
, "%s\n", irq_list
[i
]->devname
);
295 void init_irq_proc(void)
299 static int __init
enable_kmalloc(void)
304 core_initcall(enable_kmalloc
);