summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-24 11:23:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-24 11:23:45 -0400
commit836ee4874e201a5907f9658fb2bf3527dd952d30 (patch)
tree34a9e521bbba61d127794278e7b14d96797273f4 /drivers/irqchip
parentfb65d872d7a8dc629837a49513911d0281577bfd (diff)
parent7676fa70feb2f3bcdd4b854a553a57d8ef8505aa (diff)
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull initial ACPI support for arm64 from Will Deacon: "This series introduces preliminary ACPI 5.1 support to the arm64 kernel using the "hardware reduced" profile. We don't support any peripherals yet, so it's fairly limited in scope: - MEMORY init (UEFI) - ACPI discovery (RSDP via UEFI) - CPU init (FADT) - GIC init (MADT) - SMP boot (MADT + PSCI) - ACPI Kconfig options (dependent on EXPERT) ACPI for arm64 has been in development for a while now and hardware has been available that can boot with either FDT or ACPI tables. This has been made possible by both changes to the ACPI spec to cater for ARM-based machines (known as "hardware-reduced" in ACPI parlance) but also a Linaro-driven effort to get this supported on top of the Linux kernel. This pull request is the result of that work. These changes allow us to initialise the CPUs, interrupt controller, and timers via ACPI tables, with memory information and cmdline coming from EFI. We don't support a hybrid ACPI/FDT scheme. Of course, there is still plenty of work to do (a serial console would be nice!) but I expect that to happen on a per-driver basis after this core series has been merged. Anyway, the diff stat here is fairly horrible, but splitting this up and merging it via all the different subsystems would have been extremely painful. Instead, we've got all the relevant Acks in place and I've not seen anything other than trivial (Kconfig) conflicts in -next (for completeness, I've included my resolution below). Nearly half of the insertions fall under Documentation/. So, we'll see how this goes. Right now, it all depends on EXPERT and I fully expect people to use FDT by default for the immediate future" * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (31 commits) ARM64 / ACPI: make acpi_map_gic_cpu_interface() as void function ARM64 / ACPI: Ignore the return error value of acpi_map_gic_cpu_interface() ARM64 / ACPI: fix usage of acpi_map_gic_cpu_interface ARM64: kernel: acpi: honour acpi=force command line parameter ARM64: kernel: acpi: refactor ACPI tables init and checks ARM64: kernel: psci: let ACPI probe PSCI version ARM64: kernel: psci: factor out probe function ACPI: move arm64 GSI IRQ model to generic GSI IRQ layer ARM64 / ACPI: Don't unflatten device tree if acpi=force is passed ARM64 / ACPI: additions of ACPI documentation for arm64 Documentation: ACPI for ARM64 ARM64 / ACPI: Enable ARM64 in Kconfig XEN / ACPI: Make XEN ACPI depend on X86 ARM64 / ACPI: Select ACPI_REDUCED_HARDWARE_ONLY if ACPI is enabled on ARM64 clocksource / arch_timer: Parse GTDT to initialize arch timer irqchip: Add GICv2 specific ACPI boot support ARM64 / ACPI: Introduce ACPI_IRQ_MODEL_GIC and register device's gsi ACPI / processor: Make it possible to get CPU hardware ID via GICC ACPI / processor: Introduce phys_cpuid_t for CPU hardware ID ARM64 / ACPI: Parse MADT for SMP initialization ...
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic.c104
-rw-r--r--drivers/irqchip/irqchip.c3
2 files changed, 107 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index a6ce3476834e..7b315e385ba3 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -33,12 +33,14 @@
33#include <linux/of.h> 33#include <linux/of.h>
34#include <linux/of_address.h> 34#include <linux/of_address.h>
35#include <linux/of_irq.h> 35#include <linux/of_irq.h>
36#include <linux/acpi.h>
36#include <linux/irqdomain.h> 37#include <linux/irqdomain.h>
37#include <linux/interrupt.h> 38#include <linux/interrupt.h>
38#include <linux/percpu.h> 39#include <linux/percpu.h>
39#include <linux/slab.h> 40#include <linux/slab.h>
40#include <linux/irqchip/chained_irq.h> 41#include <linux/irqchip/chained_irq.h>
41#include <linux/irqchip/arm-gic.h> 42#include <linux/irqchip/arm-gic.h>
43#include <linux/irqchip/arm-gic-acpi.h>
42 44
43#include <asm/cputype.h> 45#include <asm/cputype.h>
44#include <asm/irq.h> 46#include <asm/irq.h>
@@ -1107,3 +1109,105 @@ IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
1107IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); 1109IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
1108 1110
1109#endif 1111#endif
1112
1113#ifdef CONFIG_ACPI
1114static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
1115
1116static int __init
1117gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
1118 const unsigned long end)
1119{
1120 struct acpi_madt_generic_interrupt *processor;
1121 phys_addr_t gic_cpu_base;
1122 static int cpu_base_assigned;
1123
1124 processor = (struct acpi_madt_generic_interrupt *)header;
1125
1126 if (BAD_MADT_ENTRY(processor, end))
1127 return -EINVAL;
1128
1129 /*
1130 * There is no support for non-banked GICv1/2 register in ACPI spec.
1131 * All CPU interface addresses have to be the same.
1132 */
1133 gic_cpu_base = processor->base_address;
1134 if (cpu_base_assigned && gic_cpu_base != cpu_phy_base)
1135 return -EINVAL;
1136
1137 cpu_phy_base = gic_cpu_base;
1138 cpu_base_assigned = 1;
1139 return 0;
1140}
1141
1142static int __init
1143gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
1144 const unsigned long end)
1145{
1146 struct acpi_madt_generic_distributor *dist;
1147
1148 dist = (struct acpi_madt_generic_distributor *)header;
1149
1150 if (BAD_MADT_ENTRY(dist, end))
1151 return -EINVAL;
1152
1153 dist_phy_base = dist->base_address;
1154 return 0;
1155}
1156
1157int __init
1158gic_v2_acpi_init(struct acpi_table_header *table)
1159{
1160 void __iomem *cpu_base, *dist_base;
1161 int count;
1162
1163 /* Collect CPU base addresses */
1164 count = acpi_parse_entries(ACPI_SIG_MADT,
1165 sizeof(struct acpi_table_madt),
1166 gic_acpi_parse_madt_cpu, table,
1167 ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
1168 if (count <= 0) {
1169 pr_err("No valid GICC entries exist\n");
1170 return -EINVAL;
1171 }
1172
1173 /*
1174 * Find distributor base address. We expect one distributor entry since
1175 * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
1176 */
1177 count = acpi_parse_entries(ACPI_SIG_MADT,
1178 sizeof(struct acpi_table_madt),
1179 gic_acpi_parse_madt_distributor, table,
1180 ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
1181 if (count <= 0) {
1182 pr_err("No valid GICD entries exist\n");
1183 return -EINVAL;
1184 } else if (count > 1) {
1185 pr_err("More than one GICD entry detected\n");
1186 return -EINVAL;
1187 }
1188
1189 cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
1190 if (!cpu_base) {
1191 pr_err("Unable to map GICC registers\n");
1192 return -ENOMEM;
1193 }
1194
1195 dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE);
1196 if (!dist_base) {
1197 pr_err("Unable to map GICD registers\n");
1198 iounmap(cpu_base);
1199 return -ENOMEM;
1200 }
1201
1202 /*
1203 * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
1204 * as default IRQ domain to allow for GSI registration and GSI to IRQ
1205 * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
1206 */
1207 gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
1208 irq_set_default_host(gic_data[0].domain);
1209
1210 acpi_irq_model = ACPI_IRQ_MODEL_GIC;
1211 return 0;
1212}
1213#endif
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
index 0fe2f718d81c..afd1af3dfe5a 100644
--- a/drivers/irqchip/irqchip.c
+++ b/drivers/irqchip/irqchip.c
@@ -8,6 +8,7 @@
8 * warranty of any kind, whether express or implied. 8 * warranty of any kind, whether express or implied.
9 */ 9 */
10 10
11#include <linux/acpi_irq.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/of_irq.h> 13#include <linux/of_irq.h>
13#include <linux/irqchip.h> 14#include <linux/irqchip.h>
@@ -26,4 +27,6 @@ extern struct of_device_id __irqchip_of_table[];
26void __init irqchip_init(void) 27void __init irqchip_init(void)
27{ 28{
28 of_irq_init(__irqchip_of_table); 29 of_irq_init(__irqchip_of_table);
30
31 acpi_irq_init();
29} 32}