21
21
* You should have received a copy of the GNU General Public License
22
22
* along with this program; if not, write to the Free Software
23
23
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
+ *
25
+ * TODO:
26
+ * - Fix various assumptions related to HW CPU numbers vs. linux CPU numbers
27
+ * vs node numbers in the setup code
28
+ * - Implement proper handling of maxcpus=1/2 (that is, routing of irqs from
29
+ * a non-active node to the active node)
24
30
*/
25
31
26
32
#include <linux/interrupt.h>
@@ -44,24 +50,25 @@ struct iic {
44
50
u8 target_id ;
45
51
u8 eoi_stack [16 ];
46
52
int eoi_ptr ;
47
- struct irq_host * host ;
53
+ struct device_node * node ;
48
54
};
49
55
50
56
static DEFINE_PER_CPU (struct iic , iic ) ;
51
57
#define IIC_NODE_COUNT 2
52
- static struct irq_host * iic_hosts [ IIC_NODE_COUNT ] ;
58
+ static struct irq_host * iic_host ;
53
59
54
60
/* Convert between "pending" bits and hw irq number */
55
61
static irq_hw_number_t iic_pending_to_hwnum (struct cbe_iic_pending_bits bits )
56
62
{
57
63
unsigned char unit = bits .source & 0xf ;
64
+ unsigned char node = bits .source >> 4 ;
65
+ unsigned char class = bits .class & 3 ;
58
66
67
+ /* Decode IPIs */
59
68
if (bits .flags & CBE_IIC_IRQ_IPI )
60
- return IIC_IRQ_IPI0 | (bits .prio >> 4 );
61
- else if (bits .class <= 3 )
62
- return (bits .class << 4 ) | unit ;
69
+ return IIC_IRQ_TYPE_IPI | (bits .prio >> 4 );
63
70
else
64
- return IIC_IRQ_INVALID ;
71
+ return ( node << IIC_IRQ_NODE_SHIFT ) | ( class << 4 ) | unit ;
65
72
}
66
73
67
74
static void iic_mask (unsigned int irq )
@@ -86,34 +93,78 @@ static struct irq_chip iic_chip = {
86
93
.eoi = iic_eoi ,
87
94
};
88
95
96
+
97
+ static void iic_ioexc_eoi (unsigned int irq )
98
+ {
99
+ }
100
+
101
+ static void iic_ioexc_cascade (unsigned int irq , struct irq_desc * desc ,
102
+ struct pt_regs * regs )
103
+ {
104
+ struct cbe_iic_regs * node_iic = desc -> handler_data ;
105
+ unsigned int base = (irq & 0xffffff00 ) | IIC_IRQ_TYPE_IOEXC ;
106
+ unsigned long bits , ack ;
107
+ int cascade ;
108
+
109
+ for (;;) {
110
+ bits = in_be64 (& node_iic -> iic_is );
111
+ if (bits == 0 )
112
+ break ;
113
+ /* pre-ack edge interrupts */
114
+ ack = bits & IIC_ISR_EDGE_MASK ;
115
+ if (ack )
116
+ out_be64 (& node_iic -> iic_is , ack );
117
+ /* handle them */
118
+ for (cascade = 63 ; cascade >= 0 ; cascade -- )
119
+ if (bits & (0x8000000000000000UL >> cascade )) {
120
+ unsigned int cirq =
121
+ irq_linear_revmap (iic_host ,
122
+ base | cascade );
123
+ if (cirq != NO_IRQ )
124
+ generic_handle_irq (cirq , regs );
125
+ }
126
+ /* post-ack level interrupts */
127
+ ack = bits & ~IIC_ISR_EDGE_MASK ;
128
+ if (ack )
129
+ out_be64 (& node_iic -> iic_is , ack );
130
+ }
131
+ desc -> chip -> eoi (irq );
132
+ }
133
+
134
+
135
+ static struct irq_chip iic_ioexc_chip = {
136
+ .typename = " CELL-IOEX" ,
137
+ .mask = iic_mask ,
138
+ .unmask = iic_unmask ,
139
+ .eoi = iic_ioexc_eoi ,
140
+ };
141
+
89
142
/* Get an IRQ number from the pending state register of the IIC */
90
143
static unsigned int iic_get_irq (struct pt_regs * regs )
91
144
{
92
145
struct cbe_iic_pending_bits pending ;
93
146
struct iic * iic ;
147
+ unsigned int virq ;
94
148
95
149
iic = & __get_cpu_var (iic );
96
150
* (unsigned long * ) & pending =
97
151
in_be64 ((unsigned long __iomem * ) & iic -> regs -> pending_destr );
152
+ if (!(pending .flags & CBE_IIC_IRQ_VALID ))
153
+ return NO_IRQ ;
154
+ virq = irq_linear_revmap (iic_host , iic_pending_to_hwnum (pending ));
155
+ if (virq == NO_IRQ )
156
+ return NO_IRQ ;
98
157
iic -> eoi_stack [++ iic -> eoi_ptr ] = pending .prio ;
99
158
BUG_ON (iic -> eoi_ptr > 15 );
100
- if (pending .flags & CBE_IIC_IRQ_VALID )
101
- return irq_linear_revmap (iic -> host ,
102
- iic_pending_to_hwnum (pending ));
103
- return NO_IRQ ;
159
+ return virq ;
104
160
}
105
161
106
162
#ifdef CONFIG_SMP
107
163
108
164
/* Use the highest interrupt priorities for IPI */
109
165
static inline int iic_ipi_to_irq (int ipi )
110
166
{
111
- return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi ;
112
- }
113
-
114
- static inline int iic_irq_to_ipi (int irq )
115
- {
116
- return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0 );
167
+ return IIC_IRQ_TYPE_IPI + 0xf - ipi ;
117
168
}
118
169
119
170
void iic_setup_cpu (void )
@@ -123,7 +174,7 @@ void iic_setup_cpu(void)
123
174
124
175
void iic_cause_IPI (int cpu , int mesg )
125
176
{
126
- out_be64 (& per_cpu (iic , cpu ).regs -> generate , (IIC_NUM_IPIS - 1 - mesg ) << 4 );
177
+ out_be64 (& per_cpu (iic , cpu ).regs -> generate , (0xf - mesg ) << 4 );
127
178
}
128
179
129
180
u8 iic_get_target_id (int cpu )
@@ -134,9 +185,7 @@ EXPORT_SYMBOL_GPL(iic_get_target_id);
134
185
135
186
struct irq_host * iic_get_irq_host (int node )
136
187
{
137
- if (node < 0 || node >= IIC_NODE_COUNT )
138
- return NULL ;
139
- return iic_hosts [node ];
188
+ return iic_host ;
140
189
}
141
190
EXPORT_SYMBOL_GPL (iic_get_irq_host );
142
191
@@ -149,34 +198,20 @@ static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
149
198
150
199
return IRQ_HANDLED ;
151
200
}
152
-
153
201
static void iic_request_ipi (int ipi , const char * name )
154
202
{
155
- int node , virq ;
203
+ int virq ;
156
204
157
- for (node = 0 ; node < IIC_NODE_COUNT ; node ++ ) {
158
- char * rname ;
159
- if (iic_hosts [node ] == NULL )
160
- continue ;
161
- virq = irq_create_mapping (iic_hosts [node ],
162
- iic_ipi_to_irq (ipi ));
163
- if (virq == NO_IRQ ) {
164
- printk (KERN_ERR
165
- "iic: failed to map IPI %s on node %d\n" ,
166
- name , node );
167
- continue ;
168
- }
169
- rname = kzalloc (strlen (name ) + 16 , GFP_KERNEL );
170
- if (rname )
171
- sprintf (rname , "%s node %d" , name , node );
172
- else
173
- rname = (char * )name ;
174
- if (request_irq (virq , iic_ipi_action , IRQF_DISABLED ,
175
- rname , (void * )(long )ipi ))
176
- printk (KERN_ERR
177
- "iic: failed to request IPI %s on node %d\n" ,
178
- name , node );
205
+ virq = irq_create_mapping (iic_host , iic_ipi_to_irq (ipi ));
206
+ if (virq == NO_IRQ ) {
207
+ printk (KERN_ERR
208
+ "iic: failed to map IPI %s\n" , name );
209
+ return ;
179
210
}
211
+ if (request_irq (virq , iic_ipi_action , IRQF_DISABLED , name ,
212
+ (void * )(long )ipi ))
213
+ printk (KERN_ERR
214
+ "iic: failed to request IPI %s\n" , name );
180
215
}
181
216
182
217
void iic_request_IPIs (void )
@@ -193,16 +228,24 @@ void iic_request_IPIs(void)
193
228
194
229
static int iic_host_match (struct irq_host * h , struct device_node * node )
195
230
{
196
- return h -> host_data != NULL && node == h -> host_data ;
231
+ return device_is_compatible (node ,
232
+ "IBM,CBEA-Internal-Interrupt-Controller" );
197
233
}
198
234
199
235
static int iic_host_map (struct irq_host * h , unsigned int virq ,
200
236
irq_hw_number_t hw )
201
237
{
202
- if (hw < IIC_IRQ_IPI0 )
203
- set_irq_chip_and_handler (virq , & iic_chip , handle_fasteoi_irq );
204
- else
238
+ switch (hw & IIC_IRQ_TYPE_MASK ) {
239
+ case IIC_IRQ_TYPE_IPI :
205
240
set_irq_chip_and_handler (virq , & iic_chip , handle_percpu_irq );
241
+ break ;
242
+ case IIC_IRQ_TYPE_IOEXC :
243
+ set_irq_chip_and_handler (virq , & iic_ioexc_chip ,
244
+ handle_fasteoi_irq );
245
+ break ;
246
+ default :
247
+ set_irq_chip_and_handler (virq , & iic_chip , handle_fasteoi_irq );
248
+ }
206
249
return 0 ;
207
250
}
208
251
@@ -211,11 +254,39 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
211
254
irq_hw_number_t * out_hwirq , unsigned int * out_flags )
212
255
213
256
{
214
- /* Currently, we don't translate anything. That needs to be fixed as
215
- * we get better defined device-trees. iic interrupts have to be
216
- * explicitely mapped by whoever needs them
217
- */
218
- return - ENODEV ;
257
+ unsigned int node , ext , unit , class ;
258
+ const u32 * val ;
259
+
260
+ if (!device_is_compatible (ct ,
261
+ "IBM,CBEA-Internal-Interrupt-Controller" ))
262
+ return - ENODEV ;
263
+ if (intsize != 1 )
264
+ return - ENODEV ;
265
+ val = get_property (ct , "#interrupt-cells" , NULL );
266
+ if (val == NULL || * val != 1 )
267
+ return - ENODEV ;
268
+
269
+ node = intspec [0 ] >> 24 ;
270
+ ext = (intspec [0 ] >> 16 ) & 0xff ;
271
+ class = (intspec [0 ] >> 8 ) & 0xff ;
272
+ unit = intspec [0 ] & 0xff ;
273
+
274
+ /* Check if node is in supported range */
275
+ if (node > 1 )
276
+ return - EINVAL ;
277
+
278
+ /* Build up interrupt number, special case for IO exceptions */
279
+ * out_hwirq = (node << IIC_IRQ_NODE_SHIFT );
280
+ if (unit == IIC_UNIT_IIC && class == 1 )
281
+ * out_hwirq |= IIC_IRQ_TYPE_IOEXC | ext ;
282
+ else
283
+ * out_hwirq |= IIC_IRQ_TYPE_NORMAL |
284
+ (class << IIC_IRQ_CLASS_SHIFT ) | unit ;
285
+
286
+ /* Dummy flags, ignored by iic code */
287
+ * out_flags = IRQ_TYPE_EDGE_RISING ;
288
+
289
+ return 0 ;
219
290
}
220
291
221
292
static struct irq_host_ops iic_host_ops = {
@@ -225,7 +296,7 @@ static struct irq_host_ops iic_host_ops = {
225
296
};
226
297
227
298
static void __init init_one_iic (unsigned int hw_cpu , unsigned long addr ,
228
- struct irq_host * host )
299
+ struct device_node * node )
229
300
{
230
301
/* XXX FIXME: should locate the linux CPU number from the HW cpu
231
302
* number properly. We are lucky for now
@@ -237,19 +308,19 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
237
308
238
309
iic -> target_id = ((hw_cpu & 2 ) << 3 ) | ((hw_cpu & 1 ) ? 0xf : 0xe );
239
310
iic -> eoi_stack [0 ] = 0xff ;
240
- iic -> host = host ;
311
+ iic -> node = of_node_get ( node ) ;
241
312
out_be64 (& iic -> regs -> prio , 0 );
242
313
243
- printk (KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n" ,
244
- hw_cpu , addr , iic -> regs , iic -> target_id );
314
+ printk (KERN_INFO "IIC for CPU %d target id 0x%x : %s \n" ,
315
+ hw_cpu , iic -> target_id , node -> full_name );
245
316
}
246
317
247
318
static int __init setup_iic (void )
248
319
{
249
320
struct device_node * dn ;
250
321
struct resource r0 , r1 ;
251
- struct irq_host * host ;
252
- int found = 0 ;
322
+ unsigned int node , cascade , found = 0 ;
323
+ struct cbe_iic_regs * node_iic ;
253
324
const u32 * np ;
254
325
255
326
for (dn = NULL ;
@@ -269,19 +340,33 @@ static int __init setup_iic(void)
269
340
of_node_put (dn );
270
341
return - ENODEV ;
271
342
}
272
- host = NULL ;
273
- if (found < IIC_NODE_COUNT ) {
274
- host = irq_alloc_host (IRQ_HOST_MAP_LINEAR ,
275
- IIC_SOURCE_COUNT ,
276
- & iic_host_ops ,
277
- IIC_IRQ_INVALID );
278
- iic_hosts [found ] = host ;
279
- BUG_ON (iic_hosts [found ] == NULL );
280
- iic_hosts [found ]-> host_data = of_node_get (dn );
281
- found ++ ;
282
- }
283
- init_one_iic (np [0 ], r0 .start , host );
284
- init_one_iic (np [1 ], r1 .start , host );
343
+ found ++ ;
344
+ init_one_iic (np [0 ], r0 .start , dn );
345
+ init_one_iic (np [1 ], r1 .start , dn );
346
+
347
+ /* Setup cascade for IO exceptions. XXX cleanup tricks to get
348
+ * node vs CPU etc...
349
+ * Note that we configure the IIC_IRR here with a hard coded
350
+ * priority of 1. We might want to improve that later.
351
+ */
352
+ node = np [0 ] >> 1 ;
353
+ node_iic = cbe_get_cpu_iic_regs (np [0 ]);
354
+ cascade = node << IIC_IRQ_NODE_SHIFT ;
355
+ cascade |= 1 << IIC_IRQ_CLASS_SHIFT ;
356
+ cascade |= IIC_UNIT_IIC ;
357
+ cascade = irq_create_mapping (iic_host , cascade );
358
+ if (cascade == NO_IRQ )
359
+ continue ;
360
+ set_irq_data (cascade , node_iic );
361
+ set_irq_chained_handler (cascade , iic_ioexc_cascade );
362
+ out_be64 (& node_iic -> iic_ir ,
363
+ (1 << 12 ) /* priority */ |
364
+ (node << 4 ) /* dest node */ |
365
+ IIC_UNIT_THREAD_0 /* route them to thread 0 */ );
366
+ /* Flush pending (make sure it triggers if there is
367
+ * anything pending
368
+ */
369
+ out_be64 (& node_iic -> iic_is , 0xfffffffffffffffful );
285
370
}
286
371
287
372
if (found )
@@ -292,6 +377,12 @@ static int __init setup_iic(void)
292
377
293
378
void __init iic_init_IRQ (void )
294
379
{
380
+ /* Setup an irq host data structure */
381
+ iic_host = irq_alloc_host (IRQ_HOST_MAP_LINEAR , IIC_SOURCE_COUNT ,
382
+ & iic_host_ops , IIC_IRQ_INVALID );
383
+ BUG_ON (iic_host == NULL );
384
+ irq_set_default_host (iic_host );
385
+
295
386
/* Discover and initialize iics */
296
387
if (setup_iic () < 0 )
297
388
panic ("IIC: Failed to initialize !\n" );
0 commit comments