diff options
author | Marc Zyngier <Marc.Zyngier@arm.com> | 2015-09-28 10:49:14 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-09-30 20:18:38 -0400 |
commit | f26527b1428f379fbd7edf779854c3b41bc0b3e5 (patch) | |
tree | 2837a4e9f91658bac81b2060483e432bd55e3678 /drivers/irqchip/irq-gic.c | |
parent | 46e589a391809627144e6bee93d71d73fe915db2 (diff) |
irqchip / GIC: Convert the GIC driver to ACPI probing
Now that we have a basic infrastructure to register irqchips and
call them on discovery of a matching entry in MADT, convert the
GIC driver to this new probing method.
It ends up being a code deletion party, which is a rather good thing.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/irqchip/irq-gic.c')
-rw-r--r-- | drivers/irqchip/irq-gic.c | 69 |
1 files changed, 35 insertions, 34 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 982c09c2d791..d4add30d1d46 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/irqchip.h> | 41 | #include <linux/irqchip.h> |
42 | #include <linux/irqchip/chained_irq.h> | 42 | #include <linux/irqchip/chained_irq.h> |
43 | #include <linux/irqchip/arm-gic.h> | 43 | #include <linux/irqchip/arm-gic.h> |
44 | #include <linux/irqchip/arm-gic-acpi.h> | ||
45 | 44 | ||
46 | #include <asm/cputype.h> | 45 | #include <asm/cputype.h> |
47 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
@@ -1195,7 +1194,7 @@ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); | |||
1195 | #endif | 1194 | #endif |
1196 | 1195 | ||
1197 | #ifdef CONFIG_ACPI | 1196 | #ifdef CONFIG_ACPI |
1198 | static phys_addr_t dist_phy_base, cpu_phy_base __initdata; | 1197 | static phys_addr_t cpu_phy_base __initdata; |
1199 | 1198 | ||
1200 | static int __init | 1199 | static int __init |
1201 | gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, | 1200 | gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, |
@@ -1223,60 +1222,56 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, | |||
1223 | return 0; | 1222 | return 0; |
1224 | } | 1223 | } |
1225 | 1224 | ||
1226 | static int __init | 1225 | /* The things you have to do to just *count* something... */ |
1227 | gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, | 1226 | static int __init acpi_dummy_func(struct acpi_subtable_header *header, |
1228 | const unsigned long end) | 1227 | const unsigned long end) |
1229 | { | 1228 | { |
1230 | struct acpi_madt_generic_distributor *dist; | 1229 | return 0; |
1230 | } | ||
1231 | 1231 | ||
1232 | dist = (struct acpi_madt_generic_distributor *)header; | 1232 | static bool __init acpi_gic_redist_is_present(void) |
1233 | { | ||
1234 | return acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR, | ||
1235 | acpi_dummy_func, 0) > 0; | ||
1236 | } | ||
1233 | 1237 | ||
1234 | if (BAD_MADT_ENTRY(dist, end)) | 1238 | static bool __init gic_validate_dist(struct acpi_subtable_header *header, |
1235 | return -EINVAL; | 1239 | struct acpi_probe_entry *ape) |
1240 | { | ||
1241 | struct acpi_madt_generic_distributor *dist; | ||
1242 | dist = (struct acpi_madt_generic_distributor *)header; | ||
1236 | 1243 | ||
1237 | dist_phy_base = dist->base_address; | 1244 | return (dist->version == ape->driver_data && |
1238 | return 0; | 1245 | (dist->version != ACPI_MADT_GIC_VERSION_NONE || |
1246 | !acpi_gic_redist_is_present())); | ||
1239 | } | 1247 | } |
1240 | 1248 | ||
1241 | int __init | 1249 | #define ACPI_GICV2_DIST_MEM_SIZE (SZ_4K) |
1242 | gic_v2_acpi_init(struct acpi_table_header *table) | 1250 | #define ACPI_GIC_CPU_IF_MEM_SIZE (SZ_8K) |
1251 | |||
1252 | static int __init gic_v2_acpi_init(struct acpi_subtable_header *header, | ||
1253 | const unsigned long end) | ||
1243 | { | 1254 | { |
1255 | struct acpi_madt_generic_distributor *dist; | ||
1244 | void __iomem *cpu_base, *dist_base; | 1256 | void __iomem *cpu_base, *dist_base; |
1245 | int count; | 1257 | int count; |
1246 | 1258 | ||
1247 | /* Collect CPU base addresses */ | 1259 | /* Collect CPU base addresses */ |
1248 | count = acpi_parse_entries(ACPI_SIG_MADT, | 1260 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT, |
1249 | sizeof(struct acpi_table_madt), | 1261 | gic_acpi_parse_madt_cpu, 0); |
1250 | gic_acpi_parse_madt_cpu, table, | ||
1251 | ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0); | ||
1252 | if (count <= 0) { | 1262 | if (count <= 0) { |
1253 | pr_err("No valid GICC entries exist\n"); | 1263 | pr_err("No valid GICC entries exist\n"); |
1254 | return -EINVAL; | 1264 | return -EINVAL; |
1255 | } | 1265 | } |
1256 | 1266 | ||
1257 | /* | ||
1258 | * Find distributor base address. We expect one distributor entry since | ||
1259 | * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade. | ||
1260 | */ | ||
1261 | count = acpi_parse_entries(ACPI_SIG_MADT, | ||
1262 | sizeof(struct acpi_table_madt), | ||
1263 | gic_acpi_parse_madt_distributor, table, | ||
1264 | ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0); | ||
1265 | if (count <= 0) { | ||
1266 | pr_err("No valid GICD entries exist\n"); | ||
1267 | return -EINVAL; | ||
1268 | } else if (count > 1) { | ||
1269 | pr_err("More than one GICD entry detected\n"); | ||
1270 | return -EINVAL; | ||
1271 | } | ||
1272 | |||
1273 | cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE); | 1267 | cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE); |
1274 | if (!cpu_base) { | 1268 | if (!cpu_base) { |
1275 | pr_err("Unable to map GICC registers\n"); | 1269 | pr_err("Unable to map GICC registers\n"); |
1276 | return -ENOMEM; | 1270 | return -ENOMEM; |
1277 | } | 1271 | } |
1278 | 1272 | ||
1279 | dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE); | 1273 | dist = (struct acpi_madt_generic_distributor *)header; |
1274 | dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE); | ||
1280 | if (!dist_base) { | 1275 | if (!dist_base) { |
1281 | pr_err("Unable to map GICD registers\n"); | 1276 | pr_err("Unable to map GICD registers\n"); |
1282 | iounmap(cpu_base); | 1277 | iounmap(cpu_base); |
@@ -1302,4 +1297,10 @@ gic_v2_acpi_init(struct acpi_table_header *table) | |||
1302 | acpi_irq_model = ACPI_IRQ_MODEL_GIC; | 1297 | acpi_irq_model = ACPI_IRQ_MODEL_GIC; |
1303 | return 0; | 1298 | return 0; |
1304 | } | 1299 | } |
1300 | IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, | ||
1301 | gic_validate_dist, ACPI_MADT_GIC_VERSION_V2, | ||
1302 | gic_v2_acpi_init); | ||
1303 | IRQCHIP_ACPI_DECLARE(gic_v2_maybe, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, | ||
1304 | gic_validate_dist, ACPI_MADT_GIC_VERSION_NONE, | ||
1305 | gic_v2_acpi_init); | ||
1305 | #endif | 1306 | #endif |