[PATCH 00/10] stm32mp1: board and SOC identifications

Hi,
Few patches for board and SOC identifications on STM32MP15x - update command stboard for STMicroelectronics board identification (MBxxxx with OTP 59) - update kernel device tree with SOC part number
Regards
Patrick
Patrick Delaunay (10): board: stm32mp1: update command stboard on misc_write result board: stm32mp1: read OTP in command stboard arm: stm32mp: bsec: remove unneeded test arm: stm32mp: bsec: add permanent lock support in bsec driver board: stm32mp1: stboard: lock the OTP after programming arm: stm32mp: improve the error message for smc board: stm32mp1: add finished good in board identifier OTP board: stm32mp1: display reference only for STMicroelectronics board arm: stm32mp: add function get_soc_name arm: stm32mp: fdt: update kernel device tree according the part number
arch/arm/mach-stm32mp/bsec.c | 92 +++++++++++----- arch/arm/mach-stm32mp/cpu.c | 20 ++-- arch/arm/mach-stm32mp/fdt.c | 100 +++++++++++++++--- arch/arm/mach-stm32mp/include/mach/stm32.h | 9 +- .../mach-stm32mp/include/mach/stm32mp1_smc.h | 5 +- .../arm/mach-stm32mp/include/mach/sys_proto.h | 4 + board/st/common/cmd_stboard.c | 56 +++++++--- board/st/stm32mp1/stm32mp1.c | 26 ++--- doc/board/st/stm32mp1.rst | 34 ++++-- 9 files changed, 258 insertions(+), 88 deletions(-)

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 patrick.delaunay@st.com ---
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; }

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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 patrick.delaunay@st.com
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; }
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
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 patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

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 patrick.delaunay@st.com ---
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) {

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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 patrick.delaunay@st.com
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) {
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
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 patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

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 patrick.delaunay@st.com ---
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);

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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 patrick.delaunay@st.com
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);
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi
From: Patrice CHOTARD patrice.chotard@st.com Sent: mercredi 18 mars 2020 11:05
On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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 patrick.delaunay@st.com
arch/arm/mach-stm32mp/bsec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Applied to u-boot-stm/master, thanks!
Regards
Patrick

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
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 patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

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 patrick.delaunay@st.com ---
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 <linux/iopoll.h>
#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

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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 patrick.delaunay@st.com
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 <linux/iopoll.h>
#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 ret = stm32mp_bsec_read_otp(dev, addr, i);else if (shadow) ret = stm32mp_bsec_read_shadow(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 ret = stm32mp_bsec_write_otp(dev, *val, i);else if (shadow) ret = stm32mp_bsec_write_shadow(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::
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice
### 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
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
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 patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

Lock the OTP used for board identification for the ST boards after programming.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
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;

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
Lock the OTP used for board identification for the ST boards after programming.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
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,
return CMD_RET_SUCCESS; }lock == 1 ? "" : "NOT");
@@ -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;
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
Lock the OTP used for board identification for the ST boards after programming.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

Add the SMC code and operation for trace on errors.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
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)

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
Add the SMC code and operation for trace on errors.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
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",
return -EINVAL; } if (result)__func__, svc, op, res.a0);
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
Add the SMC code and operation for trace on errors.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

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] <Board> <VarCPN> <Revision> <VarFG> <BOM>
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
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] <Board> <Variant> <Revision> <BOM>\n" + "stboard [-y] <Board> <VarCPN> <Revision> <VarFG> <BOM>\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); }

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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] <Board> <VarCPN> <Revision> <VarFG> <BOM>
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
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 ||
printf("argument %d invalid: %s\n", 2, argv[1]); return CMD_RET_USAGE; }var_cpn == 0 || var_cpn > 15) {
@@ -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) |
display_stboard(otp); printf("=> OTP[%d] = %08X\n", BSEC_OTP_BOARD, otp);(var_fg << 4) | bom;
@@ -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] <Board> <Variant> <Revision> <BOM>\n"
"stboard [-y] <Board> <VarCPN> <Revision> <VarFG> <BOM>\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);
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Dear Patrick,
In message 20200212183744.5309-8-patrick.delaunay@st.com you wrote:
Update the command stboard to support the coding of OTP 59 with finished good:
Can you please explain what "finished good" means?
I can't parse the sentence above, sorry.
Best regards,
Wolfgang Denk

