From 29d1e29d7cb137311529603056ce36ff268f861c Mon Sep 17 00:00:00 2001 From: Jit Loon Lim Date: Mon, 10 Feb 2025 15:15:31 +0800 Subject: [PATCH] feat(intel): add FDT support for Altera products Support FDT for Agilex5 platform 1. Created wrapper file socfpga_dt.c 2. Added in Agilex5 dts file 3. Implemented fdt_check_header 4. Implemented gic configuration 5. Implemented dram configuration Remove init of FDT as Agilex5 has no plan to roll out FDT at the moment. Change-Id: If3990ed9524c6da5b3cb8966b63bc4a95d01fcda Signed-off-by: Jit Loon Lim --- plat/intel/soc/agilex5/bl2_plat_setup.c | 20 ++- plat/intel/soc/agilex5/bl31_plat_setup.c | 21 ++- .../soc/agilex5/include/socfpga_plat_def.h | 4 +- plat/intel/soc/agilex5/platform.mk | 7 +- plat/intel/soc/common/fdts/agilex5_fdt.dts | 92 +++++++++++++ plat/intel/soc/common/include/socfpga_dt.h | 53 ++++++++ plat/intel/soc/common/socfpga_dt.c | 127 ++++++++++++++++++ 7 files changed, 310 insertions(+), 14 deletions(-) create mode 100644 plat/intel/soc/common/fdts/agilex5_fdt.dts create mode 100644 plat/intel/soc/common/include/socfpga_dt.h create mode 100644 plat/intel/soc/common/socfpga_dt.c diff --git a/plat/intel/soc/agilex5/bl2_plat_setup.c b/plat/intel/soc/agilex5/bl2_plat_setup.c index fe5dc6e71..f4010f91c 100644 --- a/plat/intel/soc/agilex5/bl2_plat_setup.c +++ b/plat/intel/soc/agilex5/bl2_plat_setup.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. - * Copyright (c) 2024, Altera Corporation. All rights reserved. + * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -31,6 +31,8 @@ #include "nand/nand.h" #include "qspi/cadence_qspi.h" #include "sdmmc/sdmmc.h" +/* TODO: DTB not available */ +// #include "socfpga_dt.h" #include "socfpga_emac.h" #include "socfpga_f2sdram_manager.h" #include "socfpga_handoff.h" @@ -138,6 +140,12 @@ void bl2_el3_early_platform_setup(u_register_t x0 __unused, /* DDR and IOSSM driver init */ agilex5_ddr_init(&reverse_handoff_ptr); + /* TODO: DTB not available */ + // if (socfpga_dt_open_and_check(SOCFPGA_DTB_BASE, DT_COMPATIBLE_STR) < 0) { + // ERROR("SOCFPGA: Failed to open device tree\n"); + // panic(); + // } + if (combo_phy_init(&reverse_handoff_ptr) != 0) { ERROR("SOCFPGA: Combo Phy initialization failed\n"); } @@ -165,13 +173,13 @@ void bl2_el3_plat_arch_setup(void) switch (boot_source) { case BOOT_SOURCE_SDMMC: - NOTICE("SDMMC boot\n"); + NOTICE("SOCFPGA: SDMMC boot\n"); cdns_mmc_init(¶ms, &mmc_info); socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE); break; case BOOT_SOURCE_QSPI: - NOTICE("QSPI boot\n"); + NOTICE("SOCFPGA: QSPI boot\n"); cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL, QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS, QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0); @@ -182,13 +190,13 @@ void bl2_el3_plat_arch_setup(void) break; case BOOT_SOURCE_NAND: - NOTICE("NAND boot\n"); + NOTICE("SOCFPGA: SOCFPGA: NAND boot\n"); nand_init(&reverse_handoff_ptr); socfpga_io_setup(boot_source, PLAT_NAND_DATA_BASE); break; default: - ERROR("Unsupported boot source\n"); + ERROR("SOCFPGA: Unsupported boot source\n"); panic(); break; } @@ -230,7 +238,7 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) ret = socfpga_vab_init(image_id); if (ret < 0) { - ERROR("SOCFPGA VAB Authentication failed\n"); + ERROR("SOCFPGA: VAB Authentication failed\n"); wfi(); } #endif diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c index 03559e1ff..17d955aec 100644 --- a/plat/intel/soc/agilex5/bl31_plat_setup.c +++ b/plat/intel/soc/agilex5/bl31_plat_setup.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2019-2024, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. - * Copyright (c) 2024, Altera Corporation. All rights reserved. + * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,6 +21,7 @@ #include "agilex5_cache.h" #include "agilex5_power_manager.h" #include "ccu/ncore_ccu.h" +#include "socfpga_dt.h" #include "socfpga_mailbox.h" #include "socfpga_private.h" #include "socfpga_reset_manager.h" @@ -146,7 +147,7 @@ static const interrupt_prop_t agx5_interrupt_props[] = { PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(INTR_GROUP0) }; -static const gicv3_driver_data_t plat_gicv3_gic_data = { +gicv3_driver_data_t plat_gicv3_gic_data = { .gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE, .gicr_base = PLAT_INTEL_SOCFPGA_GICR_BASE, .interrupt_props = agx5_interrupt_props, @@ -162,6 +163,11 @@ void bl31_platform_setup(void) { socfpga_delay_timer_init(); + /* TODO: DTB not available */ + // socfpga_dt_populate_gicv3_config(SOCFPGA_DTB_BASE, &plat_gicv3_gic_data); + // NOTICE("SOCFPGA: GIC GICD base address 0x%lx\n", plat_gicv3_gic_data.gicd_base); + // NOTICE("SOCFPGA: GIC GICR base address 0x%lx\n", plat_gicv3_gic_data.gicr_base); + /* Initialize the gic cpu and distributor interfaces */ gicv3_driver_init(&plat_gicv3_gic_data); gicv3_distif_init(); @@ -192,9 +198,9 @@ void bl31_plat_arch_setup(void) cpuid = MPIDR_AFFLVL1_VAL(read_mpidr()); boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10); - NOTICE("BL31: Boot Core = %x\n", boot_core); - NOTICE("BL31: CPU ID = %x\n", cpuid); - INFO("BL31: Invalidate Data cache\n"); + NOTICE("SOCFPGA: Boot Core = %x\n", boot_core); + NOTICE("SOCFPGA: CPU ID = %x\n", cpuid); + INFO("SOCFPGA: Invalidate Data cache\n"); invalidate_dcache_all(); /* Invalidate for NS EL2 and EL1 */ @@ -282,6 +288,11 @@ void bl31_plat_set_secondary_cpu_off(void) mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu); } +void bl31_plat_runtime_setup(void) +{ + console_switch_state(CONSOLE_FLAG_RUNTIME|CONSOLE_FLAG_BOOT); +} + void bl31_plat_enable_mmu(uint32_t flags) { /* TODO: Enable mmu when needed */ diff --git a/plat/intel/soc/agilex5/include/socfpga_plat_def.h b/plat/intel/soc/agilex5/include/socfpga_plat_def.h index 282958a10..42d8ccfb7 100644 --- a/plat/intel/soc/agilex5/include/socfpga_plat_def.h +++ b/plat/intel/soc/agilex5/include/socfpga_plat_def.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. - * Copyright (c) 2024, Altera Corporation. All rights reserved. + * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -29,6 +29,8 @@ #define PLAT_L2_RESET_REQ 0xB007C0DE #define PLAT_HANDOFF_OFFSET 0x0007F000 #define PLAT_TIMER_BASE_ADDR 0x10D01000 +#define SOCFPGA_DTB_BASE 0x80020000 +#define DT_COMPATIBLE_STR "arm,altera socfpga-agilex5" /* System Counter */ /* TODO: Update back to 400MHz. diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk index a831c3939..58d4b2e54 100644 --- a/plat/intel/soc/agilex5/platform.mk +++ b/plat/intel/soc/agilex5/platform.mk @@ -1,11 +1,12 @@ # # Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. # Copyright (c) 2019-2023, Intel Corporation. All rights reserved. -# Copyright (c) 2024, Altera Corporation. All rights reserved. +# Copyright (c) 2024-2025, Altera Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # include lib/xlat_tables_v2/xlat_tables.mk +include lib/libfdt/libfdt.mk PLAT_INCLUDES := \ -Iplat/intel/soc/agilex5/include/ \ -Iplat/intel/soc/common/drivers/ \ @@ -22,6 +23,7 @@ AGX5_GICv3_SOURCES := \ PLAT_BL_COMMON_SOURCES := \ ${AGX5_GICv3_SOURCES} \ + common/fdt_wrappers.c \ drivers/cadence/combo_phy/cdns_combo_phy.c \ drivers/cadence/emmc/cdns_sdmmc.c \ drivers/cadence/nand/cdns_nand.c \ @@ -36,7 +38,8 @@ PLAT_BL_COMMON_SOURCES := \ plat/intel/soc/common/drivers/ddr/ddr.c \ plat/intel/soc/common/drivers/nand/nand.c \ plat/intel/soc/common/lib/sha/sha.c \ - plat/intel/soc/common/socfpga_delay_timer.c + plat/intel/soc/common/socfpga_delay_timer.c \ + plat/intel/soc/common/socfpga_dt.c BL2_SOURCES += \ common/desc_image_load.c \ diff --git a/plat/intel/soc/common/fdts/agilex5_fdt.dts b/plat/intel/soc/common/fdts/agilex5_fdt.dts new file mode 100644 index 000000000..e16034f17 --- /dev/null +++ b/plat/intel/soc/common/fdts/agilex5_fdt.dts @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019-2024, Intel Corporation. All rights reserved. + * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "ALTERA SOCFPGA AGILEX5"; + compatible = "arm,altera socfpga-agilex5"; + owner = "jit.loon.lim@intel.com"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + + cpu_on = <0xdeadc0de>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "psci"; + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <1>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <2>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <3>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x90000000>; + }; + + gic: interrupt-controller@2c010000 { + compatible = "arm,gic-600", "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <1>; + #ranges; + interrupt-controller; + reg = <0x1D000000 0>, /* GICD */ + <0x1D060000 0>; /* GICR */ + interrupts = <0x1 0x9 0x4>; + }; + + serial0: uart@1a200000 { + compatible = "arm,console-16550"; + reg = <0x10C02000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 8 0xf04>; + clock-frequency = <100000000>; + uart-baudrate = <115200>; + }; + + timer0: timer@1a040000 { + compatible = "arm,armv7-timer-mem"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + reg = <0x1a040000 0x1000>; + clock-frequency = <7500000>; + + frame@1a050000 { + frame-number = <0>; + interrupts = <0 2 0xf04>; + reg = <0x1a050000 0x1000>; + }; + }; + +}; diff --git a/plat/intel/soc/common/include/socfpga_dt.h b/plat/intel/soc/common/include/socfpga_dt.h new file mode 100644 index 000000000..3ff4cb71a --- /dev/null +++ b/plat/intel/soc/common/include/socfpga_dt.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_DT_H +#define SOCFPGA_DT_H + + +#include +#include +#include +/* + * This macro takes three arguments: + * config: Configuration identifier + * name: property namespace + * callback: populate() function + */ +#define SOCFPGA_REGISTER_POPULATOR(config, name, callback) \ + __section(".socfpga_populator") __used \ + static const struct socfpga_populator (name##__populator) = { \ + .config_type = (#config), \ + .info = (#name), \ + .populate = (callback) \ + } + +/* + * Populator callback + * + * This structure are used by the fconf_populate function and should only be + * defined by the SOCFPGA_REGISTER_POPULATOR macro. + */ +struct socfpga_populator { + /* Description of the data loaded by the callback */ + const char *config_type; + const char *info; + + /* Callback used by fconf_populate function with a provided config dtb. + * Return 0 on success, err_code < 0 otherwise. + */ + int (*populate)(uintptr_t config); +}; + +/* Hardware Config related getter */ +#define hw_config__gicv3_config_getter(prop) plat_gicv3_gic_data.prop + +/* Function Definitions */ +int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str); +int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data); +int socfpga_dt_populate_dram_layout(uintptr_t dt_addr); + +#endif diff --git a/plat/intel/soc/common/socfpga_dt.c b/plat/intel/soc/common/socfpga_dt.c new file mode 100644 index 000000000..0333b9b56 --- /dev/null +++ b/plat/intel/soc/common/socfpga_dt.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socfpga_dt.h" + +static const void *fdt; +/******************************************************************************* + * This function checks device tree file with its header. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str) +{ + int ret = 0; + int node = 1; + + ret = fdt_check_header((void *)dt_addr); + + if (ret != 0) { + ERROR("SOCFPGA: FDT Header invalid\n"); + return ret; + } + + fdt = (const void *)dt_addr; + + /* As libfdt use void *, we can't avoid this cast */ + const void *dtb = (void *)dt_addr; + + /* Assert the node offset point to compatible property */ + node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); + if (node < 0) { + ERROR("SOCFPGA: Can't find `%s` compatible in dtb\n", + compatible_str); + return node; + } + + NOTICE("SOCFPGA: Successfully open and check FDT\n"); + + return ret; +} + +int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data) +{ + int err; + int node; + uintptr_t addr; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)dt_addr; + /* + * Find the offset of the node containing "arm,gic-v3" compatible property. + * Populating fconf strucutures dynamically is not supported for legacy + * systems which use GICv2 IP. Simply skip extracting GIC properties. + */ + node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3"); + if (node < 0) { + ERROR("SOCFPGA: Unable to locate node with arm,gic-v3 compatible property\n"); + return 0; + } + /* The GICv3 DT binding holds at least two address/size pairs, + * the first describing the distributor, the second the redistributors. + * See: bindings/interrupt-controller/arm,gic-v3.yaml + */ + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL); + if (err < 0) { + ERROR("SOCFPGA: Failed to read GICD reg property of GIC node\n"); + } else { + plat_driver_data->gicd_base = addr; + } + + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL); + if (err < 0) { + ERROR("SOCFPGA: Failed to read GICR reg property of GIC node\n"); + } else { + plat_driver_data->gicr_base = addr; + } + return err; +} + +int socfpga_dt_populate_dram_layout(uintptr_t dt_addr) +{ + int node; + uintptr_t addr; + size_t size; + + /* Necessary to work with libfdt APIs */ + const void *hw_config_dtb = (const void *)dt_addr; + + /* Find 'memory' node */ + node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type", + "memory", sizeof("memory")); + if (node < 0) { + NOTICE("SOCFPGA: Unable to locate 'memory' node\n"); + return node; + } + + int err = fdt_get_reg_props_by_index( + hw_config_dtb, node, 0, + &addr, (size_t *)&size); + + NOTICE("SOCFPGA: Mem base 0x%lx, Mem size 0x%lx\n", addr, size); + if (err < 0) { + ERROR("SOCFPGA: Failed to read 'reg' property of 'memory' node\n"); + return err; + } + + return 0; +}