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 + +/* 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 +#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 #include #include +#include #include #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) {