aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sun4c_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/sun4c_irq.c')
-rw-r--r--arch/sparc/kernel/sun4c_irq.c150
1 files changed, 90 insertions, 60 deletions
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index 90eea38ad66f..f6bf25a2ff80 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -65,62 +65,94 @@
65 */ 65 */
66unsigned char __iomem *interrupt_enable; 66unsigned char __iomem *interrupt_enable;
67 67
68static void sun4c_disable_irq(unsigned int irq_nr) 68static void sun4c_mask_irq(struct irq_data *data)
69{ 69{
70 unsigned long flags; 70 unsigned long mask = (unsigned long)data->chip_data;
71 unsigned char current_mask, new_mask; 71
72 72 if (mask) {
73 local_irq_save(flags); 73 unsigned long flags;
74 irq_nr &= (NR_IRQS - 1); 74
75 current_mask = sbus_readb(interrupt_enable); 75 local_irq_save(flags);
76 switch (irq_nr) { 76 mask = sbus_readb(interrupt_enable) & ~mask;
77 case 1: 77 sbus_writeb(mask, interrupt_enable);
78 new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
79 break;
80 case 8:
81 new_mask = ((current_mask) & (~(SUN4C_INT_E8)));
82 break;
83 case 10:
84 new_mask = ((current_mask) & (~(SUN4C_INT_E10)));
85 break;
86 case 14:
87 new_mask = ((current_mask) & (~(SUN4C_INT_E14)));
88 break;
89 default:
90 local_irq_restore(flags); 78 local_irq_restore(flags);
91 return;
92 } 79 }
93 sbus_writeb(new_mask, interrupt_enable);
94 local_irq_restore(flags);
95} 80}
96 81
97static void sun4c_enable_irq(unsigned int irq_nr) 82static void sun4c_unmask_irq(struct irq_data *data)
98{ 83{
99 unsigned long flags; 84 unsigned long mask = (unsigned long)data->chip_data;
100 unsigned char current_mask, new_mask; 85
101 86 if (mask) {
102 local_irq_save(flags); 87 unsigned long flags;
103 irq_nr &= (NR_IRQS - 1); 88
104 current_mask = sbus_readb(interrupt_enable); 89 local_irq_save(flags);
105 switch (irq_nr) { 90 mask = sbus_readb(interrupt_enable) | mask;
106 case 1: 91 sbus_writeb(mask, interrupt_enable);
107 new_mask = ((current_mask) | SUN4C_INT_E1);
108 break;
109 case 8:
110 new_mask = ((current_mask) | SUN4C_INT_E8);
111 break;
112 case 10:
113 new_mask = ((current_mask) | SUN4C_INT_E10);
114 break;
115 case 14:
116 new_mask = ((current_mask) | SUN4C_INT_E14);
117 break;
118 default:
119 local_irq_restore(flags); 92 local_irq_restore(flags);
120 return;
121 } 93 }
122 sbus_writeb(new_mask, interrupt_enable); 94}
123 local_irq_restore(flags); 95
96static unsigned int sun4c_startup_irq(struct irq_data *data)
97{
98 irq_link(data->irq);
99 sun4c_unmask_irq(data);
100
101 return 0;
102}
103
104static void sun4c_shutdown_irq(struct irq_data *data)
105{
106 sun4c_mask_irq(data);
107 irq_unlink(data->irq);
108}
109
110static struct irq_chip sun4c_irq = {
111 .name = "sun4c",
112 .irq_startup = sun4c_startup_irq,
113 .irq_shutdown = sun4c_shutdown_irq,
114 .irq_mask = sun4c_mask_irq,
115 .irq_unmask = sun4c_unmask_irq,
116};
117
118static unsigned int sun4c_build_device_irq(struct platform_device *op,
119 unsigned int real_irq)
120{
121 unsigned int irq;
122
123 if (real_irq >= 16) {
124 prom_printf("Bogus sun4c IRQ %u\n", real_irq);
125 prom_halt();
126 }
127
128 irq = irq_alloc(real_irq, real_irq);
129 if (irq) {
130 unsigned long mask = 0UL;
131
132 switch (real_irq) {
133 case 1:
134 mask = SUN4C_INT_E1;
135 break;
136 case 8:
137 mask = SUN4C_INT_E8;
138 break;
139 case 10:
140 mask = SUN4C_INT_E10;
141 break;
142 case 14:
143 mask = SUN4C_INT_E14;
144 break;
145 default:
146 /* All the rest are either always enabled,
147 * or are for signalling software interrupts.
148 */
149 break;
150 }
151 irq_set_chip_and_handler_name(irq, &sun4c_irq,
152 handle_level_irq, "level");
153 irq_set_chip_data(irq, (void *)mask);
154 }
155 return irq;
124} 156}
125 157
126struct sun4c_timer_info { 158struct sun4c_timer_info {
@@ -144,8 +176,9 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit)
144 176
145static void __init sun4c_init_timers(irq_handler_t counter_fn) 177static void __init sun4c_init_timers(irq_handler_t counter_fn)
146{ 178{
147 const struct linux_prom_irqs *irq; 179 const struct linux_prom_irqs *prom_irqs;
148 struct device_node *dp; 180 struct device_node *dp;
181 unsigned int irq;
149 const u32 *addr; 182 const u32 *addr;
150 int err; 183 int err;
151 184
@@ -163,9 +196,9 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
163 196
164 sun4c_timers = (void __iomem *) (unsigned long) addr[0]; 197 sun4c_timers = (void __iomem *) (unsigned long) addr[0];
165 198
166 irq = of_get_property(dp, "intr", NULL); 199 prom_irqs = of_get_property(dp, "intr", NULL);
167 of_node_put(dp); 200 of_node_put(dp);
168 if (!irq) { 201 if (!prom_irqs) {
169 prom_printf("sun4c_init_timers: No intr property\n"); 202 prom_printf("sun4c_init_timers: No intr property\n");
170 prom_halt(); 203 prom_halt();
171 } 204 }
@@ -178,15 +211,15 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
178 211
179 master_l10_counter = &sun4c_timers->l10_count; 212 master_l10_counter = &sun4c_timers->l10_count;
180 213
181 err = request_irq(irq[0].pri, counter_fn, 214 irq = sun4c_build_device_irq(NULL, prom_irqs[0].pri);
182 (IRQF_DISABLED | SA_STATIC_ALLOC), 215 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
183 "timer", NULL);
184 if (err) { 216 if (err) {
185 prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); 217 prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
186 prom_halt(); 218 prom_halt();
187 } 219 }
188 220
189 sun4c_disable_irq(irq[1].pri); 221 /* disable timer interrupt */
222 sun4c_mask_irq(irq_get_irq_data(irq));
190} 223}
191 224
192#ifdef CONFIG_SMP 225#ifdef CONFIG_SMP
@@ -215,14 +248,11 @@ void __init sun4c_init_IRQ(void)
215 248
216 interrupt_enable = (void __iomem *) (unsigned long) addr[0]; 249 interrupt_enable = (void __iomem *) (unsigned long) addr[0];
217 250
218 BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
219 BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
220 BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
221 BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
222 BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); 251 BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
223 BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); 252 BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
224 253
225 sparc_irq_config.init_timers = sun4c_init_timers; 254 sparc_irq_config.init_timers = sun4c_init_timers;
255 sparc_irq_config.build_device_irq = sun4c_build_device_irq;
226 256
227#ifdef CONFIG_SMP 257#ifdef CONFIG_SMP
228 BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); 258 BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);