33
33
#define PIC_REG_IDX (irq_id ) ((irq_id) / PIC_COUNT_PER_REG)
34
34
#define PIC_REG_BIT (irq_id ) ((irq_id) % PIC_COUNT_PER_REG)
35
35
36
+ static int nr_pics ;
37
+
36
38
struct pch_pic {
37
39
void __iomem * base ;
38
40
struct irq_domain * pic_domain ;
39
41
u32 ht_vec_base ;
40
42
raw_spinlock_t pic_lock ;
43
+ u32 vec_count ;
44
+ u32 gsi_base ;
41
45
};
42
46
47
+ static struct pch_pic * pch_pic_priv [MAX_IO_PICS ];
48
+
49
+ struct fwnode_handle * pch_pic_handle [MAX_IO_PICS ];
50
+
51
+ int find_pch_pic (u32 gsi )
52
+ {
53
+ int i ;
54
+
55
+ /* Find the PCH_PIC that manages this GSI. */
56
+ for (i = 0 ; i < MAX_IO_PICS ; i ++ ) {
57
+ struct pch_pic * priv = pch_pic_priv [i ];
58
+
59
+ if (!priv )
60
+ return -1 ;
61
+
62
+ if (gsi >= priv -> gsi_base && gsi < (priv -> gsi_base + priv -> vec_count ))
63
+ return i ;
64
+ }
65
+
66
+ pr_err ("ERROR: Unable to locate PCH_PIC for GSI %d\n" , gsi );
67
+ return -1 ;
68
+ }
69
+
43
70
static void pch_pic_bitset (struct pch_pic * priv , int offset , int bit )
44
71
{
45
72
u32 reg ;
@@ -139,6 +166,28 @@ static struct irq_chip pch_pic_irq_chip = {
139
166
.irq_set_type = pch_pic_set_type ,
140
167
};
141
168
169
+ static int pch_pic_domain_translate (struct irq_domain * d ,
170
+ struct irq_fwspec * fwspec ,
171
+ unsigned long * hwirq ,
172
+ unsigned int * type )
173
+ {
174
+ struct pch_pic * priv = d -> host_data ;
175
+ struct device_node * of_node = to_of_node (fwspec -> fwnode );
176
+
177
+ if (fwspec -> param_count < 1 )
178
+ return - EINVAL ;
179
+
180
+ if (of_node ) {
181
+ * hwirq = fwspec -> param [0 ] + priv -> ht_vec_base ;
182
+ * type = fwspec -> param [1 ] & IRQ_TYPE_SENSE_MASK ;
183
+ } else {
184
+ * hwirq = fwspec -> param [0 ] - priv -> gsi_base ;
185
+ * type = IRQ_TYPE_NONE ;
186
+ }
187
+
188
+ return 0 ;
189
+ }
190
+
142
191
static int pch_pic_alloc (struct irq_domain * domain , unsigned int virq ,
143
192
unsigned int nr_irqs , void * arg )
144
193
{
@@ -149,13 +198,13 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
149
198
struct irq_fwspec parent_fwspec ;
150
199
struct pch_pic * priv = domain -> host_data ;
151
200
152
- err = irq_domain_translate_twocell (domain , fwspec , & hwirq , & type );
201
+ err = pch_pic_domain_translate (domain , fwspec , & hwirq , & type );
153
202
if (err )
154
203
return err ;
155
204
156
205
parent_fwspec .fwnode = domain -> parent -> fwnode ;
157
206
parent_fwspec .param_count = 1 ;
158
- parent_fwspec .param [0 ] = hwirq + priv -> ht_vec_base ;
207
+ parent_fwspec .param [0 ] = hwirq ;
159
208
160
209
err = irq_domain_alloc_irqs_parent (domain , virq , 1 , & parent_fwspec );
161
210
if (err )
@@ -170,7 +219,7 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
170
219
}
171
220
172
221
static const struct irq_domain_ops pch_pic_domain_ops = {
173
- .translate = irq_domain_translate_twocell ,
222
+ .translate = pch_pic_domain_translate ,
174
223
.alloc = pch_pic_alloc ,
175
224
.free = irq_domain_free_irqs_parent ,
176
225
};
@@ -180,7 +229,7 @@ static void pch_pic_reset(struct pch_pic *priv)
180
229
int i ;
181
230
182
231
for (i = 0 ; i < PIC_COUNT ; i ++ ) {
183
- /* Write vectored ID */
232
+ /* Write vector ID */
184
233
writeb (priv -> ht_vec_base + i , priv -> base + PCH_INT_HTVEC (i ));
185
234
/* Hardcode route to HT0 Lo */
186
235
writeb (1 , priv -> base + PCH_INT_ROUTE (i ));
@@ -198,50 +247,37 @@ static void pch_pic_reset(struct pch_pic *priv)
198
247
}
199
248
}
200
249
201
- static int pch_pic_of_init (struct device_node * node ,
202
- struct device_node * parent )
250
+ static int pch_pic_init (phys_addr_t addr , unsigned long size , int vec_base ,
251
+ struct irq_domain * parent_domain , struct fwnode_handle * domain_handle ,
252
+ u32 gsi_base )
203
253
{
204
254
struct pch_pic * priv ;
205
- struct irq_domain * parent_domain ;
206
- int err ;
207
255
208
256
priv = kzalloc (sizeof (* priv ), GFP_KERNEL );
209
257
if (!priv )
210
258
return - ENOMEM ;
211
259
212
260
raw_spin_lock_init (& priv -> pic_lock );
213
- priv -> base = of_iomap (node , 0 );
214
- if (!priv -> base ) {
215
- err = - ENOMEM ;
261
+ priv -> base = ioremap (addr , size );
262
+ if (!priv -> base )
216
263
goto free_priv ;
217
- }
218
264
219
- parent_domain = irq_find_host (parent );
220
- if (!parent_domain ) {
221
- pr_err ("Failed to find the parent domain\n" );
222
- err = - ENXIO ;
223
- goto iounmap_base ;
224
- }
225
-
226
- if (of_property_read_u32 (node , "loongson,pic-base-vec" ,
227
- & priv -> ht_vec_base )) {
228
- pr_err ("Failed to determine pic-base-vec\n" );
229
- err = - EINVAL ;
230
- goto iounmap_base ;
231
- }
265
+ priv -> ht_vec_base = vec_base ;
266
+ priv -> vec_count = ((readq (priv -> base ) >> 48 ) & 0xff ) + 1 ;
267
+ priv -> gsi_base = gsi_base ;
232
268
233
269
priv -> pic_domain = irq_domain_create_hierarchy (parent_domain , 0 ,
234
- PIC_COUNT ,
235
- of_node_to_fwnode (node ),
236
- & pch_pic_domain_ops ,
237
- priv );
270
+ priv -> vec_count , domain_handle ,
271
+ & pch_pic_domain_ops , priv );
272
+
238
273
if (!priv -> pic_domain ) {
239
274
pr_err ("Failed to create IRQ domain\n" );
240
- err = - ENOMEM ;
241
275
goto iounmap_base ;
242
276
}
243
277
244
278
pch_pic_reset (priv );
279
+ pch_pic_handle [nr_pics ] = domain_handle ;
280
+ pch_pic_priv [nr_pics ++ ] = priv ;
245
281
246
282
return 0 ;
247
283
@@ -250,7 +286,86 @@ static int pch_pic_of_init(struct device_node *node,
250
286
free_priv :
251
287
kfree (priv );
252
288
253
- return err ;
289
+ return - EINVAL ;
290
+ }
291
+
292
+ #ifdef CONFIG_OF
293
+
294
+ static int pch_pic_of_init (struct device_node * node ,
295
+ struct device_node * parent )
296
+ {
297
+ int err , vec_base ;
298
+ struct resource res ;
299
+ struct irq_domain * parent_domain ;
300
+
301
+ if (of_address_to_resource (node , 0 , & res ))
302
+ return - EINVAL ;
303
+
304
+ parent_domain = irq_find_host (parent );
305
+ if (!parent_domain ) {
306
+ pr_err ("Failed to find the parent domain\n" );
307
+ return - ENXIO ;
308
+ }
309
+
310
+ if (of_property_read_u32 (node , "loongson,pic-base-vec" , & vec_base )) {
311
+ pr_err ("Failed to determine pic-base-vec\n" );
312
+ return - EINVAL ;
313
+ }
314
+
315
+ err = pch_pic_init (res .start , resource_size (& res ), vec_base ,
316
+ parent_domain , of_node_to_fwnode (node ), 0 );
317
+ if (err < 0 )
318
+ return err ;
319
+
320
+ return 0 ;
254
321
}
255
322
256
323
IRQCHIP_DECLARE (pch_pic , "loongson,pch-pic-1.0" , pch_pic_of_init );
324
+
325
+ #endif
326
+
327
+ #ifdef CONFIG_ACPI
328
+ static int __init
329
+ pch_lpc_parse_madt (union acpi_subtable_headers * header ,
330
+ const unsigned long end )
331
+ {
332
+ struct acpi_madt_lpc_pic * pchlpc_entry = (struct acpi_madt_lpc_pic * )header ;
333
+
334
+ return pch_lpc_acpi_init (pch_pic_priv [0 ]-> pic_domain , pchlpc_entry );
335
+ }
336
+
337
+ static int __init acpi_cascade_irqdomain_init (void )
338
+ {
339
+ acpi_table_parse_madt (ACPI_MADT_TYPE_LPC_PIC ,
340
+ pch_lpc_parse_madt , 0 );
341
+ return 0 ;
342
+ }
343
+
344
+ int __init pch_pic_acpi_init (struct irq_domain * parent ,
345
+ struct acpi_madt_bio_pic * acpi_pchpic )
346
+ {
347
+ int ret , vec_base ;
348
+ struct fwnode_handle * domain_handle ;
349
+
350
+ vec_base = acpi_pchpic -> gsi_base - GSI_MIN_PCH_IRQ ;
351
+
352
+ domain_handle = irq_domain_alloc_fwnode ((phys_addr_t * )acpi_pchpic );
353
+ if (!domain_handle ) {
354
+ pr_err ("Unable to allocate domain handle\n" );
355
+ return - ENOMEM ;
356
+ }
357
+
358
+ ret = pch_pic_init (acpi_pchpic -> address , acpi_pchpic -> size ,
359
+ vec_base , parent , domain_handle , acpi_pchpic -> gsi_base );
360
+
361
+ if (ret < 0 ) {
362
+ irq_domain_free_fwnode (domain_handle );
363
+ return ret ;
364
+ }
365
+
366
+ if (acpi_pchpic -> id == 0 )
367
+ acpi_cascade_irqdomain_init ();
368
+
369
+ return ret ;
370
+ }
371
+ #endif
0 commit comments