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

Commit 6d274309 authored by Rob Herring's avatar Rob Herring Committed by Arnd Bergmann
Browse files

irq: support domains with non-zero hwirq base



Interrupt controllers can have non-zero starting value for h/w irq numbers.
Adding support in irq_domain allows the domain hwirq numbering to match
the interrupt controllers' numbering.

As this makes looping over irqs for a domain more complicated, add loop
iterators to iterate over all hwirqs and irqs for a domain.

Signed-off-by: default avatarRob Herring <rob.herring@calxeda.com>
Reviewed-by: default avatarJamie Iles <jamie@jamieiles.com>
Tested-by: default avatarThomas Abraham <thomas.abraham@linaro.org>
Acked-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent c71a54b0
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct irq_domain_ops {
 *            of the irq_domain is responsible for allocating the array of
 *            irq_desc structures.
 * @nr_irq: Number of irqs managed by the irq domain
 * @hwirq_base: Starting number for hwirqs managed by the irq domain
 * @ops: pointer to irq_domain methods
 * @priv: private data pointer for use by owner.  Not touched by irq_domain
 *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
	struct list_head list;
	unsigned int irq_base;
	unsigned int nr_irq;
	unsigned int hwirq_base;
	const struct irq_domain_ops *ops;
	void *priv;
	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
					     unsigned long hwirq)
{
	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
	if (d->ops->to_irq)
		return d->ops->to_irq(d, hwirq);
	if (WARN_ON(hwirq < d->hwirq_base))
		return 0;
	return d->irq_base + hwirq - d->hwirq_base;
}

#define irq_domain_for_each_hwirq(d, hw) \
	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)

#define irq_domain_for_each_irq(d, hw, irq) \
	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
	     hw < d->hwirq_base + d->nr_irq; \
	     hw++, irq = irq_domain_to_irq(d, hw))

extern void irq_domain_add(struct irq_domain *domain);
extern void irq_domain_del(struct irq_domain *domain);
#endif /* CONFIG_IRQ_DOMAIN */
+6 −6
Original line number Diff line number Diff line
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
void irq_domain_add(struct irq_domain *domain)
{
	struct irq_data *d;
	int hwirq;
	int hwirq, irq;

	/*
	 * This assumes that the irq_domain owner has already allocated
	 * the irq_descs.  This block will be removed when support for dynamic
	 * allocation of irq_descs is added to irq_domain.
	 */
	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
	irq_domain_for_each_irq(domain, hwirq, irq) {
		d = irq_get_irq_data(irq);
		if (!d) {
			WARN(1, "error: assigning domain to non existant irq_desc");
			return;
@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
void irq_domain_del(struct irq_domain *domain)
{
	struct irq_data *d;
	int hwirq;
	int hwirq, irq;

	mutex_lock(&irq_domain_mutex);
	list_del(&domain->list);
	mutex_unlock(&irq_domain_mutex);

	/* Clear the irq_domain assignments */
	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
	irq_domain_for_each_irq(domain, hwirq, irq) {
		d = irq_get_irq_data(irq);
		d->domain = NULL;
	}
}