diff options
Diffstat (limited to 'arch/sparc/kernel/leon_kernel.c')
-rw-r--r-- | arch/sparc/kernel/leon_kernel.c | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 2969f777fa11..8591cf124ecf 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c | |||
@@ -83,20 +83,22 @@ static inline unsigned long get_irqmask(unsigned int irq) | |||
83 | return mask; | 83 | return mask; |
84 | } | 84 | } |
85 | 85 | ||
86 | static void leon_enable_irq(unsigned int irq_nr) | 86 | static void leon_unmask_irq(struct irq_data *data) |
87 | { | 87 | { |
88 | unsigned long mask, flags; | 88 | unsigned long mask, flags; |
89 | mask = get_irqmask(irq_nr); | 89 | |
90 | mask = (unsigned long)data->chip_data; | ||
90 | local_irq_save(flags); | 91 | local_irq_save(flags); |
91 | LEON3_BYPASS_STORE_PA(LEON_IMASK, | 92 | LEON3_BYPASS_STORE_PA(LEON_IMASK, |
92 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); | 93 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); |
93 | local_irq_restore(flags); | 94 | local_irq_restore(flags); |
94 | } | 95 | } |
95 | 96 | ||
96 | static void leon_disable_irq(unsigned int irq_nr) | 97 | static void leon_mask_irq(struct irq_data *data) |
97 | { | 98 | { |
98 | unsigned long mask, flags; | 99 | unsigned long mask, flags; |
99 | mask = get_irqmask(irq_nr); | 100 | |
101 | mask = (unsigned long)data->chip_data; | ||
100 | local_irq_save(flags); | 102 | local_irq_save(flags); |
101 | LEON3_BYPASS_STORE_PA(LEON_IMASK, | 103 | LEON3_BYPASS_STORE_PA(LEON_IMASK, |
102 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); | 104 | (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); |
@@ -104,6 +106,50 @@ static void leon_disable_irq(unsigned int irq_nr) | |||
104 | 106 | ||
105 | } | 107 | } |
106 | 108 | ||
109 | static unsigned int leon_startup_irq(struct irq_data *data) | ||
110 | { | ||
111 | irq_link(data->irq); | ||
112 | leon_unmask_irq(data); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void leon_shutdown_irq(struct irq_data *data) | ||
117 | { | ||
118 | leon_mask_irq(data); | ||
119 | irq_unlink(data->irq); | ||
120 | } | ||
121 | |||
122 | static struct irq_chip leon_irq = { | ||
123 | .name = "leon", | ||
124 | .irq_startup = leon_startup_irq, | ||
125 | .irq_shutdown = leon_shutdown_irq, | ||
126 | .irq_mask = leon_mask_irq, | ||
127 | .irq_unmask = leon_unmask_irq, | ||
128 | }; | ||
129 | |||
130 | static unsigned int leon_build_device_irq(struct platform_device *op, | ||
131 | unsigned int real_irq) | ||
132 | { | ||
133 | unsigned int irq; | ||
134 | unsigned long mask; | ||
135 | |||
136 | irq = 0; | ||
137 | mask = get_irqmask(real_irq); | ||
138 | if (mask == 0) | ||
139 | goto out; | ||
140 | |||
141 | irq = irq_alloc(real_irq, real_irq); | ||
142 | if (irq == 0) | ||
143 | goto out; | ||
144 | |||
145 | irq_set_chip_and_handler_name(irq, &leon_irq, | ||
146 | handle_simple_irq, "edge"); | ||
147 | irq_set_chip_data(irq, (void *)mask); | ||
148 | |||
149 | out: | ||
150 | return irq; | ||
151 | } | ||
152 | |||
107 | void __init leon_init_timers(irq_handler_t counter_fn) | 153 | void __init leon_init_timers(irq_handler_t counter_fn) |
108 | { | 154 | { |
109 | int irq; | 155 | int irq; |
@@ -112,6 +158,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
112 | int len; | 158 | int len; |
113 | int cpu, icsel; | 159 | int cpu, icsel; |
114 | int ampopts; | 160 | int ampopts; |
161 | int err; | ||
115 | 162 | ||
116 | leondebug_irq_disable = 0; | 163 | leondebug_irq_disable = 0; |
117 | leon_debug_irqout = 0; | 164 | leon_debug_irqout = 0; |
@@ -219,11 +266,10 @@ void __init leon_init_timers(irq_handler_t counter_fn) | |||
219 | goto bad; | 266 | goto bad; |
220 | } | 267 | } |
221 | 268 | ||
222 | irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx, | 269 | irq = leon_build_device_irq(NULL, leon3_gptimer_irq + leon3_gptimer_idx); |
223 | counter_fn, | 270 | err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); |
224 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); | ||
225 | 271 | ||
226 | if (irq) { | 272 | if (err) { |
227 | printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", | 273 | printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", |
228 | LEON_INTERRUPT_TIMER1); | 274 | LEON_INTERRUPT_TIMER1); |
229 | prom_halt(); | 275 | prom_halt(); |
@@ -347,12 +393,8 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu) | |||
347 | 393 | ||
348 | void __init leon_init_IRQ(void) | 394 | void __init leon_init_IRQ(void) |
349 | { | 395 | { |
350 | sparc_irq_config.init_timers = leon_init_timers; | 396 | sparc_irq_config.init_timers = leon_init_timers; |
351 | 397 | sparc_irq_config.build_device_irq = leon_build_device_irq; | |
352 | BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM); | ||
353 | BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM); | ||
354 | BTFIXUPSET_CALL(enable_pil_irq, leon_enable_irq, BTFIXUPCALL_NORM); | ||
355 | BTFIXUPSET_CALL(disable_pil_irq, leon_disable_irq, BTFIXUPCALL_NORM); | ||
356 | 398 | ||
357 | BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, | 399 | BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq, |
358 | BTFIXUPCALL_NORM); | 400 | BTFIXUPCALL_NORM); |