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