stm32mp1: print information about SoC

This information is located in DBGMCU registers.

Change-Id: I480aa046fed9992e3d9665b1f0520bc4b6cfdf30
Signed-off-by: Yann Gautier <yann.gautier@st.com>
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index f8b5e7b..33638b5 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -56,6 +56,9 @@
 unsigned long stm32_get_gpio_bank_clock(unsigned int bank);
 uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
 
+/* Print CPU information */
+void stm32mp_print_cpuinfo(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 7de264b..1926be3 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -272,6 +272,8 @@
 		panic();
 	}
 
+	stm32mp_print_cpuinfo();
+
 	board_model = dt_get_board_model();
 	if (board_model != NULL) {
 		NOTICE("Model: %s\n", board_model);
diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
index a878308..498a4f2 100644
--- a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
@@ -7,6 +7,12 @@
 #ifndef STM32MP1_DBGMCU_H
 #define STM32MP1_DBGMCU_H
 
+#include <stdint.h>
+
+/* Get chip version and ID from DBGMCU registers */
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version);
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id);
+
 /*
  * Freeze watchdog when a debugger is attached, if the security configuration
  * allows it.
diff --git a/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
index a614267..d026496 100644
--- a/plat/st/stm32mp1/stm32mp1_dbgmcu.c
+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
@@ -16,7 +16,13 @@
 
 #include <stm32mp1_dbgmcu.h>
 
+#define DBGMCU_IDC		U(0x00)
 #define DBGMCU_APB4FZ1		U(0x2C)
+
+#define DBGMCU_IDC_DEV_ID_MASK	GENMASK(11, 0)
+#define DBGMCU_IDC_REV_ID_MASK	GENMASK(31, 16)
+#define DBGMCU_IDC_REV_ID_SHIFT	16
+
 #define DBGMCU_APB4FZ1_IWDG2	BIT(2)
 
 static uintptr_t get_rcc_base(void)
@@ -47,6 +53,30 @@
 	return 0;
 }
 
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version)
+{
+	if (stm32mp1_dbgmcu_init() != 0) {
+		return -EPERM;
+	}
+
+	*chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+			 DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
+
+	return 0;
+}
+
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id)
+{
+	if (stm32mp1_dbgmcu_init() != 0) {
+		return -EPERM;
+	}
+
+	*chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+		DBGMCU_IDC_DEV_ID_MASK;
+
+	return 0;
+}
+
 int stm32mp1_dbgmcu_freeze_iwdg2(void)
 {
 	uint32_t dbg_conf;
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 34e6e3c..6ee5884 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -22,10 +22,31 @@
 #include <stm32mp_common.h>
 #include <stm32mp_dt.h>
 #include <stm32mp_shres_helpers.h>
+#include <stm32mp1_dbgmcu.h>
 #include <stm32mp1_private.h>
 #endif
 
 /*******************************************************************************
+ * CHIP ID
+ ******************************************************************************/
+#define STM32MP157C_PART_NB	U(0x05000000)
+#define STM32MP157A_PART_NB	U(0x05000001)
+#define STM32MP153C_PART_NB	U(0x05000024)
+#define STM32MP153A_PART_NB	U(0x05000025)
+#define STM32MP151C_PART_NB	U(0x0500002E)
+#define STM32MP151A_PART_NB	U(0x0500002F)
+
+#define STM32MP1_REV_B		U(0x2000)
+
+/*******************************************************************************
+ * PACKAGE ID
+ ******************************************************************************/
+#define PKG_AA_LFBGA448		U(4)
+#define PKG_AB_LFBGA354		U(3)
+#define PKG_AC_TFBGA361		U(2)
+#define PKG_AD_TFBGA257		U(1)
+
+/*******************************************************************************
  * STM32MP1 memory map related constants
  ******************************************************************************/
 
@@ -240,12 +261,22 @@
 
 /* OTP offsets */
 #define DATA0_OTP			U(0)
+#define PART_NUMBER_OTP			U(1)
+#define PACKAGE_OTP			U(16)
 #define HW2_OTP				U(18)
 
 /* OTP mask */
 /* DATA0 */
 #define DATA0_OTP_SECURED		BIT(6)
 
