diff --git a/docs/plat/st/stm32mp2.rst b/docs/plat/st/stm32mp2.rst index 5d4ab4e25..87bb6a535 100644 --- a/docs/plat/st/stm32mp2.rst +++ b/docs/plat/st/stm32mp2.rst @@ -85,7 +85,8 @@ To compile the correct DDR driver, one flag must be set among: Boot with FIP ~~~~~~~~~~~~~ -You need to build BL2, BL31, BL32 (OP-TEE) and BL33 (U-Boot) before building FIP binary. +You need to build BL2, BL31, BL32 (OP-TEE) and BL33 (U-Boot) and retrieve +DDR PHY firmware before building FIP binary. U-Boot ______ @@ -106,9 +107,24 @@ ______ ARCH=arm PLATFORM=stm32mp2 \ CFG_EMBED_DTB_SOURCE_FILE=stm32mp257f-ev1.dts -TF-A BL2 & BL31 -_______________ -To build TF-A BL2 with its STM32 header and BL31 for SD-card boot: +DDR PHY firmware +________________ +DDR PHY firmware files may not be delivered inside TF-A repository, especially +if you build directly from trustedfirmware.org repository. It then needs to be +retrieved from `STMicroelectronics DDR PHY github`_. + +You can either clone the repository to the default directory: + +.. code:: bash + + git clone https://github.com/STMicroelectronics/stm32-ddr-phy-binary.git drivers/st/ddr/phy/firmware/bin + +Or clone it somewhere else, and add ``STM32MP_DDR_FW_PATH=`` in your make command +line when building FIP. + +TF-A BL2 +________ +To build TF-A BL2 with its STM32 header for SD-card boot: .. code:: bash @@ -136,5 +152,6 @@ ___ .. _STM32MP2 Series: https://www.st.com/en/microcontrollers-microprocessors/stm32mp2-series.html .. _STM32MP2 part number codification: https://wiki.st.com/stm32mpu/wiki/STM32MP25_microprocessor#Part_number_codification +.. _STMicroelectronics DDR PHY github: https://github.com/STMicroelectronics/stm32-ddr-phy-binary *Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved* diff --git a/fdts/stm32mp25-bl2.dtsi b/fdts/stm32mp25-bl2.dtsi index 769aab20e..e250e3f24 100644 --- a/fdts/stm32mp25-bl2.dtsi +++ b/fdts/stm32mp25-bl2.dtsi @@ -21,6 +21,9 @@ st-io_policies { fip-handles { compatible = "st,io-fip-handle"; +#if STM32MP_DDR_FIP_IO_STORAGE + ddr_fw_uuid = "b11249be-92dd-4b10-867c-2c6a4b47a7fb"; +#endif fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e"; bl31_uuid = "47d4086d-4cfe-9846-9b95-2950cbbd5a00"; bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38"; diff --git a/fdts/stm32mp25-fw-config.dtsi b/fdts/stm32mp25-fw-config.dtsi index b187ad2bd..102980df8 100644 --- a/fdts/stm32mp25-fw-config.dtsi +++ b/fdts/stm32mp25-fw-config.dtsi @@ -25,6 +25,12 @@ id = ; }; + soc_fw { + load-address = <0x0 STM32MP_SYSRAM_BASE>; + max-size = ; + id = ; + }; + tos_fw { id = ; }; diff --git a/include/drivers/st/stm32mp_risab_regs.h b/include/drivers/st/stm32mp_risab_regs.h new file mode 100644 index 000000000..1f49bf696 --- /dev/null +++ b/include/drivers/st/stm32mp_risab_regs.h @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2024, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_RISAB_REGS_H +#define STM32MP_RISAB_REGS_H + +#define RISAB_CR U(0x00) +#define RISAB_IASR U(0x08) +#define RISAB_IACR U(0x0C) +#define RISAB_RIFLOCKR U(0x10) +#define RISAB_IAESR U(0x20) +#define RISAB_IADDR U(0x24) +#define RISAB_PG0_SECCFGR U(0x100) +#define RISAB_PG1_SECCFGR U(0x104) +#define RISAB_PG2_SECCFGR U(0x108) +#define RISAB_PG3_SECCFGR U(0x10C) +#define RISAB_PG4_SECCFGR U(0x110) +#define RISAB_PG5_SECCFGR U(0x114) +#define RISAB_PG6_SECCFGR U(0x118) +#define RISAB_PG7_SECCFGR U(0x11C) +#define RISAB_PG8_SECCFGR U(0x120) +#define RISAB_PG9_SECCFGR U(0x124) +#define RISAB_PG10_SECCFGR U(0x128) +#define RISAB_PG11_SECCFGR U(0x12C) +#define RISAB_PG12_SECCFGR U(0x130) +#define RISAB_PG13_SECCFGR U(0x134) +#define RISAB_PG14_SECCFGR U(0x138) +#define RISAB_PG15_SECCFGR U(0x13C) +#define RISAB_PG16_SECCFGR U(0x140) +#define RISAB_PG17_SECCFGR U(0x144) +#define RISAB_PG18_SECCFGR U(0x148) +#define RISAB_PG19_SECCFGR U(0x14C) +#define RISAB_PG20_SECCFGR U(0x150) +#define RISAB_PG21_SECCFGR U(0x154) +#define RISAB_PG22_SECCFGR U(0x158) +#define RISAB_PG23_SECCFGR U(0x15C) +#define RISAB_PG24_SECCFGR U(0x160) +#define RISAB_PG25_SECCFGR U(0x164) +#define RISAB_PG26_SECCFGR U(0x168) +#define RISAB_PG27_SECCFGR U(0x16C) +#define RISAB_PG28_SECCFGR U(0x170) +#define RISAB_PG29_SECCFGR U(0x174) +#define RISAB_PG30_SECCFGR U(0x178) +#define RISAB_PG31_SECCFGR U(0x17C) +#define RISAB_PG0_PRIVCFGR U(0x200) +#define RISAB_PG1_PRIVCFGR U(0x204) +#define RISAB_PG2_PRIVCFGR U(0x208) +#define RISAB_PG3_PRIVCFGR U(0x20C) +#define RISAB_PG4_PRIVCFGR U(0x210) +#define RISAB_PG5_PRIVCFGR U(0x214) +#define RISAB_PG6_PRIVCFGR U(0x218) +#define RISAB_PG7_PRIVCFGR U(0x21C) +#define RISAB_PG8_PRIVCFGR U(0x220) +#define RISAB_PG9_PRIVCFGR U(0x224) +#define RISAB_PG10_PRIVCFGR U(0x228) +#define RISAB_PG11_PRIVCFGR U(0x22C) +#define RISAB_PG12_PRIVCFGR U(0x230) +#define RISAB_PG13_PRIVCFGR U(0x234) +#define RISAB_PG14_PRIVCFGR U(0x238) +#define RISAB_PG15_PRIVCFGR U(0x23C) +#define RISAB_PG16_PRIVCFGR U(0x240) +#define RISAB_PG17_PRIVCFGR U(0x244) +#define RISAB_PG18_PRIVCFGR U(0x248) +#define RISAB_PG19_PRIVCFGR U(0x24C) +#define RISAB_PG20_PRIVCFGR U(0x250) +#define RISAB_PG21_PRIVCFGR U(0x254) +#define RISAB_PG22_PRIVCFGR U(0x258) +#define RISAB_PG23_PRIVCFGR U(0x25C) +#define RISAB_PG24_PRIVCFGR U(0x260) +#define RISAB_PG25_PRIVCFGR U(0x264) +#define RISAB_PG26_PRIVCFGR U(0x268) +#define RISAB_PG27_PRIVCFGR U(0x26C) +#define RISAB_PG28_PRIVCFGR U(0x270) +#define RISAB_PG29_PRIVCFGR U(0x274) +#define RISAB_PG30_PRIVCFGR U(0x278) +#define RISAB_PG31_PRIVCFGR U(0x27C) +#define RISAB_PG0_C2PRIVCFGR U(0x600) +#define RISAB_PG1_C2PRIVCFGR U(0x604) +#define RISAB_PG2_C2PRIVCFGR U(0x608) +#define RISAB_PG3_C2PRIVCFGR U(0x60C) +#define RISAB_PG4_C2PRIVCFGR U(0x610) +#define RISAB_PG5_C2PRIVCFGR U(0x614) +#define RISAB_PG6_C2PRIVCFGR U(0x618) +#define RISAB_PG7_C2PRIVCFGR U(0x61C) +#define RISAB_PG8_C2PRIVCFGR U(0x620) +#define RISAB_PG9_C2PRIVCFGR U(0x624) +#define RISAB_PG10_C2PRIVCFGR U(0x628) +#define RISAB_PG11_C2PRIVCFGR U(0x62C) +#define RISAB_PG12_C2PRIVCFGR U(0x630) +#define RISAB_PG13_C2PRIVCFGR U(0x634) +#define RISAB_PG14_C2PRIVCFGR U(0x638) +#define RISAB_PG15_C2PRIVCFGR U(0x63C) +#define RISAB_PG16_C2PRIVCFGR U(0x640) +#define RISAB_PG17_C2PRIVCFGR U(0x644) +#define RISAB_PG18_C2PRIVCFGR U(0x648) +#define RISAB_PG19_C2PRIVCFGR U(0x64C) +#define RISAB_PG20_C2PRIVCFGR U(0x650) +#define RISAB_PG21_C2PRIVCFGR U(0x654) +#define RISAB_PG22_C2PRIVCFGR U(0x658) +#define RISAB_PG23_C2PRIVCFGR U(0x65C) +#define RISAB_PG24_C2PRIVCFGR U(0x660) +#define RISAB_PG25_C2PRIVCFGR U(0x664) +#define RISAB_PG26_C2PRIVCFGR U(0x668) +#define RISAB_PG27_C2PRIVCFGR U(0x66C) +#define RISAB_PG28_C2PRIVCFGR U(0x670) +#define RISAB_PG29_C2PRIVCFGR U(0x674) +#define RISAB_PG30_C2PRIVCFGR U(0x678) +#define RISAB_PG31_C2PRIVCFGR U(0x67C) +#define RISAB_CID0PRIVCFGR U(0x800) +#define RISAB_CID0RDCFGR U(0x808) +#define RISAB_CID0WRCFGR U(0x810) +#define RISAB_CID1PRIVCFGR U(0x820) +#define RISAB_CID1RDCFGR U(0x828) +#define RISAB_CID1WRCFGR U(0x830) +#define RISAB_CID2PRIVCFGR U(0x840) +#define RISAB_CID2RDCFGR U(0x848) +#define RISAB_CID2WRCFGR U(0x850) +#define RISAB_CID3PRIVCFGR U(0x860) +#define RISAB_CID3RDCFGR U(0x868) +#define RISAB_CID3WRCFGR U(0x870) +#define RISAB_CID4PRIVCFGR U(0x880) +#define RISAB_CID4RDCFGR U(0x888) +#define RISAB_CID4WRCFGR U(0x890) +#define RISAB_CID5PRIVCFGR U(0x8A0) +#define RISAB_CID5RDCFGR U(0x8A8) +#define RISAB_CID5WRCFGR U(0x8B0) +#define RISAB_CID6PRIVCFGR U(0x8C0) +#define RISAB_CID6RDCFGR U(0x8C8) +#define RISAB_CID6WRCFGR U(0x8D0) +#define RISAB_PG0_CIDCFGR U(0xA00) +#define RISAB_PG1_CIDCFGR U(0xA04) +#define RISAB_PG2_CIDCFGR U(0xA08) +#define RISAB_PG3_CIDCFGR U(0xA0C) +#define RISAB_PG4_CIDCFGR U(0xA10) +#define RISAB_PG5_CIDCFGR U(0xA14) +#define RISAB_PG6_CIDCFGR U(0xA18) +#define RISAB_PG7_CIDCFGR U(0xA1C) +#define RISAB_PG8_CIDCFGR U(0xA20) +#define RISAB_PG9_CIDCFGR U(0xA24) +#define RISAB_PG10_CIDCFGR U(0xA28) +#define RISAB_PG11_CIDCFGR U(0xA2C) +#define RISAB_PG12_CIDCFGR U(0xA30) +#define RISAB_PG13_CIDCFGR U(0xA34) +#define RISAB_PG14_CIDCFGR U(0xA38) +#define RISAB_PG15_CIDCFGR U(0xA3C) +#define RISAB_PG16_CIDCFGR U(0xA40) +#define RISAB_PG17_CIDCFGR U(0xA44) +#define RISAB_PG18_CIDCFGR U(0xA48) +#define RISAB_PG19_CIDCFGR U(0xA4C) +#define RISAB_PG20_CIDCFGR U(0xA50) +#define RISAB_PG21_CIDCFGR U(0xA54) +#define RISAB_PG22_CIDCFGR U(0xA58) +#define RISAB_PG23_CIDCFGR U(0xA5C) +#define RISAB_PG24_CIDCFGR U(0xA60) +#define RISAB_PG25_CIDCFGR U(0xA64) +#define RISAB_PG26_CIDCFGR U(0xA68) +#define RISAB_PG27_CIDCFGR U(0xA6C) +#define RISAB_PG28_CIDCFGR U(0xA70) +#define RISAB_PG29_CIDCFGR U(0xA74) +#define RISAB_PG30_CIDCFGR U(0xA78) +#define RISAB_PG31_CIDCFGR U(0xA7C) +#define RISAB_HWCFGR3 U(0xFE8) +#define RISAB_HWCFGR2 U(0xFEC) +#define RISAB_HWCFGR1 U(0xFF0) +#define RISAB_VERR U(0xFF4) +#define RISAB_IPIDR U(0xFF8) +#define RISAB_SIDR U(0xFFC) + +/* RISAB_CR register fields */ +#define RISAB_CR_GLOCK BIT(0) +#define RISAB_CR_SRWIAD BIT(31) + +/* RISAB_IASR register fields */ +#define RISAB_IASR_CAEF BIT(0) +#define RISAB_IASR_IAEF BIT(1) + +/* RISAB_IACR register fields */ +#define RISAB_IACR_CAEF BIT(0) +#define RISAB_IACR_IAEF BIT(1) + +/* RISAB_RIFLOCKR register fields */ +#define RISAB_RIFLOCKR_RLOCK0 BIT(0) +#define RISAB_RIFLOCKR_RLOCK1 BIT(1) +#define RISAB_RIFLOCKR_RLOCK2 BIT(2) +#define RISAB_RIFLOCKR_RLOCK3 BIT(3) +#define RISAB_RIFLOCKR_RLOCK4 BIT(4) +#define RISAB_RIFLOCKR_RLOCK5 BIT(5) +#define RISAB_RIFLOCKR_RLOCK6 BIT(6) +#define RISAB_RIFLOCKR_RLOCK7 BIT(7) +#define RISAB_RIFLOCKR_RLOCK8 BIT(8) +#define RISAB_RIFLOCKR_RLOCK9 BIT(9) +#define RISAB_RIFLOCKR_RLOCK10 BIT(10) +#define RISAB_RIFLOCKR_RLOCK11 BIT(11) +#define RISAB_RIFLOCKR_RLOCK12 BIT(12) +#define RISAB_RIFLOCKR_RLOCK13 BIT(13) +#define RISAB_RIFLOCKR_RLOCK14 BIT(14) +#define RISAB_RIFLOCKR_RLOCK15 BIT(15) +#define RISAB_RIFLOCKR_RLOCK16 BIT(16) +#define RISAB_RIFLOCKR_RLOCK17 BIT(17) +#define RISAB_RIFLOCKR_RLOCK18 BIT(18) +#define RISAB_RIFLOCKR_RLOCK19 BIT(19) +#define RISAB_RIFLOCKR_RLOCK20 BIT(20) +#define RISAB_RIFLOCKR_RLOCK21 BIT(21) +#define RISAB_RIFLOCKR_RLOCK22 BIT(22) +#define RISAB_RIFLOCKR_RLOCK23 BIT(23) +#define RISAB_RIFLOCKR_RLOCK24 BIT(24) +#define RISAB_RIFLOCKR_RLOCK25 BIT(25) +#define RISAB_RIFLOCKR_RLOCK26 BIT(26) +#define RISAB_RIFLOCKR_RLOCK27 BIT(27) +#define RISAB_RIFLOCKR_RLOCK28 BIT(28) +#define RISAB_RIFLOCKR_RLOCK29 BIT(29) +#define RISAB_RIFLOCKR_RLOCK30 BIT(30) +#define RISAB_RIFLOCKR_RLOCK31 BIT(31) + +/* RISAB_IAESR register fields */ +#define RISAB_IAESR_IACID_MASK GENMASK(2, 0) +#define RISAB_IAESR_IACID_SHIFT 0 +#define RISAB_IAESR_IAPRIV BIT(4) +#define RISAB_IAESR_IASEC BIT(5) +#define RISAB_IAESR_IANRW BIT(7) + +/* RISAB_PGx_SECCFGR register fields */ +#define RISAB_PGx_SECCFGR_SEC(_y) BIT(_y) + +/* RISAB_PGx_PRIVCFGR register fields */ +#define RISAB_PGx_PRIVCFGR_PRIV(_y) BIT(_y) + +/* RISAB_PGx_CmPRIVCFGR register fields */ +#define RISAB_PGx_CmPRIVCFGR_PRIV(_y) BIT(_y) + +/* RISAB_CIDxPRIVCFGR register fields */ +#define RISAB_CIDxPRIVCFGR_PPRIV(_y) BIT(_y) + +/* RISAB_CIDxRDCFGR register fields */ +#define RISAB_CIDxRDCFGR_PRDEN(_y) BIT(_y) + +/* RISAB_CIDxWRCFGR register fields */ +#define RISAB_CIDxWRCFGR_PWREN(_y) BIT(_y) + +/* RISAB_PGx_CIDCFGR register fields */ +#define RISAB_PGx_CIDCFGR_CFEN BIT(0) +#define RISAB_PGx_CIDCFGR_DCEN BIT(2) +#define RISAB_PGx_CIDCFGR_DCCID_MASK GENMASK(6, 4) +#define RISAB_PGx_CIDCFGR_DCCID_SHIFT 4 + +/* RISAB_HWCFGR1 register fields */ +#define RISAB_HWCFGR1_CFG1_MASK GENMASK(3, 0) +#define RISAB_HWCFGR1_CFG1_SHIFT 0 +#define RISAB_HWCFGR1_CFG2_MASK GENMASK(7, 4) +#define RISAB_HWCFGR1_CFG2_SHIFT 4 +#define RISAB_HWCFGR1_CFG3_MASK GENMASK(11, 8) +#define RISAB_HWCFGR1_CFG3_SHIFT 8 +#define RISAB_HWCFGR1_CFG4_MASK GENMASK(15, 12) +#define RISAB_HWCFGR1_CFG4_SHIFT 12 +#define RISAB_HWCFGR1_CFG5_MASK GENMASK(19, 16) +#define RISAB_HWCFGR1_CFG5_SHIFT 16 +#define RISAB_HWCFGR1_CFG6_MASK GENMASK(23, 20) +#define RISAB_HWCFGR1_CFG6_SHIFT 20 +#define RISAB_HWCFGR1_CFG7_MASK GENMASK(27, 24) +#define RISAB_HWCFGR1_CFG7_SHIFT 24 + +/* RISAB_VERR register fields */ +#define RISAB_VERR_MINREV_MASK GENMASK(3, 0) +#define RISAB_VERR_MINREV_SHIFT 0 +#define RISAB_VERR_MAJREV_MASK GENMASK(7, 4) +#define RISAB_VERR_MAJREV_SHIFT 4 + +#endif /* STM32MP_RISAB_REGS_H */ diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c index 6ed09d9c0..1aececed4 100644 --- a/plat/st/common/stm32mp_fconf_io.c +++ b/plat/st/common/stm32mp_fconf_io.c @@ -76,14 +76,28 @@ struct plat_io_policy policies[MAX_NUMBER_IDS] = { #define DEFAULT_UUID_NUMBER U(7) +#ifdef __aarch64__ +#define BL31_UUID_NUMBER U(1) +#else +#define BL31_UUID_NUMBER U(0) +#endif + #if TRUSTED_BOARD_BOOT #define TBBR_UUID_NUMBER U(6) #else #define TBBR_UUID_NUMBER U(0) #endif +#if STM32MP_DDR_FIP_IO_STORAGE +#define DDR_FW_UUID_NUMBER U(1) +#else +#define DDR_FW_UUID_NUMBER U(0) +#endif + #define FCONF_ST_IO_UUID_NUMBER (DEFAULT_UUID_NUMBER + \ - TBBR_UUID_NUMBER) + BL31_UUID_NUMBER + \ + TBBR_UUID_NUMBER + \ + DDR_FW_UUID_NUMBER) static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER]; static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids); @@ -95,7 +109,13 @@ struct policies_load_info { /* image id to property name table */ static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = { +#if STM32MP_DDR_FIP_IO_STORAGE + {DDR_FW_ID, "ddr_fw_uuid"}, +#endif {FW_CONFIG_ID, "fw_cfg_uuid"}, +#ifdef __aarch64__ + {BL31_IMAGE_ID, "bl31_uuid"}, +#endif {BL32_IMAGE_ID, "bl32_uuid"}, {BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"}, {BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"}, diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c index edada72c9..50d19ab2f 100644 --- a/plat/st/stm32mp2/bl2_plat_setup.c +++ b/plat/st/stm32mp2/bl2_plat_setup.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -195,6 +197,17 @@ void bl2_el3_plat_arch_setup(void) panic(); } +#if STM32MP_DDR_FIP_IO_STORAGE + /* + * RISAB3 setup (dedicated for SRAM1) + * + * Allow secure read/writes data accesses to non-secure + * blocks or pages, all RISAB registers are writable. + * DDR firmwares are saved there before being loaded in DDRPHY memory. + */ + mmio_write_32(RISAB3_BASE + RISAB_CR, RISAB_CR_SRWIAD); +#endif + stm32_save_boot_info(boot_context); if (stm32mp_uart_console_setup() != 0) { @@ -229,7 +242,12 @@ skip_console_init: int bl2_plat_handle_post_image_load(unsigned int image_id) { int err = 0; - bl_mem_params_node_t *bl_mem_params __maybe_unused = get_bl_mem_params_node(image_id); + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + const struct dyn_cfg_dtb_info_t *config_info; + unsigned int i; + const unsigned int image_ids[] = { + BL31_IMAGE_ID, + }; assert(bl_mem_params != NULL); @@ -253,6 +271,30 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) FW_CONFIG_ID); fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE); + /* Iterate through all the fw config IDs */ + for (i = 0U; i < ARRAY_SIZE(image_ids); i++) { + bl_mem_params = get_bl_mem_params_node(image_ids[i]); + assert(bl_mem_params != NULL); + + config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]); + if (config_info == NULL) { + continue; + } + + bl_mem_params->image_info.image_base = config_info->config_addr; + bl_mem_params->image_info.image_max_size = config_info->config_max_size; + + bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + + switch (image_ids[i]) { + case BL31_IMAGE_ID: + bl_mem_params->ep_info.pc = config_info->config_addr; + break; + default: + return -EINVAL; + } + } + /* * After this step, the BL2 device tree area will be overwritten * with BL31 binary, no other data should be read from BL2 DT. diff --git a/plat/st/stm32mp2/bl31_plat_setup.c b/plat/st/stm32mp2/bl31_plat_setup.c new file mode 100644 index 000000000..dbf137193 --- /dev/null +++ b/plat/st/stm32mp2/bl31_plat_setup.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + bl_params_t *params_from_bl2; + int ret; + + /* + * Invalidate remaining data from second half of SYSRAM (used by BL2) as this area will + * be later used as non-secure. + */ + inv_dcache_range(STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE / 2U, + STM32MP_SYSRAM_SIZE / 2U); + + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + +#if USE_COHERENT_MEM + /* Map coherent memory */ + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + configure_mmu(); + + /* + * Map upper SYSRAM where bl_params_t are stored in BL2 + */ + ret = mmap_add_dynamic_region(STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE / 2U, + STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE / 2U, + STM32MP_SYSRAM_SIZE / 2U, MT_RO_DATA | MT_SECURE); + if (ret < 0) { + ERROR("BL2 params area mapping: %d\n", ret); + panic(); + } + + assert(arg0 != 0UL); + params_from_bl2 = (bl_params_t *)arg0; + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + while (bl_params != NULL) { + bl_params = bl_params->next_params_info; + } + + ret = mmap_remove_dynamic_region(STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE / 2U, + STM32MP_SYSRAM_SIZE / 2U); + if (ret < 0) { + ERROR("BL2 params area unmapping: %d\n", ret); + panic(); + } +} + +void bl31_plat_arch_setup(void) +{ +} + +void bl31_platform_setup(void) +{ +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type) +{ + return NULL; +} diff --git a/plat/st/stm32mp2/include/plat_tbbr_img_def.h b/plat/st/stm32mp2/include/plat_tbbr_img_def.h index 5dfd41f5f..830bf88b4 100644 --- a/plat/st/stm32mp2/include/plat_tbbr_img_def.h +++ b/plat/st/stm32mp2/include/plat_tbbr_img_def.h @@ -40,8 +40,16 @@ #define STM32MP_CONFIG_CERT_ID U(24) #define GPT_IMAGE_ID U(25) +#if STM32MP_DDR_FIP_IO_STORAGE +#define DDR_FW_ID U(26) +/* Increase the MAX_NUMBER_IDS to match the authentication pool required */ +#define MAX_NUMBER_IDS U(27) + +#else /* Increase the MAX_NUMBER_IDS to match the authentication pool required */ #define MAX_NUMBER_IDS U(26) +#endif + #endif /* PLAT_TBBR_IMG_DEF_H */ diff --git a/plat/st/stm32mp2/include/platform_def.h b/plat/st/stm32mp2/include/platform_def.h index 0f22a93be..89ca032e3 100644 --- a/plat/st/stm32mp2/include/platform_def.h +++ b/plat/st/stm32mp2/include/platform_def.h @@ -8,6 +8,7 @@ #define PLATFORM_DEF_H #include +#include #include #include @@ -32,9 +33,9 @@ #define PLATFORM_CORE_COUNT U(2) #define PLATFORM_MAX_CPUS_PER_CLUSTER U(2) -#define PLAT_MAX_PWR_LVL U(5) -#define PLAT_MAX_CPU_SUSPEND_PWR_LVL U(5) -#define PLAT_NUM_PWR_DOMAINS U(7) +#define PLAT_MAX_PWR_LVL U(3) +#define PLAT_MIN_SUSPEND_PWR_LVL U(2) +#define PLAT_NUM_PWR_DOMAINS U(6) /* Local power state for power domains in Run state. */ #define STM32MP_LOCAL_STATE_RUN U(0) @@ -98,4 +99,59 @@ #define CACHE_WRITEBACK_SHIFT 6 #define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) +/* + * Secure Interrupt: based on the standard ARM mapping + */ +#define ARM_IRQ_SEC_PHY_TIMER U(29) + +#define ARM_IRQ_NON_SEC_SGI_0 U(0) + +#define ARM_IRQ_SEC_SGI_0 U(8) +#define ARM_IRQ_SEC_SGI_1 U(9) +#define ARM_IRQ_SEC_SGI_2 U(10) +#define ARM_IRQ_SEC_SGI_3 U(11) +#define ARM_IRQ_SEC_SGI_4 U(12) +#define ARM_IRQ_SEC_SGI_5 U(13) +#define ARM_IRQ_SEC_SGI_6 U(14) +#define ARM_IRQ_SEC_SGI_7 U(15) + +/* Platform IRQ Priority */ +#define STM32MP_IRQ_SEC_SPI_PRIO U(0x10) + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE) + +#define PLATFORM_G0_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \ + GIC_HIGHEST_SEC_PRIORITY, \ + (grp), GIC_INTR_CFG_EDGE) + #endif /* PLATFORM_DEF_H */ diff --git a/plat/st/stm32mp2/plat_bl2_mem_params_desc.c b/plat/st/stm32mp2/plat_bl2_mem_params_desc.c index 0ef522e82..f8455600e 100644 --- a/plat/st/stm32mp2/plat_bl2_mem_params_desc.c +++ b/plat/st/stm32mp2/plat_bl2_mem_params_desc.c @@ -19,6 +19,24 @@ * the next executable image id. ******************************************************************************/ static bl_mem_params_node_t bl2_mem_params_descs[] = { +#if STM32MP_DDR_FIP_IO_STORAGE + /* Fill FW_DDR related information if it exists */ + { + .image_id = DDR_FW_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_2, image_info_t, + 0), + + .image_info.image_base = STM32MP_DDR_FW_BASE, + .image_info.image_max_size = STM32MP_DDR_FW_MAX_SIZE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +#endif + /* Fill FW_CONFIG related information if it exists */ { .image_id = FW_CONFIG_ID, @@ -34,6 +52,23 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = { .next_handoff_image_id = INVALID_IMAGE_ID, }, + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, }; REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk index eacbd969b..32d6235e9 100644 --- a/plat/st/stm32mp2/platform.mk +++ b/plat/st/stm32mp2/platform.mk @@ -27,6 +27,23 @@ STM32_HEADER_VERSION_MINOR := 2 # Set load address for serial boot devices DWL_BUFFER_BASE ?= 0x87000000 +# DDR types +STM32MP_DDR3_TYPE ?= 0 +STM32MP_DDR4_TYPE ?= 0 +STM32MP_LPDDR4_TYPE ?= 0 +ifeq (${STM32MP_DDR3_TYPE},1) +DDR_TYPE := ddr3 +endif +ifeq (${STM32MP_DDR4_TYPE},1) +DDR_TYPE := ddr4 +endif +ifeq (${STM32MP_LPDDR4_TYPE},1) +DDR_TYPE := lpddr4 +endif + +# DDR features +STM32MP_DDR_FIP_IO_STORAGE := 1 + # Device tree BL2_DTSI := stm32mp25-bl2.dtsi FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) @@ -38,13 +55,26 @@ STM32_BINARY_MAPPING := plat/st/stm32mp2/${ARCH}/stm32mp2.S STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME)) STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME) +ifeq (${STM32MP_DDR_FIP_IO_STORAGE},1) +STM32MP_DDR_FW_PATH ?= drivers/st/ddr/phy/firmware/bin/stm32mp2 +STM32MP_DDR_FW_NAME := ${DDR_TYPE}_pmu_train.bin +STM32MP_DDR_FW := ${STM32MP_DDR_FW_PATH}/${STM32MP_DDR_FW_NAME} +endif FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME))) # Add the FW_CONFIG to FIP and specify the same to certtool $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config)) +ifeq (${STM32MP_DDR_FIP_IO_STORAGE},1) +# Add the FW_DDR to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_IMG,STM32MP_DDR_FW,--ddr-fw)) +endif # Enable flags for C files $(eval $(call assert_booleans,\ $(sort \ + STM32MP_DDR_FIP_IO_STORAGE \ + STM32MP_DDR3_TYPE \ + STM32MP_DDR4_TYPE \ + STM32MP_LPDDR4_TYPE \ STM32MP25 \ ))) @@ -58,9 +88,14 @@ $(eval $(call assert_numerics,\ $(eval $(call add_defines,\ $(sort \ DWL_BUFFER_BASE \ + PLAT_DEF_FIP_UUID \ PLAT_PARTITION_MAX_ENTRIES \ PLAT_TBBR_IMG_DEF \ STM32_TF_A_COPIES \ + STM32MP_DDR_FIP_IO_STORAGE \ + STM32MP_DDR3_TYPE \ + STM32MP_DDR4_TYPE \ + STM32MP_LPDDR4_TYPE \ STM32MP25 \ ))) @@ -98,5 +133,35 @@ endif BL2_SOURCES += drivers/st/ddr/stm32mp2_ddr_helpers.c +# BL31 sources +BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} + +BL31_SOURCES += plat/st/stm32mp2/bl31_plat_setup.c \ + plat/st/stm32mp2/stm32mp2_pm.c \ + plat/st/stm32mp2/stm32mp2_topology.c +# Generic GIC v2 +include drivers/arm/gic/v2/gicv2.mk + +BL31_SOURCES += ${GICV2_SOURCES} \ + plat/common/plat_gicv2.c \ + plat/st/common/stm32mp_gic.c + +# Generic PSCI +BL31_SOURCES += plat/common/plat_psci_common.c + # Compilation rules +.PHONY: check_ddr_type +.SUFFIXES: + +bl2: check_ddr_type + +check_ddr_type: + $(eval DDR_TYPE = $(shell echo $$(($(STM32MP_DDR3_TYPE) + \ + $(STM32MP_DDR4_TYPE) + \ + $(STM32MP_LPDDR4_TYPE))))) + @if [ ${DDR_TYPE} != 1 ]; then \ + echo "One and only one DDR type must be defined"; \ + false; \ + fi + include plat/st/common/common_rules.mk diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h index 81fdaaed1..d3290c320 100644 --- a/plat/st/stm32mp2/stm32mp2_def.h +++ b/plat/st/stm32mp2/stm32mp2_def.h @@ -71,6 +71,9 @@ ******************************************************************************/ #define STM32MP_SYSRAM_BASE U(0x0E000000) #define STM32MP_SYSRAM_SIZE U(0x00040000) +#define SRAM1_BASE U(0x0E040000) +#define SRAM1_SIZE_FOR_TFA U(0x00010000) +#define STM32MP_SEC_SYSRAM_SIZE STM32MP_SYSRAM_SIZE /* DDR configuration */ #define STM32MP_DDR_BASE U(0x80000000) @@ -106,6 +109,10 @@ enum ddr_type { #define STM32MP_BL2_RO_SIZE U(0x00020000) /* 128 KB */ #define STM32MP_BL2_SIZE U(0x00029000) /* 164 KB for BL2 */ +/* Allocate remaining sysram to BL31 */ +#define STM32MP_BL31_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE) + #define STM32MP_BL2_BASE (STM32MP_SYSRAM_BASE + \ STM32MP_SYSRAM_SIZE - \ STM32MP_BL2_SIZE) @@ -139,6 +146,11 @@ enum ddr_type { #define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE #endif +#if STM32MP_DDR_FIP_IO_STORAGE +#define STM32MP_DDR_FW_BASE SRAM1_BASE +#define STM32MP_DDR_FW_MAX_SIZE U(0x8800) +#endif + #define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE #define STM32MP_FW_CONFIG_BASE STM32MP_SYSRAM_BASE @@ -358,6 +370,11 @@ static inline uintptr_t tamp_bkpr(uint32_t idx) #define STGEN_BASE U(0x48080000) #define SYSCFG_BASE U(0x44230000) +/******************************************************************************* + * STM32MP RIF + ******************************************************************************/ +#define RISAB3_BASE U(0x42110000) + /******************************************************************************* * STM32MP CA35SSC ******************************************************************************/ diff --git a/plat/st/stm32mp2/stm32mp2_pm.c b/plat/st/stm32mp2/stm32mp2_pm.c new file mode 100644 index 000000000..5bb381d0d --- /dev/null +++ b/plat/st/stm32mp2/stm32mp2_pm.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static uintptr_t stm32_sec_entrypoint; + +static void stm32_cpu_standby(plat_local_state_t cpu_state) +{ +} + +static int stm32_pwr_domain_on(u_register_t mpidr) +{ + return PSCI_E_INTERN_FAIL; +} + +static void stm32_pwr_domain_off(const psci_power_state_t *target_state) +{ + /* Nothing to do */ +} + +static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + /* Nothing to do, power domain is not disabled */ +} + +static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ +} + +/******************************************************************************* + * STM32MP2 handler called when a power domain has just been powered on after + * having been suspended earlier. The target_state encodes the low power state + * that each level has woken up from. + ******************************************************************************/ +static void stm32_pwr_domain_suspend_finish(const psci_power_state_t + *target_state) +{ + /* Nothing to do, power domain is not disabled */ +} + +static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t + *target_state) +{ + ERROR("stm32mp2 Power Down WFI: operation not handled.\n"); + panic(); +} + +static void __dead2 stm32_system_off(void) +{ + ERROR("stm32mp2 System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 stm32_system_reset(void) +{ + stm32mp_system_reset(); +} + +static int stm32_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + return PSCI_E_INVALID_PARAMS; +} + +static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* The non-secure entry point must be in DDR */ + if (entrypoint < STM32MP_DDR_BASE) { + return PSCI_E_INVALID_ADDRESS; + } + + return PSCI_E_SUCCESS; +} + +static void stm32_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ +} + +/******************************************************************************* + * Export the platform handlers. The ARM Standard platform layer will take care + * of registering the handlers with PSCI. + ******************************************************************************/ +static const plat_psci_ops_t stm32_psci_ops = { + .cpu_standby = stm32_cpu_standby, + .pwr_domain_on = stm32_pwr_domain_on, + .pwr_domain_off = stm32_pwr_domain_off, + .pwr_domain_suspend = stm32_pwr_domain_suspend, + .pwr_domain_on_finish = stm32_pwr_domain_on_finish, + .pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish, + .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi, + .system_off = stm32_system_off, + .system_reset = stm32_system_reset, + .validate_power_state = stm32_validate_power_state, + .validate_ns_entrypoint = stm32_validate_ns_entrypoint, + .get_sys_suspend_power_state = stm32_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + stm32_sec_entrypoint = sec_entrypoint; + *psci_ops = &stm32_psci_ops; + + return 0; +} diff --git a/plat/st/stm32mp2/stm32mp2_private.c b/plat/st/stm32mp2/stm32mp2_private.c index 2801a7fb0..99f6be22a 100644 --- a/plat/st/stm32mp2/stm32mp2_private.c +++ b/plat/st/stm32mp2/stm32mp2_private.c @@ -12,12 +12,31 @@ #define BKPR_BOOT_MODE 96U +#if defined(IMAGE_BL31) +/* BL31 only uses the first half of the SYSRAM */ +#define MAP_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ + STM32MP_SYSRAM_SIZE / 2U, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) +#else #define MAP_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ STM32MP_SYSRAM_SIZE, \ MT_MEMORY | \ MT_RW | \ MT_SECURE | \ MT_EXECUTE_NEVER) +#endif + +#if STM32MP_DDR_FIP_IO_STORAGE +#define MAP_SRAM1 MAP_REGION_FLAT(SRAM1_BASE, \ + SRAM1_SIZE_FOR_TFA, \ + MT_MEMORY | \ + MT_RW | \ + MT_SECURE | \ + MT_EXECUTE_NEVER) +#endif #define MAP_DEVICE MAP_REGION_FLAT(STM32MP_DEVICE_BASE, \ STM32MP_DEVICE_SIZE, \ @@ -27,6 +46,16 @@ MT_EXECUTE_NEVER) #if defined(IMAGE_BL2) +static const mmap_region_t stm32mp2_mmap[] = { + MAP_SYSRAM, +#if STM32MP_DDR_FIP_IO_STORAGE + MAP_SRAM1, +#endif + MAP_DEVICE, + {0} +}; +#endif +#if defined(IMAGE_BL31) static const mmap_region_t stm32mp2_mmap[] = { MAP_SYSRAM, MAP_DEVICE, diff --git a/plat/st/stm32mp2/stm32mp2_topology.c b/plat/st/stm32mp2/stm32mp2_topology.c new file mode 100644 index 000000000..cc2d58c01 --- /dev/null +++ b/plat/st/stm32mp2/stm32mp2_topology.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +/* 1 cluster, all cores into */ +static const unsigned char stm32mp2_power_domain_tree_desc[] = { + PLATFORM_CLUSTER_COUNT, + PLATFORM_CORE_COUNT, +}; + +/* This function returns the platform topology */ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return stm32mp2_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + u_register_t mpidr_copy = mpidr; + + mpidr_copy &= MPIDR_AFFINITY_MASK; + + if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) { + return -1; + } + + cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr_copy >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + /* + * Validate cpu_id by checking whether it represents a CPU in one + * of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_CORE_COUNT) { + return -1; + } + + return (int)cpu_id; +}