diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index 33638b5a5528d9eb6d15c7dcea657431d7342418..f0573903de5f920967612cdc470f05998e76a30b 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -59,6 +59,9 @@ uint32_t stm32_get_gpio_bank_offset(unsigned int bank); /* Print CPU information */ void stm32mp_print_cpuinfo(void); +/* Print board information */ +void stm32mp_print_boardinfo(void); + /* * Util for clock gating and to get clock rate for stm32 and platform drivers * @id: Target clock ID, ID used in clock DT bindings diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 1926be31373e8c6c298e418fe7256c9fd162448b..75ae372aee7a4aa2dd37460f1a7ad7e28a5bba83 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -279,6 +279,8 @@ void bl2_el3_plat_arch_setup(void) NOTICE("Model: %s\n", board_model); } + stm32mp_print_boardinfo(); + skip_console_init: if (stm32_iwdg_init() < 0) { panic(); diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 6ee58843238d4ed7368a8125f25414be36dc048b..77a95e68aa5eaf97a647643d042f5324a43b511f 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -331,6 +331,7 @@ static inline uint32_t tamp_bkpr(uint32_t idx) /******************************************************************************* * Device Tree defines ******************************************************************************/ +#define DT_BSEC_COMPAT "st,stm32mp15-bsec" #define DT_IWDG_COMPAT "st,stm32mp1-iwdg" #define DT_PWR_COMPAT "st,stm32mp1-pwr" #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c index 08fb815ced8ea8bc7b8e00646414855c4d8da2e4..c334cd1e0f6c24c8d8569ff197ddf7b266f55a9b 100644 --- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -6,11 +6,30 @@ #include <assert.h> +#include <libfdt.h> + #include <platform_def.h> #include <drivers/st/stm32_iwdg.h> #include <lib/xlat_tables/xlat_tables_v2.h> +/* Internal layout of the 32bit OTP word board_id */ +#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16) +#define BOARD_ID_BOARD_NB_SHIFT 16 +#define BOARD_ID_VARIANT_MASK GENMASK(15, 12) +#define BOARD_ID_VARIANT_SHIFT 12 +#define BOARD_ID_REVISION_MASK GENMASK(11, 8) +#define BOARD_ID_REVISION_SHIFT 8 +#define BOARD_ID_BOM_MASK GENMASK(3, 0) + +#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \ + BOARD_ID_BOARD_NB_SHIFT) +#define BOARD_ID2VAR(_id) (((_id) & BOARD_ID_VARIANT_MASK) >> \ + BOARD_ID_VARIANT_SHIFT) +#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \ + BOARD_ID_REVISION_SHIFT) +#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK) + #define MAP_SRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \ STM32MP_SYSRAM_SIZE, \ MT_MEMORY | \ @@ -188,6 +207,53 @@ void stm32mp_print_cpuinfo(void) NOTICE("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r); } +void stm32mp_print_boardinfo(void) +{ + uint32_t board_id; + uint32_t board_otp; + int bsec_node, bsec_board_id_node; + void *fdt; + const fdt32_t *cuint; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + bsec_node = fdt_node_offset_by_compatible(fdt, -1, DT_BSEC_COMPAT); + if (bsec_node < 0) { + return; + } + + bsec_board_id_node = fdt_subnode_offset(fdt, bsec_node, "board_id"); + if (bsec_board_id_node <= 0) { + return; + } + + cuint = fdt_getprop(fdt, bsec_board_id_node, "reg", NULL); + if (cuint == NULL) { + panic(); + } + + board_otp = fdt32_to_cpu(*cuint) / sizeof(uint32_t); + + if (bsec_shadow_read_otp(&board_id, board_otp) != BSEC_OK) { + ERROR("BSEC: PART_NUMBER_OTP Error\n"); + return; + } + + if (board_id != 0U) { + char rev[2]; + + rev[0] = BOARD_ID2REV(board_id) - 1 + 'A'; + rev[1] = '\0'; + NOTICE("Board: MB%04x Var%d Rev.%s-%02d\n", + BOARD_ID2NB(board_id), + BOARD_ID2VAR(board_id), + rev, + BOARD_ID2BOM(board_id)); + } +} + uint32_t stm32_iwdg_get_instance(uintptr_t base) { switch (base) {