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