xref: /aosp_15_r20/external/coreboot/src/acpi/acpi_gic.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <device/device.h>
5 
acpi_create_madt_one_gicc_v3(acpi_madt_gicc_t * gicc,u32 acpi_uid,u32 pi_gsiv,uint32_t vgic_mi,uint64_t mpidr)6 static int acpi_create_madt_one_gicc_v3(acpi_madt_gicc_t *gicc, u32 acpi_uid, u32 pi_gsiv,
7 					uint32_t vgic_mi, uint64_t mpidr)
8 {
9 	memset(gicc, 0, sizeof(acpi_madt_gicc_t));
10 	gicc->type = GICC;
11 	gicc->length = sizeof(acpi_madt_gicc_t);
12 	gicc->reserved = 0;
13 	gicc->cpu_interface_number = 0; /* V3, no compat mode */
14 	gicc->acpi_processor_uid = acpi_uid;
15 	gicc->flags.enabled = 1;
16 	gicc->parking_protocol_version = 0; /* Assume PSCI exclusively */
17 	gicc->performance_interrupt_gsiv = pi_gsiv;
18 	gicc->parked_address = 0;
19 	gicc->physical_base_address = 0; /* V3, no compat mode */
20 	gicc->vgic_maintenance_interrupt = vgic_mi;
21 	gicc->gicr_base_address = 0; /* ignored by OSPM if GICR is present */
22 	gicc->processor_power_efficiency_class = 0; /* Ignore for now */
23 	/* For platforms implementing GIC V3 the format must be:
24 	 * Bits [63:40] Must be zero
25 	 * Bits [39:32] Aff3 : Match Aff3 of target processor MPIDR
26 	 * Bits [31:24] Must be zero
27 	 * Bits [23:16] Aff2 : Match Aff2 of target processor MPIDR
28 	 * Bits [15:8] Aff1 : Match Aff1 of target processor MPIDR
29 	 * Bits [7:0] Aff0 : Match Aff0 of target processor MPIDR
30 	*/
31 	gicc->mpidr = mpidr & 0xff00fffffful;
32 
33 	return gicc->length;
34 }
35 
acpi_create_madt_giccs_v3(unsigned long current)36 static unsigned long acpi_create_madt_giccs_v3(unsigned long current)
37 {
38 	// Loop over CPUs GIC
39 	uint32_t acpi_id = 0;
40 	for (struct device *dev = dev_find_path(NULL, DEVICE_PATH_GICC_V3); dev;
41 	     dev = dev_find_path(dev, DEVICE_PATH_GICC_V3)) {
42 		acpi_madt_gicc_t *gicc = (acpi_madt_gicc_t *)current;
43 		current += acpi_create_madt_one_gicc_v3(gicc, acpi_id++,
44 							dev->path.gicc_v3.pi_gsiv,
45 							dev->path.gicc_v3.vgic_mi,
46 							dev->path.gicc_v3.mpidr);
47 	}
48 
49 	return current;
50 }
51 
acpi_create_madt_gicd_v3(unsigned long current)52 static unsigned long acpi_create_madt_gicd_v3(unsigned long current)
53 {
54 	acpi_madt_gicd_t *gicd = (acpi_madt_gicd_t *)current;
55 	memset(gicd, 0, sizeof(acpi_madt_gicd_t));
56 	gicd->type = GICD;
57 	gicd->length = sizeof(acpi_madt_gicd_t);
58 	gicd->physical_base_address = platform_get_gicd_base();
59 	gicd->system_vector_base = 0;
60 	gicd->gic_version = 3;
61 
62 	return current + gicd->length;
63 }
64 
65 /*
66  * The redistributor in GICv3 has two 64KB frames per CPU; in
67  * GICv4 it has four 64KB frames per CPU.
68  */
69 #define GICV3_REDIST_SIZE 0x20000
70 #define GICV4_REDIST_SIZE 0x40000
acpi_create_madt_gicr_v3(unsigned long current)71 static unsigned long acpi_create_madt_gicr_v3(unsigned long current)
72 {
73 	acpi_madt_gicr_t *gicr = (acpi_madt_gicr_t *)current;
74 	memset(gicr, 0, sizeof(acpi_madt_gicr_t));
75 	gicr->type = GICR;
76 	gicr->length = sizeof(acpi_madt_gicr_t);
77 	gicr->discovery_range_base_address = platform_get_gicr_base();
78 	gicr->discovery_range_length = GICV3_REDIST_SIZE * CONFIG_MAX_CPUS;
79 
80 	return current + gicr->length;
81 }
82 
platform_get_gic_its(uintptr_t ** base)83 __weak int platform_get_gic_its(uintptr_t **base)
84 {
85 	return 0;
86 }
87 
acpi_create_madt_gic_its_v3(unsigned long current)88 static unsigned long acpi_create_madt_gic_its_v3(unsigned long current)
89 {
90 	int i, its_count;
91 	uintptr_t *its_base;
92 
93 	its_count = platform_get_gic_its(&its_base);
94 
95 	for (i = 0; i < its_count; i++) {
96 		acpi_madt_gic_its_t *gic_its = (acpi_madt_gic_its_t *)current;
97 		memset(gic_its, 0, sizeof(acpi_madt_gic_its_t));
98 		gic_its->type = GIC_ITS;
99 		gic_its->gic_its_id = i;
100 		gic_its->physical_base_address = its_base[i];
101 		gic_its->length = sizeof(acpi_madt_gic_its_t);
102 
103 		current = current + gic_its->length;
104 	}
105 	return current;
106 }
107 
acpi_arch_fill_madt(acpi_madt_t * madt,unsigned long current)108 unsigned long acpi_arch_fill_madt(acpi_madt_t *madt, unsigned long current)
109 {
110 	current = acpi_create_madt_giccs_v3(current);
111 	current = acpi_create_madt_gicd_v3(current);
112 	current = acpi_create_madt_gicr_v3(current);
113 	current = acpi_create_madt_gic_its_v3(current);
114 
115 	return current;
116 }
117