3333#define PIC_REG_IDX (irq_id ) ((irq_id) / PIC_COUNT_PER_REG)
3434#define PIC_REG_BIT (irq_id ) ((irq_id) % PIC_COUNT_PER_REG)
3535
36+ static int nr_pics ;
37+
3638struct pch_pic {
3739 void __iomem * base ;
3840 struct irq_domain * pic_domain ;
3941 u32 ht_vec_base ;
4042 raw_spinlock_t pic_lock ;
43+ u32 vec_count ;
44+ u32 gsi_base ;
4145};
4246
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+
4370static void pch_pic_bitset (struct pch_pic * priv , int offset , int bit )
4471{
4572 u32 reg ;
@@ -139,6 +166,28 @@ static struct irq_chip pch_pic_irq_chip = {
139166 .irq_set_type = pch_pic_set_type ,
140167};
141168
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+
142191static int pch_pic_alloc (struct irq_domain * domain , unsigned int virq ,
143192 unsigned int nr_irqs , void * arg )
144193{
@@ -149,13 +198,13 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
149198 struct irq_fwspec parent_fwspec ;
150199 struct pch_pic * priv = domain -> host_data ;
151200
152- err = irq_domain_translate_twocell (domain , fwspec , & hwirq , & type );
201+ err = pch_pic_domain_translate (domain , fwspec , & hwirq , & type );
153202 if (err )
154203 return err ;
155204
156205 parent_fwspec .fwnode = domain -> parent -> fwnode ;
157206 parent_fwspec .param_count = 1 ;
158- parent_fwspec .param [0 ] = hwirq + priv -> ht_vec_base ;
207+ parent_fwspec .param [0 ] = hwirq ;
159208
160209 err = irq_domain_alloc_irqs_parent (domain , virq , 1 , & parent_fwspec );
161210 if (err )
@@ -170,7 +219,7 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
170219}
171220
172221static const struct irq_domain_ops pch_pic_domain_ops = {
173- .translate = irq_domain_translate_twocell ,
222+ .translate = pch_pic_domain_translate ,
174223 .alloc = pch_pic_alloc ,
175224 .free = irq_domain_free_irqs_parent ,
176225};
@@ -180,7 +229,7 @@ static void pch_pic_reset(struct pch_pic *priv)
180229 int i ;
181230
182231 for (i = 0 ; i < PIC_COUNT ; i ++ ) {
183- /* Write vectored ID */
232+ /* Write vector ID */
184233 writeb (priv -> ht_vec_base + i , priv -> base + PCH_INT_HTVEC (i ));
185234 /* Hardcode route to HT0 Lo */
186235 writeb (1 , priv -> base + PCH_INT_ROUTE (i ));
@@ -198,50 +247,37 @@ static void pch_pic_reset(struct pch_pic *priv)
198247 }
199248}
200249
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 )
203253{
204254 struct pch_pic * priv ;
205- struct irq_domain * parent_domain ;
206- int err ;
207255
208256 priv = kzalloc (sizeof (* priv ), GFP_KERNEL );
209257 if (!priv )
210258 return - ENOMEM ;
211259
212260 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 )
216263 goto free_priv ;
217- }
218264
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 ;
232268
233269 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+
238273 if (!priv -> pic_domain ) {
239274 pr_err ("Failed to create IRQ domain\n" );
240- err = - ENOMEM ;
241275 goto iounmap_base ;
242276 }
243277
244278 pch_pic_reset (priv );
279+ pch_pic_handle [nr_pics ] = domain_handle ;
280+ pch_pic_priv [nr_pics ++ ] = priv ;
245281
246282 return 0 ;
247283
@@ -250,7 +286,86 @@ static int pch_pic_of_init(struct device_node *node,
250286free_priv :
251287 kfree (priv );
252288
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 ;
254321}
255322
256323IRQCHIP_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