summaryrefslogtreecommitdiff
path: root/drivers/cpu
diff options
context:
space:
mode:
authorPatrick Rudolph <[email protected]>2024-10-23 15:20:06 +0200
committerTom Rini <[email protected]>2024-10-27 17:24:13 -0600
commit142f92bf0465b0fc9fb59a055c1f25f18d3acaf3 (patch)
treecf8704120c1eb17093b591c33dfbe16f23b3cbf5 /drivers/cpu
parentf116feadea7be9afe412c25779dfcf241c121715 (diff)
drivers/arm: Implement acpi_fill_madt
Fill the MADT table in the GIC driver and armv8 CPU driver to drop SoC specific code. While the GIC only needs devicetree data, the CPU driver needs additional information stored in the cpu_plat struct. While on it update the only board making use of the existing drivers and writing ACPI MADT in mainboard code. TEST: Booted on QEMU sbsa-ref using GICV3 driver model generated MADT. Booted on QEMU raspb4 using GICV2 driver model generated MADT. Signed-off-by: Patrick Rudolph <[email protected]> Reviewed-by: Simon Glass <[email protected]> Cc: Simon Glass <[email protected]>
Diffstat (limited to 'drivers/cpu')
-rw-r--r--drivers/cpu/Kconfig1
-rw-r--r--drivers/cpu/armv8_cpu.c80
-rw-r--r--drivers/cpu/armv8_cpu.h10
3 files changed, 90 insertions, 1 deletions
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
index 9c0df331d7f..4cc3679c009 100644
--- a/drivers/cpu/Kconfig
+++ b/drivers/cpu/Kconfig
@@ -29,6 +29,7 @@ config CPU_RISCV
config CPU_ARMV8
bool "Enable generic ARMv8 CPU driver"
depends on CPU && ARM64
+ select IRQ
help
Support CPU cores for armv8 architecture.
diff --git a/drivers/cpu/armv8_cpu.c b/drivers/cpu/armv8_cpu.c
index 19f072be430..4eedfe5e2c5 100644
--- a/drivers/cpu/armv8_cpu.c
+++ b/drivers/cpu/armv8_cpu.c
@@ -4,10 +4,11 @@
*/
#include <cpu.h>
#include <dm.h>
+#include <irq.h>
#include <acpi/acpigen.h>
#include <asm/armv8/cpu.h>
-#include <dm/acpi.h>
#include <asm/io.h>
+#include <dm/acpi.h>
#include <linux/bitops.h>
#include <linux/printk.h>
#include <linux/sizes.h>
@@ -47,8 +48,85 @@ int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
return 0;
}
+int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
+{
+ struct acpi_madt_gicc *gicc;
+ struct cpu_plat *cpu_plat;
+ struct udevice *gic;
+ u64 gicc_gicv = 0;
+ u64 gicc_gich = 0;
+ u64 gicc_gicr_base = 0;
+ u64 gicc_phys_base = 0;
+ u32 gicc_perf_gsiv = 0;
+ u64 gicc_mpidr;
+ u32 gicc_vgic_maint_irq = 0;
+ int addr_index;
+ fdt_addr_t addr;
+ int ret;
+ struct irq req_irq;
+
+ cpu_plat = dev_get_parent_plat(dev);
+ if (!cpu_plat)
+ return 0;
+
+ ret = irq_get_interrupt_parent(dev, &gic);
+ if (ret) {
+ log_err("%s: Failed to find interrupt parent for %s\n",
+ __func__, dev->name);
+ return -ENODEV;
+ }
+
+ addr_index = 1;
+
+ if (device_is_compatible(gic, "arm,gic-v3")) {
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gicr_base = addr;
+ }
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_phys_base = addr;
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gich = addr;
+
+ addr = dev_read_addr_index(gic, addr_index++);
+ if (addr != FDT_ADDR_T_NONE)
+ gicc_gicv = addr;
+
+ ret = irq_get_by_index(gic, 0, &req_irq);
+ if (!ret)
+ gicc_vgic_maint_irq = req_irq.id;
+
+ gicc_mpidr = dev_read_u64_default(dev, "reg", 0);
+ if (!gicc_mpidr)
+ gicc_mpidr = dev_read_u32_default(dev, "reg", 0);
+
+ /*
+ * gicc_vgic_maint_irq and gicc_gicv are the same for every CPU
+ */
+ gicc = ctx->current;
+ acpi_write_madt_gicc(gicc,
+ dev_seq(dev),
+ gicc_perf_gsiv, /* FIXME: needs a PMU driver */
+ gicc_phys_base,
+ gicc_gicv,
+ gicc_gich,
+ gicc_vgic_maint_irq,
+ gicc_gicr_base,
+ gicc_mpidr,
+ 0); /* FIXME: Not defined in DT */
+
+ acpi_inc(ctx, gicc->length);
+
+ return 0;
+}
+
struct acpi_ops armv8_cpu_acpi_ops = {
.fill_ssdt = armv8_cpu_fill_ssdt,
+ .fill_madt = armv8_cpu_fill_madt,
};
#endif
diff --git a/drivers/cpu/armv8_cpu.h b/drivers/cpu/armv8_cpu.h
index 2c4b0252cf8..48c705e98de 100644
--- a/drivers/cpu/armv8_cpu.h
+++ b/drivers/cpu/armv8_cpu.h
@@ -18,4 +18,14 @@
*/
int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx);
+/**
+ * armv8_cpu_fill_madt() - Fill the MADT
+ * Parses the FDT and writes the MADT subtables.
+ *
+ * @dev: cpu device to generate ACPI tables for
+ * @ctx: ACPI context pointer
+ * @return: 0 if OK, or a negative error code.
+ */
+int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx);
+
#endif \ No newline at end of file