Hi Wolfgang,
From: Wolfgang Denk wd@denx.de Sent: mercredi 18 mars 2020 11:45
Dear Patrick,
In message 20200212183744.5309-8-patrick.delaunay@st.com you wrote:
Update the command stboard to support the coding of OTP 59 with finished good:
Can you please explain what "finished good" means?
I can't parse the sentence above, sorry.
It is a part of the codification used in production of ST board, sorry if it is not clear.
The ST product codification have several element - "Commercial Product Name" (CPN) : type of product board (DKX, EVX) - "Finished Good" or "Finish Good" (FG) : effective content of the product without chip STM32MP1 (LCD, Wifi, …) - BOM: cost variant for same FG (for example, several provider of the same component)
For example commercial product = STM32MP157C-EV1 Finished Good = EVA32MP157A1$AU1
Booth information are written on board.
During production, this information is also save in OTP. And the stm32mp1 software can change its behavior based on this information.
The FG information is introduced because on DK2 board (same product / same CPN) , we have a risk to manage 2 types of display in future production batch (no more availability of the current LCD => new FG for the same product with new display)
Best regards,
Wolfgang Denk
Regards Patrick

Dear Patrick,
In message 07159b22a76a445089aa6cd646c0ef1c@SFHDAG6NODE3.st.com you wrote:
I can't parse the sentence above, sorry.
It is a part of the codification used in production of ST board, sorry if it is not clear.
I see.
Please add suich explanation to the commit message and maybe even comment in the code.
Best regards,
Wolfgang Denk

Hi Wolfgang,
From: Wolfgang Denk wd@denx.de Sent: jeudi 19 mars 2020 10:14
Dear Patrick,
In message 07159b22a76a445089aa6cd646c0ef1c@SFHDAG6NODE3.st.com you wrote:
I can't parse the sentence above, sorry.
It is a part of the codification used in production of ST board, sorry if it is not
clear.
I see.
Please add suich explanation to the commit message and maybe even comment in the code.
Sure, I will add explanation in commit message and in "cmd_stboard.c" file header.
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de Everyone, in some small sacred sanctuary of the self, is nuts. - Leo Rosten

Display the reference MBxxxx found in OTP49 only for STMicroelectronics boards when CONFIG_CMD_STBOARD is activated.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
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;

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
Display the reference MBxxxx found in OTP49 only for STMicroelectronics boards when CONFIG_CMD_STBOARD is activated.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
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;
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
Display the reference MBxxxx found in OTP49 only for STMicroelectronics boards when CONFIG_CMD_STBOARD is activated.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

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 patrick.delaunay@st.com ---
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);

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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 patrick.delaunay@st.com
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);
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
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 patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick

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@4400e000 node disabled for STM32MP151AAA Rev.B FDT: gpu@59000000 node disabled for STM32MP151AAA Rev.B FDT: dsi@5a000000 node disabled for STM32MP151AAA Rev.B
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
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;

On 2/12/20 7:37 PM, Patrick Delaunay wrote:
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@4400e000 node disabled for STM32MP151AAA Rev.B FDT: gpu@59000000 node disabled for STM32MP151AAA Rev.B FDT: dsi@5a000000 node disabled for STM32MP151AAA Rev.B
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
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;
Acked-by: Patrice Chotard patrice.chotard@st.com
Thanks
Patrice

Hi,
From: Patrick DELAUNAY patrick.delaunay@st.com Sent: mercredi 12 février 2020 19:38
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@4400e000 node disabled for STM32MP151AAA Rev.B FDT: gpu@59000000 node disabled for STM32MP151AAA Rev.B FDT: dsi@5a000000 node disabled for STM32MP151AAA Rev.B
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
Applied to u-boot-stm/next, thanks!
Regards
Patrick
participants (4)
-
Patrice CHOTARD
-
Patrick DELAUNAY
-
Patrick Delaunay
-
Wolfgang Denk