aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHanjun Guo <hanjun.guo@linaro.org>2014-05-31 17:38:27 +0800
committerGraeme Gregory <graeme.gregory@linaro.org>2014-07-30 12:59:02 +0100
commita13f790b6fc6583df98fbfbdb544d3c3d6c6bb43 (patch)
treef389af0f27d3ddcb4e0184353d9067ab9408fc24 /drivers
parentc365b3f5bde4b65b502fb01e2fc9aa4d4c078a60 (diff)
ACPI / processor: Make it possible to get CPU hardware ID via GICC
Introduce a new function map_gicc_mpidr() to allow MPIDRs to be obtained from the GICC Structure introduced by ACPI 5.1. MPIDR is the CPU hardware ID as local APIC ID on x86 platform, so we use MPIDR not the GIC CPU interface ID to identify CPUs. Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_core.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 00f48d13a516..fa3d0edd88d1 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -64,6 +64,37 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
return 0;
}
+/*
+ * On ARM platform, MPIDR value is the hardware ID as apic ID
+ * on Intel platforms
+ */
+static int map_gicc_mpidr(struct acpi_subtable_header *entry,
+ int device_declaration, u32 acpi_id, int *mpidr)
+{
+ struct acpi_madt_generic_interrupt *gicc =
+ container_of(entry, struct acpi_madt_generic_interrupt, header);
+
+ if (!(gicc->flags & ACPI_MADT_ENABLED))
+ return -ENODEV;
+
+ /* In the GIC interrupt model, logical processors are
+ * required to have a Processor Device object in the DSDT,
+ * so we should check device_declaration here
+ */
+ if (device_declaration && (gicc->uid == acpi_id)) {
+ /*
+ * Only bits [0:7] Aff0, bits [8:15] Aff1, bits [16:23] Aff2
+ * and bits [32:39] Aff3 are meaningful, so pack the Affx
+ * fields into a single 32 bit identifier to accommodate the
+ * acpi processor drivers.
+ */
+ *mpidr = ((gicc->mpidr & 0xff00000000) >> 8) | gicc->mpidr;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static int map_madt_entry(int type, u32 acpi_id)
{
unsigned long madt_end, entry;
@@ -99,6 +130,9 @@ static int map_madt_entry(int type, u32 acpi_id)
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
if (!map_lsapic_id(header, type, acpi_id, &apic_id))
break;
+ } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
+ if (!map_gicc_mpidr(header, type, acpi_id, &apic_id))
+ break;
}
entry += header->length;
}
@@ -129,6 +163,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
map_lapic_id(header, acpi_id, &apic_id);
} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
map_lsapic_id(header, type, acpi_id, &apic_id);
+ } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
+ map_gicc_mpidr(header, type, acpi_id, &apic_id);
}
exit: