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:
committed by
Arnd Bergmann
parent
c71a54b082
commit
6d274309d0
@@ -47,6 +47,7 @@ struct irq_domain_ops {
|
|||||||
* of the irq_domain is responsible for allocating the array of
|
* of the irq_domain is responsible for allocating the array of
|
||||||
* irq_desc structures.
|
* irq_desc structures.
|
||||||
* @nr_irq: Number of irqs managed by the irq domain
|
* @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
|
* @ops: pointer to irq_domain methods
|
||||||
* @priv: private data pointer for use by owner. Not touched by irq_domain
|
* @priv: private data pointer for use by owner. Not touched by irq_domain
|
||||||
* core code.
|
* core code.
|
||||||
@@ -57,6 +58,7 @@ struct irq_domain {
|
|||||||
struct list_head list;
|
struct list_head list;
|
||||||
unsigned int irq_base;
|
unsigned int irq_base;
|
||||||
unsigned int nr_irq;
|
unsigned int nr_irq;
|
||||||
|
unsigned int hwirq_base;
|
||||||
const struct irq_domain_ops *ops;
|
const struct irq_domain_ops *ops;
|
||||||
void *priv;
|
void *priv;
|
||||||
struct device_node *of_node;
|
struct device_node *of_node;
|
||||||
@@ -72,9 +74,21 @@ struct irq_domain {
|
|||||||
static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
|
static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
|
||||||
unsigned long hwirq)
|
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_add(struct irq_domain *domain);
|
||||||
extern void irq_domain_del(struct irq_domain *domain);
|
extern void irq_domain_del(struct irq_domain *domain);
|
||||||
#endif /* CONFIG_IRQ_DOMAIN */
|
#endif /* CONFIG_IRQ_DOMAIN */
|
||||||
|
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
|
|||||||
void irq_domain_add(struct irq_domain *domain)
|
void irq_domain_add(struct irq_domain *domain)
|
||||||
{
|
{
|
||||||
struct irq_data *d;
|
struct irq_data *d;
|
||||||
int hwirq;
|
int hwirq, irq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This assumes that the irq_domain owner has already allocated
|
* This assumes that the irq_domain owner has already allocated
|
||||||
* the irq_descs. This block will be removed when support for dynamic
|
* the irq_descs. This block will be removed when support for dynamic
|
||||||
* allocation of irq_descs is added to irq_domain.
|
* allocation of irq_descs is added to irq_domain.
|
||||||
*/
|
*/
|
||||||
for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
|
irq_domain_for_each_irq(domain, hwirq, irq) {
|
||||||
d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
|
d = irq_get_irq_data(irq);
|
||||||
if (!d) {
|
if (!d) {
|
||||||
WARN(1, "error: assigning domain to non existant irq_desc");
|
WARN(1, "error: assigning domain to non existant irq_desc");
|
||||||
return;
|
return;
|
||||||
@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
|
|||||||
void irq_domain_del(struct irq_domain *domain)
|
void irq_domain_del(struct irq_domain *domain)
|
||||||
{
|
{
|
||||||
struct irq_data *d;
|
struct irq_data *d;
|
||||||
int hwirq;
|
int hwirq, irq;
|
||||||
|
|
||||||
mutex_lock(&irq_domain_mutex);
|
mutex_lock(&irq_domain_mutex);
|
||||||
list_del(&domain->list);
|
list_del(&domain->list);
|
||||||
mutex_unlock(&irq_domain_mutex);
|
mutex_unlock(&irq_domain_mutex);
|
||||||
|
|
||||||
/* Clear the irq_domain assignments */
|
/* Clear the irq_domain assignments */
|
||||||
for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
|
irq_domain_for_each_irq(domain, hwirq, irq) {
|
||||||
d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
|
d = irq_get_irq_data(irq);
|
||||||
d->domain = NULL;
|
d->domain = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user