Skip to content

Commit

Permalink
irqchip: Convert all alloc/xlate users from of_node to fwnode
Browse files Browse the repository at this point in the history
Since we now have a generic data structure to express an
interrupt specifier, convert all hierarchical irqchips that
are OF based to use a fwnode_handle as part of their alloc
and xlate (which becomes translate) callbacks.

As most of these drivers have dependencies (they exchange IRQ
specifiers), change them all in a single, massive patch...

Signed-off-by: Marc Zyngier <[email protected]>
Reviewed-and-tested-by: Hanjun Guo <[email protected]>
Tested-by: Lorenzo Pieralisi <[email protected]>
Cc: <[email protected]>
Cc: Tomasz Nowicki <[email protected]>
Cc: Suravee Suthikulpanit <[email protected]>
Cc: Graeme Gregory <[email protected]>
Cc: Jake Oshins <[email protected]>
Cc: Jiang Liu <[email protected]>
Cc: Jason Cooper <[email protected]>
Cc: Rafael J. Wysocki <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
  • Loading branch information
Marc Zyngier authored and KAGA-KOKO committed Oct 13, 2015
1 parent 11e4438 commit f833f57
Show file tree
Hide file tree
Showing 13 changed files with 323 additions and 252 deletions.
55 changes: 29 additions & 26 deletions arch/arm/mach-exynos/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
#endif
};

static int exynos_pmu_domain_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int exynos_pmu_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (irq_domain_get_of_node(domain) != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;

*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;

*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}

return -EINVAL;
}

static int exynos_pmu_domain_alloc(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct of_phandle_args parent_args;
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
int i;

if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */

hwirq = args->args[1];
hwirq = fwspec->param[1];

for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&exynos_pmu_chip, NULL);

parent_args = *args;
parent_args.np = irq_domain_get_of_node(domain->parent);
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
parent_fwspec = *fwspec;
parent_fwspec.fwnode = domain->parent->fwnode;
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
&parent_fwspec);
}

static const struct irq_domain_ops exynos_pmu_domain_ops = {
.xlate = exynos_pmu_domain_xlate,
.alloc = exynos_pmu_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = exynos_pmu_domain_translate,
.alloc = exynos_pmu_domain_alloc,
.free = irq_domain_free_irqs_common,
};

static int __init exynos_pmu_irq_init(struct device_node *node,
Expand Down
55 changes: 29 additions & 26 deletions arch/arm/mach-imx/gpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,56 +181,59 @@ static struct irq_chip imx_gpc_chip = {
#endif
};

static int imx_gpc_domain_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int imx_gpc_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (irq_domain_get_of_node(domain) != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;

*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;

*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}

return -EINVAL;
}

static int imx_gpc_domain_alloc(struct irq_domain *domain,
unsigned int irq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct of_phandle_args parent_args;
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
int i;

if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */

hwirq = args->args[1];
hwirq = fwspec->param[1];
if (hwirq >= GPC_MAX_IRQS)
return -EINVAL; /* Can't deal with this */

for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
&imx_gpc_chip, NULL);

parent_args = *args;
parent_args.np = irq_domain_get_of_node(domain->parent);
return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
parent_fwspec = *fwspec;
parent_fwspec.fwnode = domain->parent->fwnode;
return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
&parent_fwspec);
}

static const struct irq_domain_ops imx_gpc_domain_ops = {
.xlate = imx_gpc_domain_xlate,
.alloc = imx_gpc_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = imx_gpc_domain_translate,
.alloc = imx_gpc_domain_alloc,
.free = irq_domain_free_irqs_common,
};

static int __init imx_gpc_init(struct device_node *node,
Expand Down
55 changes: 29 additions & 26 deletions arch/arm/mach-omap2/omap-wakeupgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,56 +399,59 @@ static struct irq_chip wakeupgen_chip = {
#endif
};

static int wakeupgen_domain_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int wakeupgen_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (irq_domain_get_of_node(domain) != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;

*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;

*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}

return -EINVAL;
}

