Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a1091ef authored by Yingjoe Chen's avatar Yingjoe Chen Committed by Jason Cooper
Browse files

irqchip: gic: Support hierarchy irq domain.

parent b3a92e2c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ config IRQCHIP
config ARM_GIC
	bool
	select IRQ_DOMAIN
	select IRQ_DOMAIN_HIERARCHY
	select MULTI_IRQ_HANDLER

config GIC_NON_BANKED
+53 −24
Original line number Diff line number Diff line
@@ -788,17 +788,16 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
{
	if (hw < 32) {
		irq_set_percpu_devid(irq);
		irq_set_chip_and_handler(irq, &gic_chip,
					 handle_percpu_devid_irq);
		irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
				    handle_percpu_devid_irq, NULL, NULL);
		set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
	} else {
		irq_set_chip_and_handler(irq, &gic_chip,
					 handle_fasteoi_irq);
		irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
				    handle_fasteoi_irq, NULL, NULL);
		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);

		gic_routable_irq_domain_ops->map(d, irq, hw);
	}
	irq_set_chip_data(irq, d->host_data);
	return 0;
}

@@ -858,6 +857,31 @@ static struct notifier_block gic_cpu_notifier = {
};
#endif

static int gic_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 of_phandle_args *irq_data = arg;

	ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
				   irq_data->args_count, &hwirq, &type);
	if (ret)
		return ret;

	for (i = 0; i < nr_irqs; i++)
		gic_irq_domain_map(domain, virq + i, hwirq + i);

	return 0;
}

static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
	.xlate = gic_irq_domain_xlate,
	.alloc = gic_irq_domain_alloc,
	.free = irq_domain_free_irqs_top,
};

static const struct irq_domain_ops gic_irq_domain_ops = {
	.map = gic_irq_domain_map,
	.unmap = gic_irq_domain_unmap,
@@ -947,6 +971,27 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
	for (i = 0; i < NR_GIC_CPU_IF; i++)
		gic_cpu_map[i] = 0xff;

	/*
	 * Find out how many interrupts are supported.
	 * The GIC only supports up to 1020 interrupt sources.
	 */
	gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
	gic_irqs = (gic_irqs + 1) * 32;
	if (gic_irqs > 1020)
		gic_irqs = 1020;
	gic->gic_irqs = gic_irqs;

	if (node) {		/* DT case */
		const struct irq_domain_ops *ops = &gic_irq_domain_hierarchy_ops;

		if (!of_property_read_u32(node, "arm,routable-irqs",
					  &nr_routable_irqs)) {
			ops = &gic_irq_domain_ops;
			gic_irqs = nr_routable_irqs;
		}

		gic->domain = irq_domain_add_linear(node, gic_irqs, ops, gic);
	} else {		/* Non-DT case */
		/*
		 * For primary GICs, skip over SGIs.
		 * For secondary GICs, skip over PPIs, too.
@@ -959,20 +1004,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
			hwirq_base = 32;
		}

	/*
	 * Find out how many interrupts are supported.
	 * The GIC only supports up to 1020 interrupt sources.
	 */
	gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f;
	gic_irqs = (gic_irqs + 1) * 32;
	if (gic_irqs > 1020)
		gic_irqs = 1020;
	gic->gic_irqs = gic_irqs;

		gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */

	if (of_property_read_u32(node, "arm,routable-irqs",
				 &nr_routable_irqs)) {
		irq_base = irq_alloc_descs(irq_start, 16, gic_irqs,
					   numa_node_id());
		if (IS_ERR_VALUE(irq_base)) {
@@ -983,10 +1016,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,

		gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base,
					hwirq_base, &gic_irq_domain_ops, gic);
	} else {
		gic->domain = irq_domain_add_linear(node, nr_routable_irqs,
						    &gic_irq_domain_ops,
						    gic);
	}

	if (WARN_ON(!gic->domain))