summaryrefslogtreecommitdiff
path: root/src/mainboard/arm/rdn2/acpi.c
diff options
context:
space:
mode:
authorNaresh Solanki <naresh.solanki@9elements.com>2023-11-17 02:21:57 +0530
committerMartin L Roth <gaumless@gmail.com>2024-10-16 15:30:31 +0000
commit6d1dbe12d2f869388ddb51e0cef7bf30ce80b255 (patch)
treed6db121cfc41e5d750e00dc80d3cfadda482ea15 /src/mainboard/arm/rdn2/acpi.c
parentf6ecfbc12b4d4c02cc33b1d854ec9a473fe3f2fb (diff)
mb/arm/rdn2: Add support for Arm Neoverse N2
Add support for Arm Neoverse N2 Reference design. Based on Arm Neoverse N2 reference design Revision: Release D TEST=Build Arm Neoverse N2 & make sure there is no error. Change-Id: I17908d3ce773d4a88924bafb1d0e9e2a043c7fbc Signed-off-by: Naresh Solanki <naresh.solanki@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/79103 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Maximilian Brune <maximilian.brune@9elements.com> Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/mainboard/arm/rdn2/acpi.c')
-rw-r--r--src/mainboard/arm/rdn2/acpi.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/mainboard/arm/rdn2/acpi.c b/src/mainboard/arm/rdn2/acpi.c
new file mode 100644
index 0000000000..941c2f4767
--- /dev/null
+++ b/src/mainboard/arm/rdn2/acpi.c
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_iort.h>
+#include <console/console.h>
+#include <mainboard/addressmap.h>
+#include <stdio.h>
+
+void acpi_fill_fadt(acpi_fadt_t *fadt)
+{
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ return current;
+}
+
+uintptr_t platform_get_gicd_base(void)
+{
+ return RDN2_GIC_DIST;
+}
+
+uintptr_t platform_get_gicr_base(void)
+{
+ return RDN2_GIC_REDIST;
+}
+
+void platform_fill_gicc(acpi_madt_gicc_t *gicc)
+{
+ gicc->physical_base_address = platform_get_gicd_base();
+ gicc->gicv = RDN2_VGIC_BASE;
+ gicc->gich = RDN2_HGIC_BASE;
+
+ if (gicc->mpidr >> 16 == 0xf)
+ gicc->trbe_interrupt = 0x180c;
+ else
+ gicc->trbe_interrupt = 0x500b;
+}
+
+static uintptr_t gic_its[] = {
+ RDN2_GIC_ITS(0),
+ RDN2_GIC_ITS(1),
+ RDN2_GIC_ITS(2),
+ RDN2_GIC_ITS(3),
+ RDN2_GIC_ITS(4),
+ RDN2_GIC_ITS(5)
+};
+
+int platform_get_gic_its(uintptr_t **base)
+{
+ *base = gic_its;
+ return ARRAY_SIZE(gic_its);
+}
+
+void mainboard_fill_fadt(acpi_fadt_t *fadt)
+{
+ fadt->preferred_pm_profile = PM_DESKTOP;
+ fadt->ARM_boot_arch = 1;
+}
+
+void acpi_soc_fill_gtdt(acpi_gtdt_t *gtdt)
+{
+ /* his value is optional if the system implements EL3 (Security
+ Extensions). If not provided, this field must be 0xFFFFFFFFFFFFFFFF. */
+ gtdt->counter_block_address = UINT64_MAX;
+ gtdt->secure_el1_interrupt = SEC_EL1_TIMER_GISV;
+ gtdt->secure_el1_flags = RDN2_TIMER_FLAGS;
+ gtdt->non_secure_el1_interrupt = NONSEC_EL1_TIMER_GSIV;
+ gtdt->non_secure_el1_flags = RDN2_TIMER_FLAGS;
+ gtdt->virtual_timer_interrupt = VIRTUAL_TIMER_GSIV;
+ gtdt->virtual_timer_flags = RDN2_TIMER_FLAGS;
+ gtdt->non_secure_el2_interrupt = NONSEC_EL2_TIMER_GSIV;
+ gtdt->non_secure_el2_flags = RDN2_TIMER_FLAGS;
+ /* his value is optional if the system implements EL3
+ (Security Extensions). If not provided, this field must be
+ 0xFFFFFFFFFFFFFFF. */
+ gtdt->counter_read_block_address = UINT64_MAX;
+}
+
+unsigned long acpi_soc_gtdt_add_timers(uint32_t *count, unsigned long current)
+{
+ struct acpi_gtdt_timer_entry timers[2];
+
+ memset(timers, 0, sizeof(timers));
+ (*count)++;
+ timers[0].frame_number = 0;
+ timers[0].base_address = RDN2_GT_FRAME1_CTL_BASE;
+ timers[0].el0_base_address = UINT64_MAX;
+ timers[0].timer_interrupt = RDN2_GT_FRAME1_GSIV;
+ timers[0].timer_flags = 0;
+ timers[0].virtual_timer_interrupt = 0;
+ timers[0].virtual_timer_flags = 0;
+ timers[0].common_flags = ACPI_GTDT_GT_ALWAYS_ON;
+
+
+ (*count)++;
+ timers[1].frame_number = 1;
+ timers[1].base_address = RDN2_GT_FRAME0_CTL_BASE;
+ timers[1].el0_base_address = UINT64_MAX;
+ timers[1].timer_interrupt = RDN2_GT_FRAME0_GSIV;
+ timers[1].timer_flags = 0;
+ timers[1].virtual_timer_interrupt = 0;
+ timers[1].virtual_timer_flags = 0;
+ timers[1].common_flags = ACPI_GTDT_GT_ALWAYS_ON | ACPI_GTDT_GT_IS_SECURE_TIMER;
+
+ current = acpi_gtdt_add_timer_block(current, RDN2_GT_CTL_BASE, timers, 2);
+
+ (*count)++;
+ current = acpi_gtdt_add_watchdog(current, RDN2_GWDT_REFRESH, RDN2_GWDT_CONTROL,
+ RDN2_GWDT_WS0_GSIV, 0);
+ /* Secure */
+ current = acpi_gtdt_add_watchdog(current, RDN2_GWDT_REFRESH, RDN2_GWDT_CONTROL,
+ RDN2_GWDT_WS1_GSIV, ACPI_GTDT_WATCHDOG_SECURE);
+
+ return current;
+}
+
+static unsigned long acpi_soc_fill_iort_tcu4(acpi_iort_t *iort, unsigned long current)
+{
+ acpi_iort_node_t *its, *smmu_v3, *named_comp;
+ u32 identifiers[] = {4};
+ u32 its_reference, smmuv3_reference;
+
+ current = acpi_iort_its_entry(current, iort, &its, 1, identifiers);
+ its_reference = (unsigned long)its - (unsigned long)iort;
+
+ current = acpi_iort_smmuv3_entry(current, iort, &smmu_v3, RDN2_SMMU_V3(4), ACPI_IORT_SMMU_V3_FLAGS);
+ smmuv3_reference = (unsigned long)smmu_v3 - (unsigned long)iort;
+
+ /* Individual maps here */
+ current = acpi_iort_id_map_entry(current, smmu_v3, 0, 1, 0x80000, its_reference,
+ ACPI_IORT_ID_SINGLE_MAPPING);
+
+ current = acpi_iort_id_map_entry(current, smmu_v3, 0x10000, 10, 0x10000, its_reference, 0);
+
+ current = acpi_iort_id_map_entry(current, smmu_v3, 0x30000, 10, 0x30000, its_reference, 0);
+
+ /* SMMUV3 entry length includes mapping */
+
+ for (int n = 0 ; n < 2 ; n++) {
+ /* DMA */
+ char dma[32];
+ snprintf(dma, sizeof(dma), "\\_SB_.DMA%d", n);
+
+ current = acpi_iort_nc_entry(current, iort, &named_comp, 0, 0, 0x30, dma);
+
+ for (int i = 0 ; i < 9 ; i++) {
+ /* ID */
+ current = acpi_iort_id_map_entry(current, named_comp, i, 1, 0x10000 + n * 0x20000 + i,
+ smmuv3_reference, ACPI_IORT_ID_SINGLE_MAPPING);
+ }
+ }
+
+
+ return current;
+}
+
+static unsigned long acpi_soc_fill_iort_tcu(u32 i, u16 id_count, u32 *smmu_offset,
+ acpi_iort_t *iort, unsigned long current)
+{
+
+ acpi_iort_node_t *its, *smmu_v3;
+ static u32 id_base = 0x30000;
+ u32 its_reference;
+
+ current = acpi_iort_its_entry(current, iort, &its, 1, &i);
+ its_reference = (unsigned long)its - (unsigned long)iort;
+
+ current = acpi_iort_smmuv3_entry(current, iort, &smmu_v3, RDN2_SMMU_V3(i), ACPI_IORT_SMMU_V3_FLAGS);
+
+ *smmu_offset = (unsigned long)smmu_v3 - (unsigned long)iort;
+
+ /* Individual maps here */
+ current = acpi_iort_id_map_entry(current, smmu_v3, 0, 1, 0x80000, its_reference,
+ ACPI_IORT_ID_SINGLE_MAPPING);
+
+ current = acpi_iort_id_map_entry(current, smmu_v3, id_base, id_count, id_base, its_reference, 0);
+ id_base += id_count;
+
+ /* SMMUV3 entry length includes mapping */
+
+ return current;
+}
+
+unsigned long acpi_soc_fill_iort(acpi_iort_t *iort, unsigned long current)
+{
+ acpi_iort_node_t *root_comp;
+ u32 smmu_offset[4];
+ uint32_t id_count[] = {768, 256, 256, 256};
+
+ for (int i = 0; i < 4; i++)
+ current = acpi_soc_fill_iort_tcu(i, id_count[i], &smmu_offset[i], iort, current);
+
+ current = acpi_soc_fill_iort_tcu4(iort, current);
+
+ current = acpi_iort_rc_entry(current, iort, &root_comp, 0, ACPI_IORT_ATS_SUPPORTED, 0,
+ 0x30, 0);
+
+ u32 base = 0;
+ for (int i = 0 ; i < 4 ; i++) {
+ current = acpi_iort_id_map_entry(current, root_comp, base, id_count[i], 0x30000 + base,
+ smmu_offset[i], 0);
+ base += id_count[i];
+ }
+
+ return current;
+}