Blame view

arch/h8300/kernel/irq.c 3.58 KB
c728d6045   Yoshinori Sato   h8300 generic irq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  /*
   * linux/arch/h8300/kernel/irq.c
   *
   * Copyright 2007 Yoshinori Sato <ysato@users.sourceforge.jp>
   */
  
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #include <linux/kernel_stat.h>
  #include <linux/seq_file.h>
  #include <linux/init.h>
  #include <linux/random.h>
  #include <linux/bootmem.h>
  #include <linux/irq.h>
f74596d07   Adrian Bunk   proper show_inter...
17
  #include <linux/interrupt.h>
c728d6045   Yoshinori Sato   h8300 generic irq
18
19
20
21
22
23
24
25
26
27
28
  
  #include <asm/system.h>
  #include <asm/traps.h>
  #include <asm/io.h>
  #include <asm/setup.h>
  #include <asm/errno.h>
  
  /*#define DEBUG*/
  
  extern unsigned long *interrupt_redirect_table;
  extern const int h8300_saved_vectors[];
5cc265a5d   Yoshinori Sato   h8300: IRQ handli...
29
  extern const h8300_vector h8300_trap_table[];
c728d6045   Yoshinori Sato   h8300 generic irq
30
31
32
33
34
35
36
37
38
39
  int h8300_enable_irq_pin(unsigned int irq);
  void h8300_disable_irq_pin(unsigned int irq);
  
  #define CPU_VECTOR ((unsigned long *)0x000000)
  #define ADDR_MASK (0xffffff)
  
  static inline int is_ext_irq(unsigned int irq)
  {
  	return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
  }
12174aac3   Thomas Gleixner   h8300: Convert to...
40
  static void h8300_enable_irq(struct irq_data *data)
c728d6045   Yoshinori Sato   h8300 generic irq
41
  {
12174aac3   Thomas Gleixner   h8300: Convert to...
42
43
  	if (is_ext_irq(data->irq))
  		IER_REGS |= 1 << (data->irq - EXT_IRQ0);
c728d6045   Yoshinori Sato   h8300 generic irq
44
  }
12174aac3   Thomas Gleixner   h8300: Convert to...
45
  static void h8300_disable_irq(struct irq_data *data)
c728d6045   Yoshinori Sato   h8300 generic irq
46
  {
12174aac3   Thomas Gleixner   h8300: Convert to...
47
48
  	if (is_ext_irq(data->irq))
  		IER_REGS &= ~(1 << (data->irq - EXT_IRQ0));
c728d6045   Yoshinori Sato   h8300 generic irq
49
  }
12174aac3   Thomas Gleixner   h8300: Convert to...
50
  static unsigned int h8300_startup_irq(struct irq_data *data)
c728d6045   Yoshinori Sato   h8300 generic irq
51
  {
12174aac3   Thomas Gleixner   h8300: Convert to...
52
53
  	if (is_ext_irq(data->irq))
  		return h8300_enable_irq_pin(data->irq);
c728d6045   Yoshinori Sato   h8300 generic irq
54
55
56
  	else
  		return 0;
  }
12174aac3   Thomas Gleixner   h8300: Convert to...
57
  static void h8300_shutdown_irq(struct irq_data *data)
c728d6045   Yoshinori Sato   h8300 generic irq
58
  {
12174aac3   Thomas Gleixner   h8300: Convert to...
59
60
  	if (is_ext_irq(data->irq))
  		h8300_disable_irq_pin(data->irq);
c728d6045   Yoshinori Sato   h8300 generic irq
61
62
63
  }
  
  /*
3a4fa0a25   Robert P. J. Day   Fix misspellings ...
64
   * h8300 interrupt controller implementation
c728d6045   Yoshinori Sato   h8300 generic irq
65
66
67
   */
  struct irq_chip h8300irq_chip = {
  	.name		= "H8300-INTC",
12174aac3   Thomas Gleixner   h8300: Convert to...
68
69
70
71
  	.irq_startup	= h8300_startup_irq,
  	.irq_shutdown	= h8300_shutdown_irq,
  	.irq_enable	= h8300_enable_irq,
  	.irq_disable	= h8300_disable_irq,
c728d6045   Yoshinori Sato   h8300 generic irq
72
  };
c728d6045   Yoshinori Sato   h8300 generic irq
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
  #if defined(CONFIG_RAMKERNEL)
  static unsigned long __init *get_vector_address(void)
  {
  	unsigned long *rom_vector = CPU_VECTOR;
  	unsigned long base,tmp;
  	int vec_no;
  
  	base = rom_vector[EXT_IRQ0] & ADDR_MASK;
  
  	/* check romvector format */
  	for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
  		if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
  			return NULL;
  	}
  
  	/* ramvector base address */
  	base -= EXT_IRQ0*4;
  
  	/* writerble check */
  	tmp = ~(*(volatile unsigned long *)base);
  	(*(volatile unsigned long *)base) = tmp;
  	if ((*(volatile unsigned long *)base) != tmp)
  		return NULL;
  	return (unsigned long *)base;
  }
  
  static void __init setup_vector(void)
  {
  	int i;
  	unsigned long *ramvec,*ramvec_p;
5cc265a5d   Yoshinori Sato   h8300: IRQ handli...
103
  	const h8300_vector *trap_entry;
c728d6045   Yoshinori Sato   h8300 generic irq
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  	const int *saved_vector;
  
  	ramvec = get_vector_address();
  	if (ramvec == NULL)
  		panic("interrupt vector serup failed.");
  	else
  		printk(KERN_INFO "virtual vector at 0x%08lx
  ",(unsigned long)ramvec);
  
  	/* create redirect table */
  	ramvec_p = ramvec;
  	trap_entry = h8300_trap_table;
  	saved_vector = h8300_saved_vectors;
  	for ( i = 0; i < NR_IRQS; i++) {
  		if (i == *saved_vector) {
  			ramvec_p++;
  			saved_vector++;
  		} else {
  			if ( i < NR_TRAPS ) {
  				if (*trap_entry)
  					*ramvec_p = VECTOR(*trap_entry);
  				ramvec_p++;
  				trap_entry++;
  			} else
  				*ramvec_p++ = REDIRECT(interrupt_entry);
  		}
  	}
  	interrupt_redirect_table = ramvec;
  #ifdef DEBUG
  	ramvec_p = ramvec;
  	for (i = 0; i < NR_IRQS; i++) {
  		if ((i % 8) == 0)
  			printk(KERN_DEBUG "
  %p: ",ramvec_p);
  		printk(KERN_DEBUG "%p ",*ramvec_p);
  		ramvec_p++;
  	}
  	printk(KERN_DEBUG "
  ");
  #endif
  }
  #else
  #define setup_vector() do { } while(0)
  #endif
  
  void __init init_IRQ(void)
  {
  	int c;
  
  	setup_vector();
f9f91ef5e   Thomas Gleixner   h8300: Convert in...
154
  	for (c = 0; c < NR_IRQS; c++)
7b04690a3   Thomas Gleixner   h8300: Convert ge...
155
  		irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
c728d6045   Yoshinori Sato   h8300 generic irq
156
157
158
159
160
  }
  
  asmlinkage void do_IRQ(int irq)
  {
  	irq_enter();
f9f91ef5e   Thomas Gleixner   h8300: Convert in...
161
  	generic_handle_irq(irq);
c728d6045   Yoshinori Sato   h8300 generic irq
162
163
  	irq_exit();
  }