20
20
21
21
#define LIOINTC_CHIP_IRQ 32
22
22
#define LIOINTC_NUM_PARENT 4
23
+ #define LIOINTC_NUM_CORES 4
23
24
24
25
#define LIOINTC_INTC_CHIP_START 0x20
25
26
@@ -42,6 +43,7 @@ struct liointc_handler_data {
42
43
struct liointc_priv {
43
44
struct irq_chip_generic * gc ;
44
45
struct liointc_handler_data handler [LIOINTC_NUM_PARENT ];
46
+ void __iomem * core_isr [LIOINTC_NUM_CORES ];
45
47
u8 map_cache [LIOINTC_CHIP_IRQ ];
46
48
bool has_lpc_irq_errata ;
47
49
};
@@ -51,11 +53,12 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)
51
53
struct liointc_handler_data * handler = irq_desc_get_handler_data (desc );
52
54
struct irq_chip * chip = irq_desc_get_chip (desc );
53
55
struct irq_chip_generic * gc = handler -> priv -> gc ;
56
+ int core = get_ebase_cpunum () % LIOINTC_NUM_CORES ;
54
57
u32 pending ;
55
58
56
59
chained_irq_enter (chip , desc );
57
60
58
- pending = readl (gc -> reg_base + LIOINTC_REG_INTC_STATUS );
61
+ pending = readl (handler -> priv -> core_isr [ core ] );
59
62
60
63
if (!pending ) {
61
64
/* Always blame LPC IRQ if we have that bug */
@@ -141,6 +144,18 @@ static void liointc_resume(struct irq_chip_generic *gc)
141
144
}
142
145
143
146
static const char * const parent_names [] = {"int0" , "int1" , "int2" , "int3" };
147
+ static const char * const core_reg_names [] = {"isr0" , "isr1" , "isr2" , "isr3" };
148
+
149
+ static void __iomem * liointc_get_reg_byname (struct device_node * node ,
150
+ const char * name )
151
+ {
152
+ int index = of_property_match_string (node , "reg-names" , name );
153
+
154
+ if (index < 0 )
155
+ return NULL ;
156
+
157
+ return of_iomap (node , index );
158
+ }
144
159
145
160
static int __init liointc_of_init (struct device_node * node ,
146
161
struct device_node * parent )
@@ -159,10 +174,28 @@ static int __init liointc_of_init(struct device_node *node,
159
174
if (!priv )
160
175
return - ENOMEM ;
161
176
162
- base = of_iomap (node , 0 );
163
- if (!base ) {
164
- err = - ENODEV ;
165
- goto out_free_priv ;
177
+ if (of_device_is_compatible (node , "loongson,liointc-2.0" )) {
178
+ base = liointc_get_reg_byname (node , "main" );
179
+ if (!base ) {
180
+ err = - ENODEV ;
181
+ goto out_free_priv ;
182
+ }
183
+
184
+ for (i = 0 ; i < LIOINTC_NUM_CORES ; i ++ )
185
+ priv -> core_isr [i ] = liointc_get_reg_byname (node , core_reg_names [i ]);
186
+ if (!priv -> core_isr [0 ]) {
187
+ err = - ENODEV ;
188
+ goto out_iounmap_base ;
189
+ }
190
+ } else {
191
+ base = of_iomap (node , 0 );
192
+ if (!base ) {
193
+ err = - ENODEV ;
194
+ goto out_free_priv ;
195
+ }
196
+
197
+ for (i = 0 ; i < LIOINTC_NUM_CORES ; i ++ )
198
+ priv -> core_isr [i ] = base + LIOINTC_REG_INTC_STATUS ;
166
199
}
167
200
168
201
for (i = 0 ; i < LIOINTC_NUM_PARENT ; i ++ ) {
@@ -172,7 +205,7 @@ static int __init liointc_of_init(struct device_node *node,
172
205
}
173
206
if (!have_parent ) {
174
207
err = - ENODEV ;
175
- goto out_iounmap ;
208
+ goto out_iounmap_isr ;
176
209
}
177
210
178
211
sz = of_property_read_variable_u32_array (node ,
@@ -183,7 +216,7 @@ static int __init liointc_of_init(struct device_node *node,
183
216
if (sz < 4 ) {
184
217
pr_err ("loongson-liointc: No parent_int_map\n" );
185
218
err = - ENODEV ;
186
- goto out_iounmap ;
219
+ goto out_iounmap_isr ;
187
220
}
188
221
189
222
for (i = 0 ; i < LIOINTC_NUM_PARENT ; i ++ )
@@ -195,7 +228,7 @@ static int __init liointc_of_init(struct device_node *node,
195
228
if (!domain ) {
196
229
pr_err ("loongson-liointc: cannot add IRQ domain\n" );
197
230
err = - EINVAL ;
198
- goto out_iounmap ;
231
+ goto out_iounmap_isr ;
199
232
}
200
233
201
234
err = irq_alloc_domain_generic_chips (domain , 32 , 1 ,
@@ -260,7 +293,13 @@ static int __init liointc_of_init(struct device_node *node,
260
293
261
294
out_free_domain :
262
295
irq_domain_remove (domain );
263
- out_iounmap :
296
+ out_iounmap_isr :
297
+ for (i = 0 ; i < LIOINTC_NUM_CORES ; i ++ ) {
298
+ if (!priv -> core_isr [i ])
299
+ continue ;
300
+ iounmap (priv -> core_isr [i ]);
301
+ }
302
+ out_iounmap_base :
264
303
iounmap (base );
265
304
out_free_priv :
266
305
kfree (priv );
@@ -270,3 +309,4 @@ static int __init liointc_of_init(struct device_node *node,
270
309
271
310
IRQCHIP_DECLARE (loongson_liointc_1_0 , "loongson,liointc-1.0" , liointc_of_init );
272
311
IRQCHIP_DECLARE (loongson_liointc_1_0a , "loongson,liointc-1.0a" , liointc_of_init );
312
+ IRQCHIP_DECLARE (loongson_liointc_2_0 , "loongson,liointc-2.0" , liointc_of_init );
0 commit comments