+/* PART NUMBER */
+#define PART_NUMBER_OTP_PART_MASK	GENMASK_32(7, 0)
+#define PART_NUMBER_OTP_PART_SHIFT	0
+
+/* PACKAGE */
+#define PACKAGE_OTP_PKG_MASK		GENMASK_32(29, 27)
+#define PACKAGE_OTP_PKG_SHIFT		27
+
 /* IWDG OTP */
 #define HW2_OTP_IWDG_HW_POS		U(3)
 #define HW2_OTP_IWDG_FZ_STOP_POS	U(5)
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 886a8f3..08fb815 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -68,6 +68,126 @@
 	return GPIOA + (bank - GPIO_BANK_A);
 }
 
+static int get_part_number(uint32_t *part_nb)
+{
+	uint32_t part_number;
+	uint32_t dev_id;
+
+	if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) {
+		return -1;
+	}
+
+	if (bsec_shadow_read_otp(&part_number, PART_NUMBER_OTP) != BSEC_OK) {
+		ERROR("BSEC: PART_NUMBER_OTP Error\n");
+		return -1;
+	}
+
+	part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >>
+		PART_NUMBER_OTP_PART_SHIFT;
+
+	*part_nb = part_number | (dev_id << 16);
+
+	return 0;
+}
+
+static int get_cpu_package(uint32_t *cpu_package)
+{
+	uint32_t package;
+
+	if (bsec_shadow_read_otp(&package, PACKAGE_OTP) != BSEC_OK) {
+		ERROR("BSEC: PACKAGE_OTP Error\n");
+		return -1;
+	}
+
+	*cpu_package = (package & PACKAGE_OTP_PKG_MASK) >>
+		PACKAGE_OTP_PKG_SHIFT;
+
+	return 0;
+}
+
+void stm32mp_print_cpuinfo(void)
+{
+	const char *cpu_s, *cpu_r, *pkg;
+	uint32_t part_number;
+	uint32_t cpu_package;
+	uint32_t chip_dev_id;
+	int ret;
+
+	/* MPUs Part Numbers */
+	ret = get_part_number(&part_number);
+	if (ret < 0) {
+		WARN("Cannot get part number\n");
+		return;
+	}
+
+	switch (part_number) {
+	case STM32MP157C_PART_NB:
+		cpu_s = "157C";
+		break;
+	case STM32MP157A_PART_NB:
+		cpu_s = "157A";
+		break;
+	case STM32MP153C_PART_NB:
+		cpu_s = "153C";
+		break;
+	case STM32MP153A_PART_NB:
+		cpu_s = "153A";
+		break;
+	case STM32MP151C_PART_NB:
+		cpu_s = "151C";
+		break;
+	case STM32MP151A_PART_NB:
+		cpu_s = "151A";
+		break;
+	default:
+		cpu_s = "????";
+		break;
+	}
+
+	/* Package */
+	ret = get_cpu_package(&cpu_package);
+	if (ret < 0) {
+		WARN("Cannot get CPU package\n");
+		return;
+	}
+
+	switch (cpu_package) {
+	case PKG_AA_LFBGA448:
+		pkg = "AA";
+		break;
+	case PKG_AB_LFBGA354:
+		pkg = "AB";
+		break;
+	case PKG_AC_TFBGA361:
+		pkg = "AC";
+		break;
+	case PKG_AD_TFBGA257:
+		pkg = "AD";
+		break;
+	default:
+		pkg = "??";
+		break;
+	}
+
+	/* REVISION */
+	ret = stm32mp1_dbgmcu_get_chip_version(&chip_dev_id);
+	if (ret < 0) {
+		WARN("Cannot get CPU version\n");
+		return;
+	}
+
+	switch (chip_dev_id) {
+	case STM32MP1_REV_B:
+		cpu_r = "B";
+		break;
+	default:
+		cpu_r = "?";
+		break;
+	}
+
+	NOTICE("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r);
+}
+
 uint32_t stm32_iwdg_get_instance(uintptr_t base)
 {
 	switch (base) {