Skip to content

Commit b2c4c39

Browse files
zhangqingmytsbogend
authored andcommitted
irqchip/loongson-liointc: irqchip add 2.0 version
Add IO interrupt controller support for Loongson-2K1000, different from the Loongson-3A series is that Loongson-2K1000 has 64 interrupt sources, 0-31 correspond to the device tree liointc0 device node, and the other correspond to liointc1 node. Signed-off-by: Jiaxun Yang <[email protected]> Signed-off-by: Qing Zhang <[email protected]> Tested-by: Ming Wang <[email protected]> Acked-by: Marc Zyngier <[email protected]> Signed-off-by: Thomas Bogendoerfer <[email protected]>
1 parent 44151ea commit b2c4c39

File tree

1 file changed

+49
-9
lines changed

1 file changed

+49
-9
lines changed

drivers/irqchip/irq-loongson-liointc.c

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#define LIOINTC_CHIP_IRQ 32
2222
#define LIOINTC_NUM_PARENT 4
23+
#define LIOINTC_NUM_CORES 4
2324

2425
#define LIOINTC_INTC_CHIP_START 0x20
2526

@@ -42,6 +43,7 @@ struct liointc_handler_data {
4243
struct liointc_priv {
4344
struct irq_chip_generic *gc;
4445
struct liointc_handler_data handler[LIOINTC_NUM_PARENT];
46+
void __iomem *core_isr[LIOINTC_NUM_CORES];
4547
u8 map_cache[LIOINTC_CHIP_IRQ];
4648
bool has_lpc_irq_errata;
4749
};
@@ -51,11 +53,12 @@ static void liointc_chained_handle_irq(struct irq_desc *desc)
5153
struct liointc_handler_data *handler = irq_desc_get_handler_data(desc);
5254
struct irq_chip *chip = irq_desc_get_chip(desc);
5355
struct irq_chip_generic *gc = handler->priv->gc;
56+
int core = get_ebase_cpunum() % LIOINTC_NUM_CORES;
5457
u32 pending;
5558

5659
chained_irq_enter(chip, desc);
5760

58-
pending = readl(gc->reg_base + LIOINTC_REG_INTC_STATUS);
61+
pending = readl(handler->priv->core_isr[core]);
5962

6063
if (!pending) {
6164
/* Always blame LPC IRQ if we have that bug */
@@ -141,6 +144,18 @@ static void liointc_resume(struct irq_chip_generic *gc)
141144
}
142145

143146
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+
}
144159

145160
static int __init liointc_of_init(struct device_node *node,
146161
struct device_node *parent)
@@ -159,10 +174,28 @@ static int __init liointc_of_init(struct device_node *node,
159174
if (!priv)
160175
return -ENOMEM;
161176

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;
166199
}
167200

168201
for (i = 0; i < LIOINTC_NUM_PARENT; i++) {
@@ -172,7 +205,7 @@ static int __init liointc_of_init(struct device_node *node,
172205
}
173206
if (!have_parent) {
174207
err = -ENODEV;
175-
goto out_iounmap;
208+
goto out_iounmap_isr;
176209
}
177210

178211
sz = of_property_read_variable_u32_array(node,
@@ -183,7 +216,7 @@ static int __init liointc_of_init(struct device_node *node,
183216
if (sz < 4) {
184217
pr_err("loongson-liointc: No parent_int_map\n");
185218
err = -ENODEV;
186-
goto out_iounmap;
219+
goto out_iounmap_isr;
187220
}
188221

189222
for (i = 0; i < LIOINTC_NUM_PARENT; i++)
@@ -195,7 +228,7 @@ static int __init liointc_of_init(struct device_node *node,
195228
if (!domain) {
196229
pr_err("loongson-liointc: cannot add IRQ domain\n");
197230
err = -EINVAL;
198-
goto out_iounmap;
231+
goto out_iounmap_isr;
199232
}
200233

201234
err = irq_alloc_domain_generic_chips(domain, 32, 1,
@@ -260,7 +293,13 @@ static int __init liointc_of_init(struct device_node *node,
260293

261294
out_free_domain:
262295
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:
264303
iounmap(base);
265304
out_free_priv:
266305
kfree(priv);
@@ -270,3 +309,4 @@ static int __init liointc_of_init(struct device_node *node,
270309

271310
IRQCHIP_DECLARE(loongson_liointc_1_0, "loongson,liointc-1.0", liointc_of_init);
272311
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

Comments
 (0)