@@ -593,6 +593,7 @@ config LOONGSON_LIOINTC
default y
select IRQ_DOMAIN
select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN_HIERARCHY
help
Support for the Loongson Local I/O Interrupt Controller.
@@ -160,26 +160,48 @@ static u32 parent_int_map[LIOINTC_NUM_PARENT];
static const char *const parent_names[] = {"int0", "int1", "int2", "int3"};
static const char *const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"};
-static int liointc_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
- const u32 *intspec, unsigned int intsize,
- unsigned long *out_hwirq, unsigned int *out_type)
+static int liointc_irq_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec, unsigned long *out_hwirq,
+ unsigned int *out_type)
{
- if (WARN_ON(intsize < 1))
+ if (WARN_ON(fwspec->param_count < 1))
return -EINVAL;
- *out_hwirq = intspec[0] - GSI_MIN_CPU_IRQ;
- if (intsize > 1)
- *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+ if (!acpi_disabled)
+ *out_hwirq = fwspec->param[0] - GSI_MIN_CPU_IRQ;
+ else
+ *out_hwirq = fwspec->param[0];
+
+ if (fwspec->param_count > 1)
+ *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
else
*out_type = IRQ_TYPE_NONE;
return 0;
}
-static const struct irq_domain_ops acpi_irq_gc_ops = {
- .map = irq_map_generic_chip,
- .unmap = irq_unmap_generic_chip,
- .xlate = liointc_domain_xlate,
+static int liointc_irq_domain_alloc(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs, void *arg)
+{
+ int i, ret;
+ irq_hw_number_t hwirq;
+ unsigned int type = IRQ_TYPE_NONE;
+ struct irq_fwspec *fwspec = arg;
+
+ ret = liointc_irq_domain_translate(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < nr_irqs; i++)
+ irq_map_generic_chip(domain, virq + i, hwirq + i);
+
+ return 0;
+}
+
+static const struct irq_domain_ops irq_gc_ops = {
+ .translate = liointc_irq_domain_translate,
+ .alloc = liointc_irq_domain_alloc,
+ .free = irq_domain_free_irqs_top,
};
static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
@@ -222,12 +244,9 @@ static int liointc_init(phys_addr_t addr, unsigned long size, int revision,
}
/* Setup IRQ domain */
- if (!acpi_disabled)
- domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
- &acpi_irq_gc_ops, priv);
- else
- domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
- &irq_generic_chip_ops, priv);
+ domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ,
+ &irq_gc_ops, priv);
+
if (!domain) {
pr_err("loongson-liointc: cannot add IRQ domain\n");
goto out_iounmap;