diff options
Diffstat (limited to 'drivers/cpu')
| -rw-r--r-- | drivers/cpu/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/cpu/armv8_cpu.c | 80 | ||||
| -rw-r--r-- | drivers/cpu/armv8_cpu.h | 10 |
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 |
