irqchip/gic: Add helper functions for GIC setup and teardown

Move the code that sets-up a GIC via device-tree into it's own
function and add a generic function for GIC teardown that can be used
for both device-tree and ACPI to unmap the GIC memory.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
Jon Hunter 2016-05-10 16:14:45 +01:00 committed by Marc Zyngier
parent f673b9b5cb
commit d6490461a1
1 changed files with 42 additions and 19 deletions

View File

@ -1197,6 +1197,17 @@ void __init gic_init(unsigned int gic_nr, int irq_start,
__gic_init_bases(gic, irq_start, NULL); __gic_init_bases(gic, irq_start, NULL);
} }
static void gic_teardown(struct gic_chip_data *gic)
{
if (WARN_ON(!gic))
return;
if (gic->raw_dist_base)
iounmap(gic->raw_dist_base);
if (gic->raw_cpu_base)
iounmap(gic->raw_cpu_base);
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int gic_cnt __initdata; static int gic_cnt __initdata;
@ -1238,6 +1249,30 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
return true; return true;
} }
static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
{
if (!gic || !node)
return -EINVAL;
gic->raw_dist_base = of_iomap(node, 0);
if (WARN(!gic->raw_dist_base, "unable to map gic dist registers\n"))
goto error;
gic->raw_cpu_base = of_iomap(node, 1);
if (WARN(!gic->raw_cpu_base, "unable to map gic cpu registers\n"))
goto error;
if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
gic->percpu_offset = 0;
return 0;
error:
gic_teardown(gic);
return -ENOMEM;
}
int __init int __init
gic_of_init(struct device_node *node, struct device_node *parent) gic_of_init(struct device_node *node, struct device_node *parent)
{ {
@ -1252,15 +1287,9 @@ gic_of_init(struct device_node *node, struct device_node *parent)
gic = &gic_data[gic_cnt]; gic = &gic_data[gic_cnt];
gic->raw_dist_base = of_iomap(node, 0); ret = gic_of_setup(gic, node);
if (WARN(!gic->raw_dist_base, "unable to map gic dist registers\n")) if (ret)
return -ENOMEM; return ret;
gic->raw_cpu_base = of_iomap(node, 1);
if (WARN(!gic->raw_cpu_base, "unable to map gic cpu registers\n")) {
iounmap(gic->raw_dist_base);
return -ENOMEM;
}
/* /*
* Disable split EOI/Deactivate if either HYP is not available * Disable split EOI/Deactivate if either HYP is not available
@ -1269,13 +1298,9 @@ gic_of_init(struct device_node *node, struct device_node *parent)
if (gic_cnt == 0 && !gic_check_eoimode(node, &gic->raw_cpu_base)) if (gic_cnt == 0 && !gic_check_eoimode(node, &gic->raw_cpu_base))
static_key_slow_dec(&supports_deactivate); static_key_slow_dec(&supports_deactivate);
if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
gic->percpu_offset = 0;
ret = __gic_init_bases(gic, -1, &node->fwnode); ret = __gic_init_bases(gic, -1, &node->fwnode);
if (ret) { if (ret) {
iounmap(gic->raw_dist_base); gic_teardown(gic);
iounmap(gic->raw_cpu_base);
return ret; return ret;
} }
@ -1388,7 +1413,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
ACPI_GICV2_DIST_MEM_SIZE); ACPI_GICV2_DIST_MEM_SIZE);
if (!gic->raw_dist_base) { if (!gic->raw_dist_base) {
pr_err("Unable to map GICD registers\n"); pr_err("Unable to map GICD registers\n");
iounmap(gic->raw_cpu_base); gic_teardown(gic);
return -ENOMEM; return -ENOMEM;
} }
@ -1406,8 +1431,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base); domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base);
if (!domain_handle) { if (!domain_handle) {
pr_err("Unable to allocate domain handle\n"); pr_err("Unable to allocate domain handle\n");
iounmap(gic->raw_cpu_base); gic_teardown(gic);
iounmap(gic->raw_dist_base);
return -ENOMEM; return -ENOMEM;
} }
@ -1415,8 +1439,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
if (ret) { if (ret) {
pr_err("Failed to initialise GIC\n"); pr_err("Failed to initialise GIC\n");
irq_domain_free_fwnode(domain_handle); irq_domain_free_fwnode(domain_handle);
iounmap(gic->raw_cpu_base); gic_teardown(gic);
iounmap(gic->raw_dist_base);
return ret; return ret;
} }