From patchwork Wed Feb 12 18:37:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236269 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:35 +0100 Subject: [PATCH 01/10] board: stm32mp1: update command stboard on misc_write result In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-2-patrick.delaunay@st.com> Update management of misc_write, which now return length of data after the commit 8729b1ae2cbd ("misc: Update read() and write() methods to return bytes xfered") Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- board/st/common/cmd_stboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/st/common/cmd_stboard.c b/board/st/common/cmd_stboard.c index e994a88e71..b740f4510e 100644 --- a/board/st/common/cmd_stboard.c +++ b/board/st/common/cmd_stboard.c @@ -125,7 +125,7 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, ret = misc_write(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD), &otp, sizeof(otp)); - if (ret) { + if (ret < 0) { puts("BOARD programming error\n"); return CMD_RET_FAILURE; } From patchwork Wed Feb 12 18:37:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236270 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:36 +0100 Subject: [PATCH 02/10] board: stm32mp1: read OTP in command stboard In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-3-patrick.delaunay@st.com> Read the value directly from the OTP and no more of the shadows to avoid the need of reboot after stboard command to have correct value. Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- board/st/common/cmd_stboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/st/common/cmd_stboard.c b/board/st/common/cmd_stboard.c index b740f4510e..c7ca773b1c 100644 --- a/board/st/common/cmd_stboard.c +++ b/board/st/common/cmd_stboard.c @@ -58,7 +58,7 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, DM_GET_DRIVER(stm32mp_bsec), &dev); - ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), + ret = misc_read(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD), &otp, sizeof(otp)); if (ret < 0) { From patchwork Wed Feb 12 18:37:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236275 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:37 +0100 Subject: [PATCH 03/10] arm: stm32mp: bsec: remove unneeded test In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-4-patrick.delaunay@st.com> Remove the test offs < 0 , as offs is unsigned. This patch solves the warnings when compiling with W=1 on stm32mp1 board: In function ?stm32mp_bsec_read?: arch/arm/mach-stm32mp/bsec.c:368:11: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 368 | if (offs < 0 || (offs % 4) || (size % 4)) | ^ In function ?stm32mp_bsec_write?: arch/arm/mach-stm32mp/bsec.c:405:11: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] 405 | if (offs < 0 || (offs % 4) || (size % 4)) | ^ Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- arch/arm/mach-stm32mp/bsec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index a77c706a1a..1d904caae1 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -365,7 +365,7 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset, shadow = false; } - if (offs < 0 || (offs % 4) || (size % 4)) + if ((offs % 4) || (size % 4)) return -EINVAL; otp = offs / sizeof(u32); @@ -402,7 +402,7 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, shadow = false; } - if (offs < 0 || (offs % 4) || (size % 4)) + if ((offs % 4) || (size % 4)) return -EINVAL; otp = offs / sizeof(u32); From patchwork Wed Feb 12 18:37:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236279 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:38 +0100 Subject: [PATCH 04/10] arm: stm32mp: bsec: add permanent lock support in bsec driver In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-5-patrick.delaunay@st.com> Add BSEC lock access (read / write) at 0xC0000000 offset of misc driver. The write access only available for Trusted boot mode, based on new SMC STM32_SMC_WRLOCK_OTP. With the fuse command, the permanent lock status is accessed with 0x10000000 offset (0xC0000000 - 0x8000000 for OTP sense/program divided by u32 size), for example: Read lock status of fuse 57 (0x39) STM32MP> fuse sense 0 0x10000039 1 Sensing bank 0: Word 0x10000039: 00000000 Set permanent lock of fuse 57 (0x39) STM32MP> fuse prog 0 0x10000039 1 Sensing bank 0: Word 0x10000039: 00000000 WARNING: the OTP lock is updated only after reboot WARING: Programming lock or fuses is an irreversible operation! This may brick your system. Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- arch/arm/mach-stm32mp/bsec.c | 88 +++++++++++++------ arch/arm/mach-stm32mp/cpu.c | 6 -- arch/arm/mach-stm32mp/include/mach/stm32.h | 9 +- .../mach-stm32mp/include/mach/stm32mp1_smc.h | 1 + doc/board/st/stm32mp1.rst | 34 ++++--- 5 files changed, 95 insertions(+), 43 deletions(-) diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index 1d904caae1..3b923f088e 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -12,8 +12,6 @@ #include #define BSEC_OTP_MAX_VALUE 95 - -#ifndef CONFIG_STM32MP1_TRUSTED #define BSEC_TIMEOUT_US 10000 /* BSEC REGISTER OFFSET (base relative) */ @@ -24,9 +22,10 @@ #define BSEC_OTP_LOCK_OFF 0x010 #define BSEC_DISTURBED_OFF 0x01C #define BSEC_ERROR_OFF 0x034 -#define BSEC_SPLOCK_OFF 0x064 /* Program safmem sticky lock */ -#define BSEC_SWLOCK_OFF 0x07C /* write in OTP sticky lock */ -#define BSEC_SRLOCK_OFF 0x094 /* shadowing sticky lock */ +#define BSEC_WRLOCK_OFF 0x04C /* OTP write permananet lock */ +#define BSEC_SPLOCK_OFF 0x064 /* OTP write sticky lock */ +#define BSEC_SWLOCK_OFF 0x07C /* shadow write sticky lock */ +#define BSEC_SRLOCK_OFF 0x094 /* shadow read sticky lock */ #define BSEC_OTP_DATA_OFF 0x200 /* BSEC_CONFIGURATION Register MASK */ @@ -53,12 +52,12 @@ #define BSEC_LOCK_PROGRAM 0x04 /** - * bsec_check_error() - Check status of one otp - * @base: base address of bsec IP + * bsec_lock() - manage lock for each type SR/SP/SW + * @address: address of bsec IP register * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) - * Return: 0 if no error, -EAGAIN or -ENOTSUPP + * Return: true if locked else false */ -static u32 bsec_check_error(u32 base, u32 otp) +static bool bsec_read_lock(u32 address, u32 otp) { u32 bit; u32 bank; @@ -66,21 +65,17 @@ static u32 bsec_check_error(u32 base, u32 otp) bit = 1 << (otp & OTP_LOCK_MASK); bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); - if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) - return -EAGAIN; - else if (readl(base + BSEC_ERROR_OFF + bank) & bit) - return -ENOTSUPP; - - return 0; + return !!(readl(address + bank) & bit); } +#ifndef CONFIG_STM32MP1_TRUSTED /** - * bsec_lock() - manage lock for each type SR/SP/SW - * @address: address of bsec IP register + * bsec_check_error() - Check status of one otp + * @base: base address of bsec IP * @otp: otp number (0 - BSEC_OTP_MAX_VALUE) - * Return: true if locked else false + * Return: 0 if no error, -EAGAIN or -ENOTSUPP */ -static bool bsec_read_lock(u32 address, u32 otp) +static u32 bsec_check_error(u32 base, u32 otp) { u32 bit; u32 bank; @@ -88,7 +83,12 @@ static bool bsec_read_lock(u32 address, u32 otp) bit = 1 << (otp & OTP_LOCK_MASK); bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32); - return !!(readl(address + bank) & bit); + if (readl(base + BSEC_DISTURBED_OFF + bank) & bit) + return -EAGAIN; + else if (readl(base + BSEC_ERROR_OFF + bank) & bit) + return -ENOTSUPP; + + return 0; } /** @@ -324,6 +324,16 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp) #endif } +static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp) +{ + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + /* return OTP permanent write lock status */ + *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp); + + return 0; +} + static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp) { #ifdef CONFIG_STM32MP1_TRUSTED @@ -350,17 +360,36 @@ static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp) #endif } +static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp) +{ +#ifdef CONFIG_STM32MP1_TRUSTED + if (val == 1) + return stm32_smc_exec(STM32_SMC_BSEC, + STM32_SMC_WRLOCK_OTP, + otp, 0); + if (val == 0) + return 0; /* nothing to do */ + + return -EINVAL; +#else + return -ENOTSUPP; +#endif +} + static int stm32mp_bsec_read(struct udevice *dev, int offset, void *buf, int size) { int ret; int i; - bool shadow = true; + bool shadow = true, lock = false; int nb_otp = size / sizeof(u32); int otp; unsigned int offs = offset; - if (offs >= STM32_BSEC_OTP_OFFSET) { + if (offs >= STM32_BSEC_LOCK_OFFSET) { + offs -= STM32_BSEC_LOCK_OFFSET; + lock = true; + } else if (offs >= STM32_BSEC_OTP_OFFSET) { offs -= STM32_BSEC_OTP_OFFSET; shadow = false; } @@ -373,7 +402,9 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset, for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) { u32 *addr = &((u32 *)buf)[i - otp]; - if (shadow) + if (lock) + ret = stm32mp_bsec_read_lock(dev, addr, i); + else if (shadow) ret = stm32mp_bsec_read_shadow(dev, addr, i); else ret = stm32mp_bsec_read_otp(dev, addr, i); @@ -392,12 +423,15 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, { int ret = 0; int i; - bool shadow = true; + bool shadow = true, lock = false; int nb_otp = size / sizeof(u32); int otp; unsigned int offs = offset; - if (offs >= STM32_BSEC_OTP_OFFSET) { + if (offs >= STM32_BSEC_LOCK_OFFSET) { + offs -= STM32_BSEC_LOCK_OFFSET; + lock = true; + } else if (offs >= STM32_BSEC_OTP_OFFSET) { offs -= STM32_BSEC_OTP_OFFSET; shadow = false; } @@ -410,7 +444,9 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset, for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) { u32 *val = &((u32 *)buf)[i - otp]; - if (shadow) + if (lock) + ret = stm32mp_bsec_write_lock(dev, *val, i); + else if (shadow) ret = stm32mp_bsec_write_shadow(dev, *val, i); else ret = stm32mp_bsec_write_otp(dev, *val, i); diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index ea0bd94605..5febed735c 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -61,12 +61,6 @@ #define BOOTROM_INSTANCE_MASK GENMASK(31, 16) #define BOOTROM_INSTANCE_SHIFT 16 -/* BSEC OTP index */ -#define BSEC_OTP_RPN 1 -#define BSEC_OTP_SERIAL 13 -#define BSEC_OTP_PKG 16 -#define BSEC_OTP_MAC 57 - /* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */ #define RPN_SHIFT 0 #define RPN_MASK GENMASK(7, 0) diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index f0636005e5..6daf9f7121 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -119,7 +119,14 @@ enum forced_boot_mode { #define STM32_BSEC_SHADOW(id) (STM32_BSEC_SHADOW_OFFSET + (id) * 4) #define STM32_BSEC_OTP_OFFSET 0x80000000 #define STM32_BSEC_OTP(id) (STM32_BSEC_OTP_OFFSET + (id) * 4) - +#define STM32_BSEC_LOCK_OFFSET 0xC0000000 +#define STM32_BSEC_LOCK(id) (STM32_BSEC_LOCK_OFFSET + (id) * 4) + +/* BSEC OTP index */ +#define BSEC_OTP_RPN 1 +#define BSEC_OTP_SERIAL 13 +#define BSEC_OTP_PKG 16 +#define BSEC_OTP_MAC 57 #define BSEC_OTP_BOARD 59 #endif /* __ASSEMBLY__*/ diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h index 8130546b27..7b9167c356 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h @@ -27,6 +27,7 @@ #define STM32_SMC_READ_OTP 0x04 #define STM32_SMC_READ_ALL 0x05 #define STM32_SMC_WRITE_ALL 0x06 +#define STM32_SMC_WRLOCK_OTP 0x07 /* SMC error codes */ #define STM32_SMC_OK 0x0 diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst index 131f4902a3..274f8d9710 100644 --- a/doc/board/st/stm32mp1.rst +++ b/doc/board/st/stm32mp1.rst @@ -402,20 +402,26 @@ For STMicroelectonics board, it is retrieved in STM32MP15x OTP : - OTP_58[15:0] = MAC_ADDR[47:32] To program a MAC address on virgin OTP words above, you can use the fuse command -on bank 0 to access to internal OTP: +on bank 0 to access to internal OTP and lock them: Prerequisite: check if a MAC address isn't yet programmed in OTP -1) check OTP: their value must be equal to 0 +1) check OTP: their value must be equal to 0:: - STM32MP> fuse sense 0 57 2 - Sensing bank 0: - Word 0x00000039: 00000000 00000000 + STM32MP> fuse sense 0 57 2 + Sensing bank 0: + Word 0x00000039: 00000000 00000000 + +2) check environment variable:: + + STM32MP> env print ethaddr + ## Error: "ethaddr" not defined -2) check environment variable +3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked):: - STM32MP> env print ethaddr - ## Error: "ethaddr" not defined + STM32MP> fuse sense 0 0x10000039 2 + Sensing bank 0: + Word 0x10000039: 00000000 00000000 Example to set mac address "12:34:56:78:9a:bc" @@ -429,11 +435,19 @@ Example to set mac address "12:34:56:78:9a:bc" Sensing bank 0: Word 0x00000039: 78563412 0000bc9a -3) next REBOOT, in the trace:: +3) Lock OTP:: + + STM32MP> fuse prog 0 0x10000039 1 1 + + STM32MP> fuse sense 0 0x10000039 2 + Sensing bank 0: + Word 0x10000039: 00000001 00000001 + +4) next REBOOT, in the trace:: ### Setting environment from OTP MAC address = "12:34:56:78:9a:bc" -4) check env update:: +5) check env update:: STM32MP> env print ethaddr ethaddr=12:34:56:78:9a:bc From patchwork Wed Feb 12 18:37:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236276 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:39 +0100 Subject: [PATCH 05/10] board: stm32mp1: stboard: lock the OTP after programming In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-6-patrick.delaunay@st.com> Lock the OTP used for board identification for the ST boards after programming. Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- board/st/common/cmd_stboard.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/board/st/common/cmd_stboard.c b/board/st/common/cmd_stboard.c index c7ca773b1c..1573e35410 100644 --- a/board/st/common/cmd_stboard.c +++ b/board/st/common/cmd_stboard.c @@ -42,7 +42,7 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int ret; - u32 otp; + u32 otp, lock; u8 revision; unsigned long board, variant, bom; struct udevice *dev; @@ -66,11 +66,20 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, return CMD_RET_FAILURE; } + ret = misc_read(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), + &lock, sizeof(lock)); + if (ret < 0) { + puts("LOCK read error"); + return CMD_RET_FAILURE; + } + if (argc == 0) { if (!otp) puts("Board : OTP board FREE\n"); else display_stboard(otp); + printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD, + lock == 1 ? "" : "NOT"); return CMD_RET_SUCCESS; } @@ -129,6 +138,16 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, puts("BOARD programming error\n"); return CMD_RET_FAILURE; } + + /* write persistent lock */ + otp = 1; + ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), + &otp, sizeof(otp)); + if (ret < 0) { + puts("BOARD lock error\n"); + return CMD_RET_FAILURE; + } + puts("BOARD programming done\n"); return CMD_RET_SUCCESS; From patchwork Wed Feb 12 18:37:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236277 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:40 +0100 Subject: [PATCH 06/10] arm: stm32mp: improve the error message for smc In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-7-patrick.delaunay@st.com> Add the SMC code and operation for trace on errors. Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h index 7b9167c356..4ad14f963b 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h @@ -46,8 +46,8 @@ static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result) arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res); if (res.a0) { - pr_err("%s: Failed to exec in secure mode (err = %ld)\n", - __func__, res.a0); + pr_err("%s: Failed to exec svc=%x op=%x in secure mode (err = %ld)\n", + __func__, svc, op, res.a0); return -EINVAL; } if (result) From patchwork Wed Feb 12 18:37:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236272 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:41 +0100 Subject: [PATCH 07/10] board: stm32mp1: add finished good in board identifier OTP In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-8-patrick.delaunay@st.com> Update the command stboard to support the coding of OTP 59 with finished good: bit [31:16] (hex) => MBxxxx bit [15:12] (dec) => Variant CPN (1....15) bit [11:8] (dec) => Revision board (index with A = 1, Z = 26) bit [7:4] (dec) => Variant FG : finished good (NEW) bit [3:0] (dec) => BOM (01, .... 255) the command is: stboard [-y] Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- board/st/common/cmd_stboard.c | 31 ++++++++++++++++++++----------- board/st/stm32mp1/stm32mp1.c | 3 ++- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/board/st/common/cmd_stboard.c b/board/st/common/cmd_stboard.c index 1573e35410..3ead1edecd 100644 --- a/board/st/common/cmd_stboard.c +++ b/board/st/common/cmd_stboard.c @@ -31,9 +31,10 @@ static bool check_stboard(u16 board) static void display_stboard(u32 otp) { - printf("Board: MB%04x Var%d Rev.%c-%02d\n", + printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n", otp >> 16, (otp >> 12) & 0xF, + (otp >> 4) & 0xF, ((otp >> 8) & 0xF) - 1 + 'A', otp & 0xF); } @@ -44,14 +45,14 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, int ret; u32 otp, lock; u8 revision; - unsigned long board, variant, bom; + unsigned long board, var_cpn, var_fg, bom; struct udevice *dev; - int confirmed = argc == 6 && !strcmp(argv[1], "-y"); + int confirmed = argc == 7 && !strcmp(argv[1], "-y"); argc -= 1 + confirmed; argv += 1 + confirmed; - if (argc != 0 && argc != 4) + if (argc != 0 && argc != 5) return CMD_RET_USAGE; ret = uclass_get_device_by_driver(UCLASS_MISC, @@ -95,8 +96,8 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, return CMD_RET_USAGE; } - if (strict_strtoul(argv[1], 10, &variant) < 0 || - variant == 0 || variant > 15) { + if (strict_strtoul(argv[1], 10, &var_cpn) < 0 || + var_cpn == 0 || var_cpn > 15) { printf("argument %d invalid: %s\n", 2, argv[1]); return CMD_RET_USAGE; } @@ -107,13 +108,20 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, return CMD_RET_USAGE; } - if (strict_strtoul(argv[3], 10, &bom) < 0 || + if (strict_strtoul(argv[3], 10, &var_fg) < 0 || + var_fg > 15) { + printf("argument %d invalid: %s\n", 4, argv[3]); + return CMD_RET_USAGE; + } + + if (strict_strtoul(argv[4], 10, &bom) < 0 || bom == 0 || bom > 15) { printf("argument %d invalid: %s\n", 4, argv[3]); return CMD_RET_USAGE; } - otp = (board << 16) | (variant << 12) | (revision << 8) | bom; + otp = (board << 16) | (var_cpn << 12) | (revision << 8) | + (var_fg << 4) | bom; display_stboard(otp); printf("=> OTP[%d] = %08X\n", BSEC_OTP_BOARD, otp); @@ -153,15 +161,16 @@ static int do_stboard(cmd_tbl_t *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } -U_BOOT_CMD(stboard, 6, 0, do_stboard, +U_BOOT_CMD(stboard, 7, 0, do_stboard, "read/write board reference in OTP", "\n" " Print current board information\n" - "stboard [-y] \n" + "stboard [-y] \n" " Write board information\n" " - Board: xxxx, example 1264 for MB1264\n" - " - Variant: 1 ... 15\n" + " - VarCPN: 1...15\n" " - Revision: A...O\n" + " - VarFG: 0...15\n" " - BOM: 1...15\n"); #endif diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index e82a43074f..76399e2d62 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -109,9 +109,10 @@ int checkboard(void) ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), &otp, sizeof(otp)); if (ret > 0 && otp) { - printf("Board: MB%04x Var%d Rev.%c-%02d\n", + printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n", otp >> 16, (otp >> 12) & 0xF, + (otp >> 4) & 0xF, ((otp >> 8) & 0xF) - 1 + 'A', otp & 0xF); } From patchwork Wed Feb 12 18:37:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236273 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:42 +0100 Subject: [PATCH 08/10] board: stm32mp1: display reference only for STMicroelectronics board In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-9-patrick.delaunay@st.com> Display the reference MBxxxx found in OTP49 only for STMicroelectronics boards when CONFIG_CMD_STBOARD is activated. Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- board/st/stm32mp1/stm32mp1.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 76399e2d62..463248bcd7 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -101,20 +101,21 @@ int checkboard(void) printf(" (%s)", fdt_compat); puts("\n"); - ret = uclass_get_device_by_driver(UCLASS_MISC, - DM_GET_DRIVER(stm32mp_bsec), - &dev); + if (CONFIG_IS_ENABLED(CMD_STBOARD)) { + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); - if (!ret) - ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), - &otp, sizeof(otp)); - if (ret > 0 && otp) { - printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n", - otp >> 16, - (otp >> 12) & 0xF, - (otp >> 4) & 0xF, - ((otp >> 8) & 0xF) - 1 + 'A', - otp & 0xF); + if (!ret) + ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), + &otp, sizeof(otp)); + if (ret > 0 && otp) + printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n", + otp >> 16, + (otp >> 12) & 0xF, + (otp >> 4) & 0xF, + ((otp >> 8) & 0xF) - 1 + 'A', + otp & 0xF); } return 0; From patchwork Wed Feb 12 18:37:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236274 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:43 +0100 Subject: [PATCH 09/10] arm: stm32mp: add function get_soc_name In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-10-patrick.delaunay@st.com> Add a function get_soc_name to get a string with the full name of the SOC "STM32MP15xxx Rev.x" Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- arch/arm/mach-stm32mp/cpu.c | 14 +++++++++++--- arch/arm/mach-stm32mp/include/mach/sys_proto.h | 4 ++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 5febed735c..9c5e0448ce 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -279,8 +279,7 @@ u32 get_cpu_package(void) return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK); } -#if defined(CONFIG_DISPLAY_CPUINFO) -int print_cpuinfo(void) +void get_soc_name(char name[SOC_NAME_SIZE]) { char *cpu_s, *cpu_r, *pkg; @@ -344,7 +343,16 @@ int print_cpuinfo(void) break; } - printf("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r); + snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char name[SOC_NAME_SIZE]; + + get_soc_name(name); + printf("CPU: %s\n", name); return 0; } diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index da46c11573..065b7b2856 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h @@ -29,6 +29,10 @@ u32 get_cpu_package(void); #define PKG_AC_TFBGA361 2 #define PKG_AD_TFBGA257 1 +/* Get SOC name */ +#define SOC_NAME_SIZE 20 +void get_soc_name(char name[SOC_NAME_SIZE]); + /* return boot mode */ u32 get_bootmode(void); From patchwork Wed Feb 12 18:37:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Delaunay X-Patchwork-Id: 236278 List-Id: U-Boot discussion From: patrick.delaunay at st.com (Patrick Delaunay) Date: Wed, 12 Feb 2020 19:37:44 +0100 Subject: [PATCH 10/10] arm: stm32mp: fdt: update kernel device tree according the part number In-Reply-To: <20200212183744.5309-1-patrick.delaunay@st.com> References: <20200212183744.5309-1-patrick.delaunay@st.com> Message-ID: <20200212183744.5309-11-patrick.delaunay@st.com> Update the kernel device tree for STM32MP15x product lines according the used soc and its part number, when CONFIG_OF_SYSTEM_SETUP is activated: - STM32MP15XA hasn't Crypto (cryp1/2) - STM32M151 and STM32M153 hasn't 3D GPU and DSI host - STM32M151 hasn't CAN FD and has single A7 For example: FDT: cpu 1 node remove for STM32MP151AAA Rev.B FDT: can at 4400e000 node disabled for STM32MP151AAA Rev.B FDT: gpu at 59000000 node disabled for STM32MP151AAA Rev.B FDT: dsi at 5a000000 node disabled for STM32MP151AAA Rev.B Signed-off-by: Patrick Delaunay Acked-by: Patrice Chotard --- arch/arm/mach-stm32mp/fdt.c | 100 +++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c index 82c430b7c7..a3db86dc46 100644 --- a/arch/arm/mach-stm32mp/fdt.c +++ b/arch/arm/mach-stm32mp/fdt.c @@ -23,6 +23,12 @@ #define ETZPC_RESERVED 0xffffffff +#define STM32_FDCAN_BASE 0x4400e000 +#define STM32_CRYP2_BASE 0x4c005000 +#define STM32_CRYP1_BASE 0x54001000 +#define STM32_GPU_BASE 0x59000000 +#define STM32_DSI_BASE 0x5a000000 + static const u32 stm32mp1_ip_addr[] = { 0x5c008000, /* 00 stgenc */ 0x54000000, /* 01 bkpsram */ @@ -33,7 +39,7 @@ static const u32 stm32mp1_ip_addr[] = { ETZPC_RESERVED, /* 06 reserved */ 0x54003000, /* 07 rng1 */ 0x54002000, /* 08 hash1 */ - 0x54001000, /* 09 cryp1 */ + STM32_CRYP1_BASE, /* 09 cryp1 */ 0x5a003000, /* 0A ddrctrl */ 0x5a004000, /* 0B ddrphyc */ 0x5c009000, /* 0C i2c6 */ @@ -86,7 +92,7 @@ static const u32 stm32mp1_ip_addr[] = { 0x4400b000, /* 3B sai2 */ 0x4400c000, /* 3C sai3 */ 0x4400d000, /* 3D dfsdm */ - 0x4400e000, /* 3E tt_fdcan */ + STM32_FDCAN_BASE, /* 3E tt_fdcan */ ETZPC_RESERVED, /* 3F reserved */ 0x50021000, /* 40 lptim2 */ 0x50022000, /* 41 lptim3 */ @@ -99,7 +105,7 @@ static const u32 stm32mp1_ip_addr[] = { 0x48003000, /* 48 adc */ 0x4c002000, /* 49 hash2 */ 0x4c003000, /* 4A rng2 */ - 0x4c005000, /* 4B cryp2 */ + STM32_CRYP2_BASE, /* 4B cryp2 */ ETZPC_RESERVED, /* 4C reserved */ ETZPC_RESERVED, /* 4D reserved */ ETZPC_RESERVED, /* 4E reserved */ @@ -126,11 +132,13 @@ static const u32 stm32mp1_ip_addr[] = { static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr) { int node; + fdt_addr_t regs; for (node = fdt_first_subnode(fdt, offset); node >= 0; node = fdt_next_subnode(fdt, node)) { - if (addr == (u32)fdt_getprop(fdt, node, "reg", 0)) { + regs = fdtdec_get_addr(fdt, node, "reg"); + if (addr == regs) { if (fdtdec_get_is_enabled(fdt, node)) { fdt_status_disabled(fdt, node); @@ -143,11 +151,11 @@ static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr) return false; } -static int stm32_fdt_fixup_etzpc(void *fdt) +static int stm32_fdt_fixup_etzpc(void *fdt, int soc_node) { const u32 *array; int array_size, i; - int soc_node, offset, shift; + int offset, shift; u32 addr, status, decprot[ETZPC_DECPROT_NB]; array = stm32mp1_ip_addr; @@ -156,10 +164,6 @@ static int stm32_fdt_fixup_etzpc(void *fdt) for (i = 0; i < ETZPC_DECPROT_NB; i++) decprot[i] = readl(ETZPC_DECPROT(i)); - soc_node = fdt_path_offset(fdt, "/soc"); - if (soc_node < 0) - return soc_node; - for (i = 0; i < array_size; i++) { offset = i / NB_PROT_PER_REG; shift = (i % NB_PROT_PER_REG) * DECPROT_NB_BITS; @@ -180,6 +184,40 @@ static int stm32_fdt_fixup_etzpc(void *fdt) return 0; } +/* deactivate all the cpu except core 0 */ +static void stm32_fdt_fixup_cpu(void *blob, char *name) +{ + int off; + u32 reg; + + off = fdt_path_offset(blob, "/cpus"); + if (off < 0) { + printf("%s: couldn't find /cpus node\n", __func__); + return; + } + + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + reg = fdtdec_get_addr(blob, off, "reg"); + if (reg != 0) { + fdt_del_node(blob, off); + printf("FDT: cpu %d node remove for %s\n", reg, name); + /* after delete we can't trust the offsets anymore */ + off = -1; + } + off = fdt_node_offset_by_prop_value(blob, off, + "device_type", "cpu", 4); + } +} + +static void stm32_fdt_disable(void *fdt, int offset, u32 addr, + const char *string, const char *name) +{ + if (fdt_disable_subnode_by_address(fdt, offset, addr)) + printf("FDT: %s@%08x node disabled for %s\n", + string, addr, name); +} + /* * This function is called right before the kernel is booted. "blob" is the * device tree that will be passed to the kernel. @@ -187,14 +225,52 @@ static int stm32_fdt_fixup_etzpc(void *fdt) int ft_system_setup(void *blob, bd_t *bd) { int ret = 0; - u32 pkg; + int soc; + u32 pkg, cpu; + char name[SOC_NAME_SIZE]; + + soc = fdt_path_offset(blob, "/soc"); + if (soc < 0) + return soc; if (CONFIG_IS_ENABLED(STM32_ETZPC)) { - ret = stm32_fdt_fixup_etzpc(blob); + ret = stm32_fdt_fixup_etzpc(blob, soc); if (ret) return ret; } + /* MPUs Part Numbers and name*/ + cpu = get_cpu_type(); + get_soc_name(name); + + switch (cpu) { + case CPU_STM32MP151Cxx: + case CPU_STM32MP151Axx: + stm32_fdt_fixup_cpu(blob, name); + /* after cpu delete we can't trust the soc offsets anymore */ + soc = fdt_path_offset(blob, "/soc"); + stm32_fdt_disable(blob, soc, STM32_FDCAN_BASE, "can", name); + /* fall through */ + case CPU_STM32MP153Cxx: + case CPU_STM32MP153Axx: + stm32_fdt_disable(blob, soc, STM32_GPU_BASE, "gpu", name); + stm32_fdt_disable(blob, soc, STM32_DSI_BASE, "dsi", name); + break; + default: + break; + } + + switch (cpu) { + case CPU_STM32MP157Axx: + case CPU_STM32MP153Axx: + case CPU_STM32MP151Axx: + stm32_fdt_disable(blob, soc, STM32_CRYP1_BASE, "cryp", name); + stm32_fdt_disable(blob, soc, STM32_CRYP2_BASE, "cryp", name); + break; + default: + break; + } + switch (get_cpu_package()) { case PKG_AA_LBGA448: pkg = STM32MP_PKG_AA;