static int wakeupgen_domain_alloc(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct of_phandle_args parent_args;
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
int i;

if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */

hwirq = args->args[1];
hwirq = fwspec->param[1];
if (hwirq >= MAX_IRQS)
return -EINVAL; /* Can't deal with this */

for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&wakeupgen_chip, NULL);

parent_args = *args;
parent_args.np = irq_domain_get_of_node(domain->parent);
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
parent_fwspec = *fwspec;
parent_fwspec.fwnode = domain->parent->fwnode;
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
&parent_fwspec);
}

static const struct irq_domain_ops wakeupgen_domain_ops = {
.xlate = wakeupgen_domain_xlate,
.alloc = wakeupgen_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = wakeupgen_domain_translate,
.alloc = wakeupgen_domain_alloc,
.free = irq_domain_free_irqs_common,
};

/*
Expand Down
62 changes: 34 additions & 28 deletions drivers/irqchip/irq-crossbar.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,13 @@ static struct irq_chip crossbar_chip = {
static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
irq_hw_number_t hwirq)
{
struct of_phandle_args args;
struct irq_fwspec fwspec;
int i;
int err;

if (!irq_domain_get_of_node(domain->parent))
return -EINVAL;

raw_spin_lock(&cb->lock);
for (i = cb->int_max - 1; i >= 0; i--) {
if (cb->irq_map[i] == IRQ_FREE) {
Expand All @@ -94,13 +97,13 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
if (i < 0)
return -ENODEV;

args.np = irq_domain_get_of_node(domain->parent);
args.args_count = 3;
args.args[0] = 0; /* SPI */
args.args[1] = i;
args.args[2] = IRQ_TYPE_LEVEL_HIGH;
fwspec.fwnode = domain->parent->fwnode;
fwspec.param_count = 3;
fwspec.param[0] = 0; /* SPI */
fwspec.param[1] = i;
fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;

err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
if (err)
cb->irq_map[i] = IRQ_FREE;
else
Expand All @@ -112,16 +115,16 @@ static int allocate_gic_irq(struct irq_domain *domain, unsigned virq,
static int crossbar_domain_alloc(struct irq_domain *d, unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct irq_fwspec *fwspec = data;
irq_hw_number_t hwirq;
int i;

if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */

hwirq = args->args[1];
hwirq = fwspec->param[1];
if ((hwirq + nr_irqs) > cb->max_crossbar_sources)
return -EINVAL; /* Can't deal with this */

Expand Down Expand Up @@ -166,28 +169,31 @@ static void crossbar_domain_free(struct irq_domain *domain, unsigned int virq,
raw_spin_unlock(&cb->lock);
}

static int crossbar_domain_xlate(struct irq_domain *d,
struct device_node *controller,
const u32 *intspec, unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int crossbar_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (irq_domain_get_of_node(d) != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;

*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;

*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}

return -EINVAL;
}

static const struct irq_domain_ops crossbar_domain_ops = {
.alloc = crossbar_domain_alloc,
.free = crossbar_domain_free,
.xlate = crossbar_domain_xlate,
.alloc = crossbar_domain_alloc,
.free = crossbar_domain_free,
.translate = crossbar_domain_translate,
};

static int __init crossbar_of_init(struct device_node *node)
Expand Down
18 changes: 11 additions & 7 deletions drivers/irqchip/irq-gic-v2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,21 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
unsigned int virq,
irq_hw_number_t hwirq)
{
struct of_phandle_args args;
struct irq_fwspec fwspec;
struct irq_data *d;
int err;

args.np = irq_domain_get_of_node(domain->parent);
args.args_count = 3;
args.args[0] = 0;
args.args[1] = hwirq - 32;
args.args[2] = IRQ_TYPE_EDGE_RISING;
if (is_of_node(domain->parent->fwnode)) {
fwspec.fwnode = domain->parent->fwnode;
fwspec.param_count = 3;
fwspec.param[0] = 0;
fwspec.param[1] = hwirq - 32;
fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
} else {
return -EINVAL;
}

err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
if (err)
return err;

Expand Down
Loading

0 comments on commit f833f57

Please sign in to comment.