stm32mp1: print information about board

On STMicroelectronics boards, the board information is stored in OTP.
This OTP is described in device tree, in BSEC board_id node.

Change-Id: Ieccbdcb048343680faac8dc577b75c67ac106f5b
Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 1926be3..75ae372 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -279,6 +279,8 @@
 		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 6ee5884..77a95e6 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -331,6 +331,7 @@
 /*******************************************************************************
  * 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 08fb815..c334cd1 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 @@
 	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) {