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: Rob Herring <rob.herring@calxeda.com> Reviewed-by: Jamie Iles <jamie@jamieiles.com> Tested-by: Thomas Abraham <thomas.abraham@linaro.org> Acked-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
c71a54b082
commit
6d274309d0
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue