blob: 4eedfe5e2c5f49c2e7ed557ebf83ebb0f6798d4b [file] [log] [blame]
Patrick Rudolphd9078be2024-10-23 15:20:01 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2024 9elements GmbH
4 */
5#include <cpu.h>
6#include <dm.h>
Patrick Rudolph613f1ed2024-10-23 15:20:06 +02007#include <irq.h>
Patrick Rudolphd9078be2024-10-23 15:20:01 +02008#include <acpi/acpigen.h>
9#include <asm/armv8/cpu.h>
Patrick Rudolphd9078be2024-10-23 15:20:01 +020010#include <asm/io.h>
Patrick Rudolph613f1ed2024-10-23 15:20:06 +020011#include <dm/acpi.h>
Patrick Rudolphd9078be2024-10-23 15:20:01 +020012#include <linux/bitops.h>
13#include <linux/printk.h>
14#include <linux/sizes.h>
15
16static int armv8_cpu_get_desc(const struct udevice *dev, char *buf, int size)
17{
18 int cpuid;
19
20 cpuid = (read_midr() & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT;
21
22 snprintf(buf, size, "CPU MIDR %04x", cpuid);
23
24 return 0;
25}
26
27static int armv8_cpu_get_info(const struct udevice *dev,
28 struct cpu_info *info)
29{
30 info->cpu_freq = 0;
31 info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU);
32
33 return 0;
34}
35
36static int armv8_cpu_get_count(const struct udevice *dev)
37{
38 return uclass_id_count(UCLASS_CPU);
39}
40
41#ifdef CONFIG_ACPIGEN
42int armv8_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
43{
44 uint core_id = dev_seq(dev);
45
46 acpigen_write_processor_device(ctx, core_id);
47
48 return 0;
49}
50
Patrick Rudolph613f1ed2024-10-23 15:20:06 +020051int armv8_cpu_fill_madt(const struct udevice *dev, struct acpi_ctx *ctx)
52{
53 struct acpi_madt_gicc *gicc;
54 struct cpu_plat *cpu_plat;
55 struct udevice *gic;
56 u64 gicc_gicv = 0;
57 u64 gicc_gich = 0;
58 u64 gicc_gicr_base = 0;
59 u64 gicc_phys_base = 0;
60 u32 gicc_perf_gsiv = 0;
61 u64 gicc_mpidr;
62 u32 gicc_vgic_maint_irq = 0;
63 int addr_index;
64 fdt_addr_t addr;
65 int ret;
66 struct irq req_irq;
67
68 cpu_plat = dev_get_parent_plat(dev);
69 if (!cpu_plat)
70 return 0;
71
72 ret = irq_get_interrupt_parent(dev, &gic);
73 if (ret) {
74 log_err("%s: Failed to find interrupt parent for %s\n",
75 __func__, dev->name);
76 return -ENODEV;
77 }
78
79 addr_index = 1;
80
81 if (device_is_compatible(gic, "arm,gic-v3")) {
82 addr = dev_read_addr_index(gic, addr_index++);
83 if (addr != FDT_ADDR_T_NONE)
84 gicc_gicr_base = addr;
85 }
86
87 addr = dev_read_addr_index(gic, addr_index++);
88 if (addr != FDT_ADDR_T_NONE)
89 gicc_phys_base = addr;
90
91 addr = dev_read_addr_index(gic, addr_index++);
92 if (addr != FDT_ADDR_T_NONE)
93 gicc_gich = addr;
94
95 addr = dev_read_addr_index(gic, addr_index++);
96 if (addr != FDT_ADDR_T_NONE)
97 gicc_gicv = addr;
98
99 ret = irq_get_by_index(gic, 0, &req_irq);
100 if (!ret)
101 gicc_vgic_maint_irq = req_irq.id;
102
103 gicc_mpidr = dev_read_u64_default(dev, "reg", 0);
104 if (!gicc_mpidr)
105 gicc_mpidr = dev_read_u32_default(dev, "reg", 0);
106
107 /*
108 * gicc_vgic_maint_irq and gicc_gicv are the same for every CPU
109 */
110 gicc = ctx->current;
111 acpi_write_madt_gicc(gicc,
112 dev_seq(dev),
113 gicc_perf_gsiv, /* FIXME: needs a PMU driver */
114 gicc_phys_base,
115 gicc_gicv,
116 gicc_gich,
117 gicc_vgic_maint_irq,
118 gicc_gicr_base,
119 gicc_mpidr,
120 0); /* FIXME: Not defined in DT */
121
122 acpi_inc(ctx, gicc->length);
123
124 return 0;
125}
126
Patrick Rudolphd9078be2024-10-23 15:20:01 +0200127struct acpi_ops armv8_cpu_acpi_ops = {
128 .fill_ssdt = armv8_cpu_fill_ssdt,
Patrick Rudolph613f1ed2024-10-23 15:20:06 +0200129 .fill_madt = armv8_cpu_fill_madt,
Patrick Rudolphd9078be2024-10-23 15:20:01 +0200130};
131#endif
132
133static const struct cpu_ops cpu_ops = {
134 .get_count = armv8_cpu_get_count,
135 .get_desc = armv8_cpu_get_desc,
136 .get_info = armv8_cpu_get_info,
137};
138
139static const struct udevice_id cpu_ids[] = {
140 { .compatible = "arm,armv8" },
141 {}
142};
143
144U_BOOT_DRIVER(arm_cpu) = {
145 .name = "arm-cpu",
146 .id = UCLASS_CPU,
147 .of_match = cpu_ids,
148 .ops = &cpu_ops,
149 .flags = DM_FLAG_PRE_RELOC,
150 ACPI_OPS_PTR(&armv8_cpu_acpi_ops)
151};