meta-st-stm32mp/recipes-bsp/u-boot/u-boot-stm32mp/0001-ARM-v2021.10-stm32mp-r...

4093 lines
112 KiB
Diff

From ebcd6dbbef2fc9a1aa90b046cac7a810478499df Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@foss.st.com>
Date: Mon, 30 May 2022 09:59:24 +0200
Subject: [PATCH 1/5] ARM-v2021.10-stm32mp-r1-MACHINE
---
arch/arm/Kconfig | 3 -
arch/arm/mach-stm32mp/Kconfig | 162 ++-----
arch/arm/mach-stm32mp/Kconfig.13x | 57 +++
arch/arm/mach-stm32mp/Kconfig.15x | 134 ++++++
arch/arm/mach-stm32mp/Makefile | 5 +-
arch/arm/mach-stm32mp/bsec.c | 293 +++++++++++-
arch/arm/mach-stm32mp/cmd_stm32key.c | 329 +++++++++----
arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig | 10 +-
.../cmd_stm32prog/cmd_stm32prog.c | 13 +-
.../mach-stm32mp/cmd_stm32prog/stm32prog.c | 431 ++++++++++++++----
.../mach-stm32mp/cmd_stm32prog/stm32prog.h | 47 +-
.../cmd_stm32prog/stm32prog_usb.c | 9 +-
arch/arm/mach-stm32mp/config.mk | 29 --
arch/arm/mach-stm32mp/cpu.c | 398 +++-------------
arch/arm/mach-stm32mp/fdt.c | 274 ++++++++---
arch/arm/mach-stm32mp/include/mach/bsec.h | 8 +
arch/arm/mach-stm32mp/include/mach/gpio.h | 87 ----
arch/arm/mach-stm32mp/include/mach/stm32.h | 28 ++
.../mach-stm32mp/include/mach/stm32mp1_smc.h | 50 +-
.../arm/mach-stm32mp/include/mach/sys_proto.h | 44 +-
arch/arm/mach-stm32mp/pwr_regulator.c | 5 +
arch/arm/mach-stm32mp/spl.c | 1 +
arch/arm/mach-stm32mp/stm32mp13x.c | 123 +++++
arch/arm/mach-stm32mp/stm32mp15x.c | 330 ++++++++++++++
24 files changed, 1978 insertions(+), 892 deletions(-)
create mode 100644 arch/arm/mach-stm32mp/Kconfig.13x
create mode 100644 arch/arm/mach-stm32mp/Kconfig.15x
delete mode 100644 arch/arm/mach-stm32mp/config.mk
delete mode 100644 arch/arm/mach-stm32mp/include/mach/gpio.h
create mode 100644 arch/arm/mach-stm32mp/stm32mp13x.c
create mode 100644 arch/arm/mach-stm32mp/stm32mp15x.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b5bd3284cd..9dd7ea8074 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1749,7 +1749,6 @@ config ARCH_STM32
select CPU_V7M
select DM
select DM_SERIAL
- select GPIO_EXTRA_HEADER
imply CMD_DM
config ARCH_STI
@@ -1775,14 +1774,12 @@ config ARCH_STM32MP
select DM_GPIO
select DM_RESET
select DM_SERIAL
- select GPIO_EXTRA_HEADER
select MISC
select OF_CONTROL
select OF_LIBFDT
select OF_SYSTEM_SETUP
select PINCTRL
select REGMAP
- select SUPPORT_SPL
select SYSCON
select SYSRESET
select SYS_THUMB_BUILD
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 5d7eca649a..09227cabed 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -33,127 +33,54 @@ config SYS_MALLOC_LEN
config ENV_SIZE
default 0x2000
+choice
+ prompt "Select STMicroelectronics STM32MPxxx Soc"
+ default STM32MP15x
+
+config STM32MP13x
+ bool "Support STMicroelectronics STM32MP13x Soc"
+ select ARM_SMCCC
+ select CPU_V7A
+ select CPU_V7_HAS_NONSEC
+ select CPU_V7_HAS_VIRT
+ select OF_BOARD_SETUP
+ select PINCTRL_STM32
+ select STM32_RCC
+ select STM32_RESET
+ select STM32_SERIAL
+ select SYS_ARCH_TIMER
+ imply CMD_NVEDIT_INFO
+ help
+ support of STMicroelectronics SOC STM32MP13x family
+ STMicroelectronics MPU with core ARMv7
+
config STM32MP15x
bool "Support STMicroelectronics STM32MP15x Soc"
- select ARCH_SUPPORT_PSCI if !TFABOOT
- select ARM_SMCCC if TFABOOT
+ select ARCH_SUPPORT_PSCI
+ select BINMAN
select CPU_V7A
- select CPU_V7_HAS_NONSEC if !TFABOOT
+ select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select OF_BOARD_SETUP
select PINCTRL_STM32
select STM32_RCC
select STM32_RESET
select STM32_SERIAL
+ select SUPPORT_SPL
select SYS_ARCH_TIMER
imply CMD_NVEDIT_INFO
- imply SYSRESET_PSCI if TFABOOT
- imply SYSRESET_SYSCON if !TFABOOT
help
support of STMicroelectronics SOC STM32MP15x family
STM32MP157, STM32MP153 or STM32MP151
STMicroelectronics MPU with core ARMv7
dual core A7 for STM32MP157/3, monocore for STM32MP151
- target all the STMicroelectronics board with SOC STM32MP1 family
-
-config STM32MP15x_STM32IMAGE
- bool "Support STM32 image for generated U-Boot image"
- depends on STM32MP15x && TFABOOT
- help
- Support of STM32 image generation for SOC STM32MP15x
- for TF-A boot when FIP container is not used
-
-choice
- prompt "STM32MP15x board select"
- optional
-
-config TARGET_ST_STM32MP15x
- bool "STMicroelectronics STM32MP15x boards"
- select STM32MP15x
- imply BOOTCOUNT_LIMIT
- imply BOOTSTAGE
- imply CMD_BOOTCOUNT
- imply CMD_BOOTSTAGE
- imply CMD_CLS if CMD_BMP
- imply DISABLE_CONSOLE
- imply PRE_CONSOLE_BUFFER
- imply SILENT_CONSOLE
- help
- target the STMicroelectronics board with SOC STM32MP15x
- managed by board/st/stm32mp1:
- Evalulation board (EV1) or Discovery board (DK1 and DK2).
- The difference between board are managed with devicetree
-
-config TARGET_MICROGEA_STM32MP1
- bool "Engicam MicroGEA STM32MP1 SOM"
- select STM32MP15x
- imply BOOTCOUNT_LIMIT
- imply BOOTSTAGE
- imply CMD_BOOTCOUNT
- imply CMD_BOOTSTAGE
- imply CMD_CLS if CMD_BMP
- imply DISABLE_CONSOLE
- imply PRE_CONSOLE_BUFFER
- imply SILENT_CONSOLE
- help
- MicroGEA STM32MP1 is a STM32MP157A based Micro SOM.
-
- MicroGEA STM32MP1 MicroDev 2.0:
- * MicroDev 2.0 is a general purpose miniature carrier board with CAN,
- LTE and LVDS panel interfaces.
- * MicroGEA STM32MP1 needs to mount on top of this MicroDev 2.0 board
- for creating complete MicroGEA STM32MP1 MicroDev 2.0 Carrier board.
-
- MicroGEA STM32MP1 MicroDev 2.0 7" OF:
- * 7" OF is a capacitive touch 7" Open Frame panel solutions with LVDS
- panel and toucscreen.
- * MicroGEA STM32MP1 needs to mount on top of MicroDev 2.0 board with
- pluged 7" OF for creating complete MicroGEA STM32MP1 MicroDev 2.0 7"
- Open Frame Solution board.
-
-config TARGET_ICORE_STM32MP1
- bool "Engicam i.Core STM32MP1 SOM"
- select STM32MP15x
- imply BOOTCOUNT_LIMIT
- imply BOOTSTAGE
- imply CMD_BOOTCOUNT
- imply CMD_BOOTSTAGE
- imply CMD_CLS if CMD_BMP
- imply DISABLE_CONSOLE
- imply PRE_CONSOLE_BUFFER
- imply SILENT_CONSOLE
- help
- i.Core STM32MP1 is an EDIMM SOM based on STM32MP157A.
-
- i.Core STM32MP1 EDIMM2.2:
- * EDIMM2.2 is a Form Factor Capacitive Evaluation Board.
- * i.Core STM32MP1 needs to mount on top of EDIMM2.2 for
- creating complete i.Core STM32MP1 EDIMM2.2 Starter Kit.
-
- i.Core STM32MP1 C.TOUCH 2.0
- * C.TOUCH 2.0 is a general purpose Carrier board.
- * i.Core STM32MP1 needs to mount on top of this Carrier board
- for creating complete i.Core STM32MP1 C.TOUCH 2.0 board.
-
-config TARGET_DH_STM32MP1_PDK2
- bool "DH STM32MP1 PDK2"
- select STM32MP15x
- imply BOOTCOUNT_LIMIT
- imply CMD_BOOTCOUNT
- help
- Target the DH PDK2 development kit with STM32MP15x SoM.
-
endchoice
-config SYS_TEXT_BASE
- default 0xC0100000
-
config NR_DRAM_BANKS
default 1
config DDR_CACHEABLE_SIZE
hex "Size of the DDR marked cacheable in pre-reloc stage"
- default 0x10000000 if TFABOOT
default 0x40000000
help
Define the size of the DDR marked as cacheable in U-Boot
@@ -174,7 +101,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
config STM32_ETZPC
bool "STM32 Extended TrustZone Protection"
- depends on STM32MP15x
+ depends on STM32MP15x || STM32MP13x
default y
help
Say y to enable STM32 Extended TrustZone Protection
@@ -197,41 +124,8 @@ config CMD_STM32KEY
This command is used to evaluate the secure boot on stm32mp SOC,
it is deactivated by default in real products.
-config PRE_CON_BUF_ADDR
- default 0xC02FF000
-
-config PRE_CON_BUF_SZ
- default 4096
-
-config BOOTSTAGE_STASH_ADDR
- default 0xC3000000
-
-if BOOTCOUNT_LIMIT
-config SYS_BOOTCOUNT_SINGLEWORD
- default y
-
-# TAMP_BOOTCOUNT = TAMP_BACKUP_REGISTER(21)
-config SYS_BOOTCOUNT_ADDR
- default 0x5C00A154
-endif
-
-if DEBUG_UART
-
-config DEBUG_UART_BOARD_INIT
- default y
-
-# debug on UART4 by default
-config DEBUG_UART_BASE
- default 0x40010000
-
-# clock source is HSI on reset
-config DEBUG_UART_CLOCK
- default 64000000
-endif
+source "arch/arm/mach-stm32mp/Kconfig.13x"
+source "arch/arm/mach-stm32mp/Kconfig.15x"
source "arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig"
-source "board/dhelectronics/dh_stm32mp1/Kconfig"
-source "board/engicam/stm32mp1/Kconfig"
-source "board/st/stm32mp1/Kconfig"
-
endif
diff --git a/arch/arm/mach-stm32mp/Kconfig.13x b/arch/arm/mach-stm32mp/Kconfig.13x
new file mode 100644
index 0000000000..5fc000986e
--- /dev/null
+++ b/arch/arm/mach-stm32mp/Kconfig.13x
@@ -0,0 +1,57 @@
+if STM32MP13x
+
+choice
+ prompt "STM32MP13x board select"
+ optional
+
+config TARGET_ST_STM32MP13x
+ bool "STMicroelectronics STM32MP13x boards"
+ imply BOOTSTAGE
+ imply CMD_BOOTSTAGE
+ imply CMD_CLS if CMD_BMP
+ imply DISABLE_CONSOLE
+ imply PRE_CONSOLE_BUFFER
+ imply SILENT_CONSOLE
+ help
+ target the STMicroelectronics board with SOC STM32MP13x
+ managed by board/st/stm32mp1.
+ The difference between board are managed with devicetree
+
+endchoice
+
+config SYS_TEXT_BASE
+ default 0xC0000000
+
+config PRE_CON_BUF_ADDR
+ default 0xC0800000
+
+config PRE_CON_BUF_SZ
+ default 4096
+
+config BOOTSTAGE_STASH_ADDR
+ default 0xC3000000
+
+if BOOTCOUNT_GENERIC
+config SYS_BOOTCOUNT_SINGLEWORD
+ default y
+
+# TAMP_BOOTCOUNT = TAMP_BACKUP_REGISTER(31)
+config SYS_BOOTCOUNT_ADDR
+ default 0x5C00A17C
+endif
+
+if DEBUG_UART
+
+# debug on UART4 by default
+config DEBUG_UART_BASE
+ default 0x40010000
+
+# clock source is HSI on reset
+config DEBUG_UART_CLOCK
+ default 48000000 if STM32_FPGA
+ default 64000000
+endif
+
+source "board/st/stm32mp1/Kconfig"
+
+endif
diff --git a/arch/arm/mach-stm32mp/Kconfig.15x b/arch/arm/mach-stm32mp/Kconfig.15x
new file mode 100644
index 0000000000..1887ce15ff
--- /dev/null
+++ b/arch/arm/mach-stm32mp/Kconfig.15x
@@ -0,0 +1,134 @@
+if STM32MP15x
+
+config STM32MP15x_STM32IMAGE
+ bool "Support STM32 image for generated U-Boot image"
+ depends on TFABOOT
+ help
+ Support of STM32 image generation for SOC STM32MP15x
+ for TF-A boot when FIP container is not used
+
+choice
+ prompt "STM32MP15x board select"
+ optional
+
+config TARGET_ST_STM32MP15x
+ bool "STMicroelectronics STM32MP15x boards"
+ imply BOOTSTAGE
+ imply CMD_BOOTSTAGE
+ imply CMD_CLS if CMD_BMP
+ imply DISABLE_CONSOLE
+ imply PRE_CONSOLE_BUFFER
+ imply SILENT_CONSOLE
+ help
+ target the STMicroelectronics board with SOC STM32MP15x
+ managed by board/st/stm32mp1:
+ Evalulation board (EV1) or Discovery board (DK1 and DK2).
+ The difference between board are managed with devicetree
+
+config TARGET_DH_STM32MP1_PDK2
+ bool "DH STM32MP1 PDK2"
+ help
+ Target the DH PDK2 development kit with STM32MP15x SoM.
+
+config TARGET_MICROGEA_STM32MP1
+ bool "Engicam MicroGEA STM32MP1 SOM"
+ imply BOOTSTAGE
+ imply CMD_BOOTSTAGE
+ imply CMD_CLS if CMD_BMP
+ imply DISABLE_CONSOLE
+ imply PRE_CONSOLE_BUFFER
+ imply SILENT_CONSOLE
+ help
+ MicroGEA STM32MP1 is a STM32MP157A based Micro SOM.
+
+ MicroGEA STM32MP1 MicroDev 2.0:
+ * MicroDev 2.0 is a general purpose miniature carrier board with CAN,
+ LTE and LVDS panel interfaces.
+ * MicroGEA STM32MP1 needs to mount on top of this MicroDev 2.0 board
+ for creating complete MicroGEA STM32MP1 MicroDev 2.0 Carrier board.
+
+ MicroGEA STM32MP1 MicroDev 2.0 7" OF:
+ * 7" OF is a capacitive touch 7" Open Frame panel solutions with LVDS
+ panel and toucscreen.
+ * MicroGEA STM32MP1 needs to mount on top of MicroDev 2.0 board with
+ pluged 7" OF for creating complete MicroGEA STM32MP1 MicroDev 2.0 7"
+ Open Frame Solution board.
+
+config TARGET_ICORE_STM32MP1
+ bool "Engicam i.Core STM32MP1 SOM"
+ imply BOOTSTAGE
+ imply CMD_BOOTSTAGE
+ imply CMD_CLS if CMD_BMP
+ imply DISABLE_CONSOLE
+ imply PRE_CONSOLE_BUFFER
+ imply SILENT_CONSOLE
+ help
+ i.Core STM32MP1 is an EDIMM SOM based on STM32MP157A.
+
+ i.Core STM32MP1 EDIMM2.2:
+ * EDIMM2.2 is a Form Factor Capacitive Evaluation Board.
+ * i.Core STM32MP1 needs to mount on top of EDIMM2.2 for
+ creating complete i.Core STM32MP1 EDIMM2.2 Starter Kit.
+
+ i.Core STM32MP1 C.TOUCH 2.0
+ * C.TOUCH 2.0 is a general purpose Carrier board.
+ * i.Core STM32MP1 needs to mount on top of this Carrier board
+ for creating complete i.Core STM32MP1 C.TOUCH 2.0 board.
+
+endchoice
+
+config STM32MP15_PWR
+ bool "Enable driver for STM32MP15x PWR"
+ depends on DM_REGULATOR && DM_PMIC
+ default y
+ help
+ This config enables implementation of driver-model pmic and
+ regulator uclass features for access to STM32MP15x PWR.
+
+config SPL_STM32MP15_PWR
+ bool "Enable driver for STM32MP15x PWR in SPL"
+ depends on SPL && SPL_DM_REGULATOR && SPL_DM_PMIC
+ default y
+ help
+ This config enables implementation of driver-model pmic and
+ regulator uclass features for access to STM32MP15x PWR in SPL.
+config SYS_TEXT_BASE
+ default 0xC0100000
+
+config PRE_CON_BUF_ADDR
+ default 0xC02FF000
+
+config PRE_CON_BUF_SZ
+ default 4096
+
+config BOOTSTAGE_STASH_ADDR
+ default 0xC3000000
+
+if BOOTCOUNT_GENERIC
+config SYS_BOOTCOUNT_SINGLEWORD
+ default y
+
+# TAMP_BOOTCOUNT = TAMP_BACKUP_REGISTER(21)
+config SYS_BOOTCOUNT_ADDR
+ default 0x5C00A154
+endif
+
+if DEBUG_UART
+
+config DEBUG_UART_BOARD_INIT
+ default y
+
+# debug on UART4 by default
+config DEBUG_UART_BASE
+ default 0x40010000
+
+# clock source is HSI on reset
+config DEBUG_UART_CLOCK
+ default 64000000
+endif
+
+source "board/st/stm32mp1/Kconfig"
+source "board/dhelectronics/dh_stm32mp1/Kconfig"
+source "board/engicam/stm32mp1/Kconfig"
+
+endif
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index 391b47cf13..1db9057e04 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -8,6 +8,9 @@ obj-y += dram_init.o
obj-y += syscon.o
obj-y += bsec.o
+obj-$(CONFIG_STM32MP13x) += stm32mp13x.o
+obj-$(CONFIG_STM32MP15x) += stm32mp15x.o
+
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += tzc400.o
@@ -19,5 +22,5 @@ obj-$(CONFIG_ARMV7_PSCI) += psci.o
obj-$(CONFIG_TFABOOT) += boot_params.o
endif
-obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o
+obj-$(CONFIG_$(SPL_)STM32MP15_PWR) += pwr_regulator.o
obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index fe39bd80cf..1a06331530 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -10,14 +10,17 @@
#include <dm.h>
#include <log.h>
#include <misc.h>
+#include <tee.h>
#include <asm/io.h>
#include <asm/arch/bsec.h>
#include <asm/arch/stm32mp1_smc.h>
+#include <dm/device.h>
#include <dm/device_compat.h>
#include <linux/arm-smccc.h>
#include <linux/iopoll.h>
#define BSEC_OTP_MAX_VALUE 95
+#define BSEC_OTP_UPPER_START 32
#define BSEC_TIMEOUT_US 10000
/* BSEC REGISTER OFFSET (base relative) */
@@ -41,6 +44,7 @@
/* BSEC_CONTROL Register */
#define BSEC_READ 0x000
#define BSEC_WRITE 0x100
+#define BSEC_LOCK 0x200
/* LOCK Register */
#define OTP_LOCK_MASK 0x1F
@@ -61,6 +65,48 @@
*/
#define BSEC_LOCK_PROGRAM 0x04
+#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \
+ { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } }
+
+/*
+ * Read OTP memory
+ *
+ * [in] value a: OTP start offset in byte
+ * b: access type
+ * 0 to read from shadow
+ * 1 to read from fuse
+ * 2 to read lock status
+ * [out] memref buffer: Output buffer to store read values
+ * size: Size of OTP to be read
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define PTA_BSEC_READ_MEM 0x0 /* Read OTP */
+
+/*
+ * Write OTP memory
+ *
+ * [in] value a: OTP start offset in byte
+ * b: access type
+ * 0 to write to shadow
+ * 1 to write to fuse
+ * 2 to update the lock status
+ * [in] memref buffer: Input buffer to read values
+ * size: Size of OTP to be written
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define PTA_BSEC_WRITE_MEM 0x1 /* Write OTP */
+
+/* value of PTA_BSEC access type = value[in] b */
+#define SHADOW_ACCESS 0
+#define FUSE_ACCESS 1
+#define LOCK_ACCESS 2
+
/**
* bsec_lock() - manage lock for each type SR/SP/SW
* @address: address of bsec IP register
@@ -160,6 +206,7 @@ static int bsec_power_safmem(u32 base, bool power)
/**
* bsec_shadow_register() - copy safmen otp to bsec data
+ * @dev: bsec IP device
* @base: base address of bsec IP
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: 0 if no error
@@ -203,6 +250,7 @@ static int bsec_shadow_register(struct udevice *dev, u32 base, u32 otp)
/**
* bsec_read_shadow() - read an otp data value from shadow
+ * @dev: bsec IP device
* @base: base address of bsec IP
* @val: read value
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
@@ -217,6 +265,7 @@ static int bsec_read_shadow(struct udevice *dev, u32 base, u32 *val, u32 otp)
/**
* bsec_write_shadow() - write value in BSEC data register in shadow
+ * @dev: bsec IP device
* @base: base address of bsec IP
* @val: value to write
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
@@ -235,6 +284,7 @@ static int bsec_write_shadow(struct udevice *dev, u32 base, u32 val, u32 otp)
/**
* bsec_program_otp() - program a bit in SAFMEM
+ * @dev: bsec IP device
* @base: base address of bsec IP
* @val: value to program
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
@@ -284,18 +334,82 @@ static int bsec_program_otp(struct udevice *dev, long base, u32 val, u32 otp)
return ret;
}
+/**
+ * bsec_permanent_lock_otp() - permanent lock of OTP in SAFMEM
+ * @dev: bsec IP device
+ * @base: base address of bsec IP
+ * @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
+ * Return: 0 if no error
+ */
+static int bsec_permanent_lock_otp(struct udevice *dev, long base, uint32_t otp)
+{
+ int ret;
+ bool power_up = false;
+ u32 val, addr;
+
+ /* check if safemem is power up */
+ if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
+ ret = bsec_power_safmem(base, true);
+ if (ret)
+ return ret;
+
+ power_up = true;
+ }
+
+ /*
+ * low OTPs = 2 bits word for low OTPs, 1 bits per word for upper OTP
+ * and only 16 bits used in WRDATA
+ */
+ if (otp < BSEC_OTP_UPPER_START) {
+ addr = otp / 8;
+ val = 0x03 << ((otp * 2) & 0xF);
+ } else {
+ addr = BSEC_OTP_UPPER_START / 8 +
+ ((otp - BSEC_OTP_UPPER_START) / 16);
+ val = 0x01 << (otp & 0xF);
+ }
+
+ /* set value in write register*/
+ writel(val, base + BSEC_OTP_WRDATA_OFF);
+
+ /* set BSEC_OTP_CTRL_OFF with the otp addr and lock request*/
+ writel(addr | BSEC_WRITE | BSEC_LOCK, base + BSEC_OTP_CTRL_OFF);
+
+ /* check otp status*/
+ ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
+ val, (val & BSEC_MODE_BUSY_MASK) == 0,
+ BSEC_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ if (val & BSEC_MODE_PROGFAIL_MASK)
+ ret = -EACCES;
+ else
+ ret = bsec_check_error(base, otp);
+
+ if (power_up)
+ bsec_power_safmem(base, false);
+
+ return ret;
+}
+
/* BSEC MISC driver *******************************************************/
struct stm32mp_bsec_plat {
u32 base;
};
+struct stm32mp_bsec_privdata {
+ struct udevice *tee;
+ u32 tee_session;
+};
+
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
{
struct stm32mp_bsec_plat *plat;
u32 tmp_data = 0;
int ret;
- if (IS_ENABLED(CONFIG_TFABOOT))
+ if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_OTP,
otp, 0, val);
@@ -326,7 +440,7 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
{
struct stm32mp_bsec_plat *plat;
- if (IS_ENABLED(CONFIG_TFABOOT))
+ if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_SHADOW,
otp, 0, val);
@@ -339,9 +453,14 @@ static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
static int stm32mp_bsec_read_lock(struct udevice *dev, u32 *val, u32 otp)
{
struct stm32mp_bsec_plat *plat = dev_get_plat(dev);
+ u32 wrlock;
/* return OTP permanent write lock status */
- *val = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
+ wrlock = bsec_read_lock(plat->base + BSEC_WRLOCK_OFF, otp);
+
+ *val = 0;
+ if (wrlock)
+ *val = BSEC_LOCK_PERM;
return 0;
}
@@ -350,7 +469,7 @@ static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
{
struct stm32mp_bsec_plat *plat;
- if (IS_ENABLED(CONFIG_TFABOOT))
+ if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_PROG_OTP,
otp, val);
@@ -365,7 +484,7 @@ static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
{
struct stm32mp_bsec_plat *plat;
- if (IS_ENABLED(CONFIG_TFABOOT))
+ if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_WRITE_SHADOW,
otp, val);
@@ -377,27 +496,103 @@ static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
static int stm32mp_bsec_write_lock(struct udevice *dev, u32 val, u32 otp)
{
- if (!IS_ENABLED(CONFIG_TFABOOT))
- return -ENOTSUPP;
+ struct stm32mp_bsec_plat *plat;
- if (val == 1)
+ /* only permanent write lock is supported in U-Boot */
+ if (!(val & BSEC_LOCK_PERM)) {
+ dev_dbg(dev, "lock option without BSEC_LOCK_PERM: %x\n", val);
+ return 0; /* nothing to do */
+ }
+
+ if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_WRLOCK_OTP,
otp, 0);
- if (val == 0)
- return 0; /* nothing to do */
- return -EINVAL;
+ plat = dev_get_plat(dev);
+
+ return bsec_permanent_lock_otp(dev, plat->base, otp);
+}
+
+static int bsec_optee_pta_open(struct udevice *dev)
+{
+ struct stm32mp_bsec_privdata *priv = dev_get_priv(dev);
+ const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
+ struct tee_open_session_arg arg;
+ struct udevice *tee = NULL;
+ int rc;
+
+ tee = tee_find_device(NULL, NULL, NULL, NULL);
+ if (!tee)
+ return -ENODEV;
+
+ memset(&arg, 0, sizeof(arg));
+ tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+ arg.clnt_login = TEE_LOGIN_REE_KERNEL;
+ rc = tee_open_session(tee, &arg, 0, NULL);
+ if (rc < 0)
+ return -ENODEV;
+
+ priv->tee = tee;
+ priv->tee_session = arg.session;
+
+ return 0;
+}
+
+static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
+ void *buff, ulong size)
+{
+ struct stm32mp_bsec_privdata *priv = dev_get_priv(dev);
+ struct tee_invoke_arg arg;
+ struct tee_param param[2];
+ struct tee_shm *fw_shm;
+ int rc;
+
+ rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
+ if (rc)
+ return rc;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.func = cmd;
+ arg.session = priv->tee_session;
+
+ memset(param, 0, sizeof(param));
+
+ param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = offset;
+ param[0].u.value.b = type;
+
+ if (cmd == PTA_BSEC_WRITE_MEM)
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ else
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+
+ param[1].u.memref.shm = fw_shm;
+ param[1].u.memref.size = size;
+
+ rc = tee_invoke_func(priv->tee, &arg, 2, param);
+ if (rc < 0 || arg.ret != 0) {
+ dev_err(priv->tee,
+ "PTA_BSEC invoke failed TEE err: %x, err:%x\n",
+ arg.ret, rc);
+ if (!rc)
+ rc = -EIO;
+ }
+
+ tee_shm_free(fw_shm);
+
+ return rc;
}
static int stm32mp_bsec_read(struct udevice *dev, int offset,
void *buf, int size)
{
+ struct stm32mp_bsec_privdata *priv = dev_get_priv(dev);
int ret;
int i;
bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32);
- int otp;
+ int otp, cmd;
unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) {
@@ -411,6 +606,19 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
if ((offs % 4) || (size % 4))
return -EINVAL;
+ if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
+ cmd = FUSE_ACCESS;
+ if (shadow)
+ cmd = SHADOW_ACCESS;
+ if (lock)
+ cmd = LOCK_ACCESS;
+ ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
+ if (ret)
+ return ret;
+
+ return size;
+ }
+
otp = offs / sizeof(u32);
for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
@@ -435,11 +643,12 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
static int stm32mp_bsec_write(struct udevice *dev, int offset,
const void *buf, int size)
{
+ struct stm32mp_bsec_privdata *priv = dev_get_priv(dev);
int ret = 0;
int i;
bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32);
- int otp;
+ int otp, cmd;
unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) {
@@ -453,6 +662,19 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
if ((offs % 4) || (size % 4))
return -EINVAL;
+ if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
+ cmd = FUSE_ACCESS;
+ if (shadow)
+ cmd = SHADOW_ACCESS;
+ if (lock)
+ cmd = LOCK_ACCESS;
+ ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
+ if (ret)
+ return ret;
+
+ return size;
+ }
+
otp = offs / sizeof(u32);
for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
@@ -501,12 +723,14 @@ static int stm32mp_bsec_probe(struct udevice *dev)
return ret;
}
+ if (IS_ENABLED(CONFIG_OPTEE))
+ bsec_optee_pta_open(dev);
+
/*
* update unlocked shadow for OTP cleared by the rom code
- * only executed in U-Boot proper when TF-A is not used
+ * only executed in SPL, it is done in TF-A for TFABOOT
*/
-
- if (!IS_ENABLED(CONFIG_TFABOOT) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
+ if (IS_ENABLED(CONFIG_SPL_BUILD)) {
plat = dev_get_plat(dev);
for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
@@ -517,7 +741,23 @@ static int stm32mp_bsec_probe(struct udevice *dev)
return 0;
}
+static int stm32mp_bsec_remove(struct udevice *dev)
+{
+ struct stm32mp_bsec_privdata *priv = dev_get_priv(dev);
+ int ret;
+
+ if (IS_ENABLED(CONFIG_OPTEE) && priv && priv->tee) {
+ ret = tee_close_session(priv->tee, priv->tee_session);
+ if (ret)
+ return ret;
+ priv->tee = NULL;
+ }
+
+ return 0;
+}
+
static const struct udevice_id stm32mp_bsec_ids[] = {
+ { .compatible = "st,stm32mp13-bsec" },
{ .compatible = "st,stm32mp15-bsec" },
{}
};
@@ -527,9 +767,11 @@ U_BOOT_DRIVER(stm32mp_bsec) = {
.id = UCLASS_MISC,
.of_match = stm32mp_bsec_ids,
.of_to_plat = stm32mp_bsec_of_to_plat,
- .plat_auto = sizeof(struct stm32mp_bsec_plat),
+ .plat_auto = sizeof(struct stm32mp_bsec_plat),
+ .priv_auto = sizeof(struct stm32mp_bsec_privdata),
.ops = &stm32mp_bsec_ops,
.probe = stm32mp_bsec_probe,
+ .remove = stm32mp_bsec_remove,
};
bool bsec_dbgswenable(void)
@@ -551,3 +793,20 @@ bool bsec_dbgswenable(void)
return false;
}
+
+u32 get_otp(int index, int shift, int mask)
+{
+ int ret;
+ struct udevice *dev;
+ u32 otp = 0;
+
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_DRIVER_GET(stm32mp_bsec),
+ &dev);
+
+ if (!ret)
+ ret = misc_read(dev, STM32_BSEC_SHADOW(index),
+ &otp, sizeof(otp));
+
+ return (otp >> shift) & mask;
+}
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c
index 68f28922d1..d58c422c11 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32key.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32key.c
@@ -8,16 +8,82 @@
#include <console.h>
#include <log.h>
#include <misc.h>
+#include <asm/arch/bsec.h>
#include <dm/device.h>
#include <dm/uclass.h>
-/* Closed device : bit 6 of OPT0*/
+/*
+ * Closed device: OTP0
+ * STM32MP15x: bit 6 of OPT0
+ * STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device
+ */
#define STM32_OTP_CLOSE_ID 0
-#define STM32_OTP_CLOSE_MASK BIT(6)
+#define STM32_OTP_STM32MP13x_CLOSE_MASK 0x3F
+#define STM32_OTP_STM32MP15x_CLOSE_MASK BIT(6)
+
+/* PKH is the first element of the key list */
+#define STM32KEY_PKH 0
+
+struct stm32key {
+ char *name;
+ char *desc;
+ u8 start;
+ u8 size;
+};
+
+const struct stm32key stm32mp13_list[] = {
+ [STM32KEY_PKH] = {
+ .name = "PKHTH",
+ .desc = "Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm)",
+ .start = 24,
+ .size = 8,
+ },
+ {
+ .name = "EDMK",
+ .desc = "Encryption/Decryption Master Key",
+ .start = 92,
+ .size = 4,
+ }
+};
+
+const struct stm32key stm32mp15_list[] = {
+ [STM32KEY_PKH] = {
+ .name = "PKH",
+ .desc = "Hash of the ECC Public Key (ECDSA is the authentication algorithm)",
+ .start = 24,
+ .size = 8,
+ }
+};
+
+/* index of current selected key in stm32key list, 0 = PKH by default */
+static u8 stm32key_index;
+
+static u8 get_key_nb(void)
+{
+ if (IS_ENABLED(CONFIG_STM32MP13x))
+ return ARRAY_SIZE(stm32mp13_list);
-/* HASH of key: 8 OTPs, starting with OTP24) */
-#define STM32_OTP_HASH_KEY_START 24
-#define STM32_OTP_HASH_KEY_SIZE 8
+ if (IS_ENABLED(CONFIG_STM32MP15x))
+ return ARRAY_SIZE(stm32mp15_list);
+}
+
+static const struct stm32key *get_key(u8 index)
+{
+ if (IS_ENABLED(CONFIG_STM32MP13x))
+ return &stm32mp13_list[index];
+
+ if (IS_ENABLED(CONFIG_STM32MP15x))
+ return &stm32mp15_list[index];
+}
+
+static u32 get_otp_close_mask(void)
+{
+ if (IS_ENABLED(CONFIG_STM32MP13x))
+ return STM32_OTP_STM32MP13x_CLOSE_MASK;
+
+ if (IS_ENABLED(CONFIG_STM32MP15x))
+ return STM32_OTP_STM32MP15x_CLOSE_MASK;
+}
static int get_misc_dev(struct udevice **dev)
{
@@ -30,108 +96,115 @@ static int get_misc_dev(struct udevice **dev)
return ret;
}
-static void read_hash_value(u32 addr)
+static void read_key_value(const struct stm32key *key, u32 addr)
{
int i;
- printf("Read KEY at 0x%x\n", addr);
- for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
- printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i,
- __be32_to_cpu(*(u32 *)addr));
+ for (i = 0; i < key->size; i++) {
+ printf("%s OTP %i: [%08x] %08x\n", key->name, key->start + i,
+ addr, __be32_to_cpu(*(u32 *)addr));
addr += 4;
}
}
-static int read_hash_otp(bool print, bool *locked, bool *closed)
+static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool print, bool *locked)
{
- struct udevice *dev;
int i, word, ret;
- int nb_invalid = 0, nb_zero = 0, nb_lock = 0;
+ int nb_invalid = 0, nb_zero = 0, nb_lock = 0, nb_lock_err = 0;
u32 val, lock;
bool status;
- ret = get_misc_dev(&dev);
- if (ret)
- return ret;
-
- for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) {
+ for (i = 0, word = key->start; i < key->size; i++, word++) {
ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
if (ret != 4)
val = ~0x0;
ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
if (ret != 4)
- lock = -1;
+ lock = BSEC_LOCK_ERROR;
if (print)
- printf("OTP HASH %i: %x lock : %d\n", word, val, lock);
+ printf("%s OTP %i: %08x lock : %08x\n", key->name, word, val, lock);
if (val == ~0x0)
nb_invalid++;
else if (val == 0x0)
nb_zero++;
- if (lock == 1)
+ if (lock & BSEC_LOCK_PERM)
nb_lock++;
+ if (lock & BSEC_LOCK_ERROR)
+ nb_lock_err++;
}
- word = STM32_OTP_CLOSE_ID;
- ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
- if (ret != 4)
- val = 0x0;
- ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
- if (ret != 4)
- lock = -1;
-
- status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK;
- if (closed)
- *closed = status;
- if (print)
- printf("OTP %d: closed status: %d lock : %d\n", word, status, lock);
-
- status = (nb_lock == STM32_OTP_HASH_KEY_SIZE);
+ status = nb_lock_err || (nb_lock == key->size);
if (locked)
*locked = status;
- if (!status && print)
- printf("Hash of key is not locked!\n");
+ if (nb_lock_err && print)
+ printf("%s lock is invalid!\n", key->name);
+ else if (!status && print)
+ printf("%s is not locked!\n", key->name);
- if (nb_invalid == STM32_OTP_HASH_KEY_SIZE) {
+ if (nb_invalid == key->size) {
if (print)
- printf("Hash of key is invalid!\n");
+ printf("%s is invalid!\n", key->name);
return -EINVAL;
}
- if (nb_zero == STM32_OTP_HASH_KEY_SIZE) {
+ if (nb_zero == key->size) {
if (print)
- printf("Hash of key is free!\n");
+ printf("%s is free!\n", key->name);
return -ENOENT;
}
return 0;
}
-static int fuse_hash_value(u32 addr, bool print)
+static int read_close_status(struct udevice *dev, bool print, bool *closed)
+{
+ int word, ret, result;
+ u32 val, lock, mask;
+ bool status;
+
+ result = 0;
+ word = STM32_OTP_CLOSE_ID;
+ ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4);
+ if (ret < 0)
+ result = ret;
+ if (ret != 4)
+ val = 0x0;
+
+ ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4);
+ if (ret < 0)
+ result = ret;
+ if (ret != 4)
+ lock = BSEC_LOCK_ERROR;
+
+ mask = get_otp_close_mask();
+ status = (val & mask) == mask;
+ if (closed)
+ *closed = status;
+ if (print)
+ printf("OTP %d: closed status: %d lock : %08x\n", word, status, lock);
+
+ return result;
+}
+
+static int fuse_key_value(struct udevice *dev, const struct stm32key *key, u32 addr, bool print)
{
- struct udevice *dev;
u32 word, val;
int i, ret;
- ret = get_misc_dev(&dev);
- if (ret)
- return ret;
-
- for (i = 0, word = STM32_OTP_HASH_KEY_START;
- i < STM32_OTP_HASH_KEY_SIZE;
- i++, word++, addr += 4) {
+ for (i = 0, word = key->start; i < key->size; i++, word++, addr += 4) {
val = __be32_to_cpu(*(u32 *)addr);
if (print)
- printf("Fuse OTP %i : %x\n", word, val);
+ printf("Fuse %s OTP %i : %08x\n", key->name, word, val);
ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4);
if (ret != 4) {
- log_err("Fuse OTP %i failed\n", word);
+ log_err("Fuse %s OTP %i failed\n", key->name, word);
return ret;
}
- /* on success, lock the OTP for HASH key */
- val = 1;
+ /* on success, lock the OTP for the key */
+ val = BSEC_LOCK_PERM;
ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4);
if (ret != 4) {
- log_err("Lock OTP %i failed\n", word);
+ log_err("Lock %s OTP %i failed\n", key->name, word);
return ret;
}
}
@@ -153,28 +226,103 @@ static int confirm_prog(void)
return 0;
}
+static void display_key_info(const struct stm32key *key)
+{
+ printf("%s : %s\n", key->name, key->desc);
+ printf("\tOTP%d..%d\n", key->start, key->start + key->size);
+}
+
+static int do_stm32key_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ int i;
+
+ for (i = 0; i < get_key_nb(); i++)
+ display_key_info(get_key(i));
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_stm32key_select(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ const struct stm32key *key;
+ int i;
+
+ if (argc == 1) {
+ printf("Selected key:\n");
+ key = get_key(stm32key_index);
+ display_key_info(key);
+ return CMD_RET_SUCCESS;
+ }
+
+ for (i = 0; i < get_key_nb(); i++) {
+ key = get_key(i);
+ if (!strcmp(key->name, argv[1])) {
+ printf("%s selected\n", key->name);
+ stm32key_index = i;
+ return CMD_RET_SUCCESS;
+ }
+ }
+
+ printf("Unknown key %s\n", argv[1]);
+
+ return CMD_RET_FAILURE;
+}
+
static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
+ const struct stm32key *key;
+ struct udevice *dev;
u32 addr;
+ int ret, i;
+ int result;
+
+ ret = get_misc_dev(&dev);
if (argc == 1) {
- read_hash_otp(true, NULL, NULL);
+ if (ret)
+ return CMD_RET_FAILURE;
+ key = get_key(stm32key_index);
+ ret = read_key_otp(dev, key, true, NULL);
+ if (ret != -ENOENT)
+ return CMD_RET_FAILURE;
return CMD_RET_SUCCESS;
}
+ if (!strcmp("-a", argv[1])) {
+ if (ret)
+ return CMD_RET_FAILURE;
+ result = CMD_RET_SUCCESS;
+ for (i = 0; i < get_key_nb(); i++) {
+ key = get_key(i);
+ ret = read_key_otp(dev, key, true, NULL);
+ if (ret != -ENOENT)
+ result = CMD_RET_FAILURE;
+ }
+ ret = read_close_status(dev, true, NULL);
+ if (ret)
+ result = CMD_RET_FAILURE;
+
+ return result;
+ }
+
addr = hextoul(argv[1], NULL);
if (!addr)
return CMD_RET_USAGE;
- read_hash_value(addr);
+ key = get_key(stm32key_index);
+ printf("Read %s at 0x%08x\n", key->name, addr);
+ read_key_value(key, addr);
return CMD_RET_SUCCESS;
}
static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
+ const struct stm32key *key = get_key(stm32key_index);
+ struct udevice *dev;
u32 addr;
- bool yes = false, lock, closed;
+ int ret;
+ bool yes = false, lock;
if (argc < 2)
return CMD_RET_USAGE;
@@ -189,29 +337,38 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con
if (!addr)
return CMD_RET_USAGE;
- if (read_hash_otp(!yes, &lock, &closed) != -ENOENT) {
+ ret = get_misc_dev(&dev);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ if (read_key_otp(dev, key, !yes, &lock) != -ENOENT) {
printf("Error: can't fuse again the OTP\n");
return CMD_RET_FAILURE;
}
-
- if (lock || closed) {
- printf("Error: invalid OTP configuration (lock=%d, closed=%d)\n", lock, closed);
+ if (lock) {
+ printf("Error: %s is locked\n", key->name);
return CMD_RET_FAILURE;
}
+ if (!yes) {
+ printf("Writing %s with\n", key->name);
+ read_key_value(key, addr);
+ }
+
if (!yes && !confirm_prog())
return CMD_RET_FAILURE;
- if (fuse_hash_value(addr, !yes))
+ if (fuse_key_value(dev, key, addr, !yes))
return CMD_RET_FAILURE;
- printf("Hash key updated !\n");
+ printf("%s updated !\n", key->name);
return CMD_RET_SUCCESS;
}
static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
+ const struct stm32key *key;
bool yes, lock, closed;
struct udevice *dev;
u32 val;
@@ -224,32 +381,36 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co
yes = true;
}
- ret = read_hash_otp(!yes, &lock, &closed);
- if (ret) {
- if (ret == -ENOENT)
- printf("Error: OTP not programmed!\n");
+ ret = get_misc_dev(&dev);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ if (read_close_status(dev, !yes, &closed))
return CMD_RET_FAILURE;
- }
if (closed) {
printf("Error: already closed!\n");
return CMD_RET_FAILURE;
}
+ /* check PKH status before to close */
+ key = get_key(STM32KEY_PKH);
+ ret = read_key_otp(dev, key, !yes, &lock);
+ if (ret) {
+ if (ret == -ENOENT)
+ printf("Error: %s not programmed!\n", key->name);
+ return CMD_RET_FAILURE;
+ }
if (!lock)
- printf("Warning: OTP not locked!\n");
+ printf("Warning: %s not locked!\n", key->name);
if (!yes && !confirm_prog())
return CMD_RET_FAILURE;
- ret = get_misc_dev(&dev);
- if (ret)
- return CMD_RET_FAILURE;
-
- val = STM32_OTP_CLOSE_MASK;
+ val = get_otp_close_mask();
ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4);
if (ret != 4) {
- printf("Error: can't update OTP\n");
+ printf("Error: can't update OTP %d\n", STM32_OTP_CLOSE_ID);
return CMD_RET_FAILURE;
}
@@ -259,11 +420,15 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co
}
static char stm32key_help_text[] =
- "read [<addr>]: Read the hash stored at addr in memory or in OTP\n"
- "stm32key fuse [-y] <addr> : Fuse hash stored at addr in OTP\n"
- "stm32key close [-y] : Close the device, the hash stored in OTP\n";
-
-U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Fuse ST Hash key", stm32key_help_text,
+ "list : list the supported key with description\n"
+ "stm32key select [<key>] : Select the key identified by <key> or display the key used for read/fuse command\n"
+ "stm32key read [<addr> | -a ] : Read the curent key at <addr> or current / all (-a) key in OTP\n"
+ "stm32key fuse [-y] <addr> : Fuse the current key at addr in OTP\n"
+ "stm32key close [-y] : Close the device, force use of PKH stored in OTP\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Manage key on STM32", stm32key_help_text,
+ U_BOOT_SUBCMD_MKENT(list, 1, 0, do_stm32key_list),
+ U_BOOT_SUBCMD_MKENT(select, 2, 0, do_stm32key_select),
U_BOOT_SUBCMD_MKENT(read, 2, 0, do_stm32key_read),
U_BOOT_SUBCMD_MKENT(fuse, 3, 0, do_stm32key_fuse),
U_BOOT_SUBCMD_MKENT(close, 2, 0, do_stm32key_close));
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig
index f4c0d18d4d..8f91db4b46 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig
@@ -1,4 +1,3 @@
-
config CMD_STM32PROG
bool "command stm32prog for STM32CudeProgrammer"
select DFU
@@ -31,4 +30,11 @@ config CMD_STM32PROG_SERIAL
help
activate the command "stm32prog serial" for STM32MP soc family
with the tools STM32CubeProgrammer using U-Boot serial device
- and UART protocol.
\ No newline at end of file
+ and UART protocol.
+
+config CMD_STM32PROG_OTP
+ bool "support stm32prog for OTP update"
+ depends on CMD_STM32PROG
+ default y if ARM_SMCCC || OPTEE
+ help
+ Support the OTP update with the command "stm32prog" for STM32MP
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
index 41452b5a29..f59414e716 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
@@ -73,16 +73,9 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
/* check STM32IMAGE presence */
if (size == 0) {
- stm32prog_header_check((struct raw_header_s *)addr, &header);
+ stm32prog_header_check(addr, &header);
if (header.type == HEADER_STM32IMAGE) {
- size = header.image_length + BL_HEADER_SIZE;
-
-#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
- /* uImage detected in STM32IMAGE, execute the script */
- if (IMAGE_FORMAT_LEGACY ==
- genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
- return image_source_script(addr + BL_HEADER_SIZE, "script@1");
-#endif
+ size = header.image_length + header.length;
}
}
@@ -160,6 +153,8 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
else if (CONFIG_IS_ENABLED(CMD_BOOTZ))
do_bootz(cmdtp, 0, 4, bootm_argv);
}
+ if (data->script)
+ image_source_script(data->script, "script@stm32prog");
if (reset) {
puts("Reset...\n");
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
index 3b6ca4e773..ce568b44dc 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
@@ -6,12 +6,15 @@
#include <command.h>
#include <console.h>
#include <dfu.h>
+#include <image.h>
#include <malloc.h>
#include <misc.h>
#include <mmc.h>
#include <part.h>
+#include <tee.h>
#include <asm/arch/stm32mp1_smc.h>
#include <asm/global_data.h>
+#include <dm/device_compat.h>
#include <dm/uclass.h>
#include <jffs2/load_kernel.h>
#include <linux/list.h>
@@ -46,7 +49,7 @@
EFI_GUID(0xFD58F1C7, 0xBE0D, 0x4338, \
0x88, 0xE9, 0xAD, 0x8F, 0x05, 0x0A, 0xEB, 0x18)
-/* RAW parttion (binary / bootloader) used Linux - reserved UUID */
+/* RAW partition (binary / bootloader) used Linux - reserved UUID */
#define LINUX_RESERVED_UUID "8DA63339-0007-60C0-C436-083AC8230908"
/*
@@ -60,6 +63,28 @@ static const efi_guid_t uuid_mmc[3] = {
ROOTFS_MMC2_UUID
};
+/* FIP type partition UUID used by TF-A*/
+#define FIP_TYPE_UUID "19D5DF83-11B0-457B-BE2C-7559C13142A5"
+
+/* unique partition guid (uuid) for FIP partitions A/B */
+#define FIP_A_UUID \
+ EFI_GUID(0x4FD84C93, 0x54EF, 0x463F, \
+ 0xA7, 0xEF, 0xAE, 0x25, 0xFF, 0x88, 0x70, 0x87)
+
+#define FIP_B_UUID \
+ EFI_GUID(0x09C54952, 0xD5BF, 0x45AF, \
+ 0xAC, 0xEE, 0x33, 0x53, 0x03, 0x76, 0x6F, 0xB3)
+
+static const char * const fip_part_name[] = {
+ "fip-a",
+ "fip-b"
+};
+
+static const efi_guid_t fip_part_uuid[] = {
+ FIP_A_UUID,
+ FIP_B_UUID
+};
+
/* order of column in flash layout file */
enum stm32prog_col_t {
COL_OPTION,
@@ -81,6 +106,109 @@ struct fip_toc_header {
DECLARE_GLOBAL_DATA_PTR;
+/* OPTEE TA NVMEM helpers fucntions */
+#define TA_NVMEM_UUID { 0x1a8342cc, 0x81a5, 0x4512, \
+ { 0x99, 0xfe, 0x9e, 0x2b, 0x3e, 0x37, 0xd6, 0x26 } }
+
+/*
+ * Read NVMEM memory for STM32CubeProgrammer
+ *
+ * [in] value a: Type
+ * 0 to read OTP
+ * [out] memref buffer: Output buffer to store read values
+ * size: Size of buffer to be read
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_NVMEM_READ 0x0
+
+/*
+ * Write NVMEM memory for STM32CubeProgrammer
+ *
+ * [in] value a: Type
+ * 0 to read OTP
+ * [in] memref buffer: Input buffer to read values
+ * size: Size of buffer to be written
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_NVMEM_WRITE 0x1
+
+/* value of TA_NVMEM type = value[in] a */
+#define NVMEM_OTP 0
+
+static int optee_ta_open(struct stm32prog_data *data)
+{
+ const struct tee_optee_ta_uuid uuid = TA_NVMEM_UUID;
+ struct tee_open_session_arg arg;
+ struct udevice *tee = NULL;
+ int rc;
+
+ if (data->tee)
+ return 0;
+
+ tee = tee_find_device(NULL, NULL, NULL, NULL);
+ if (!tee)
+ return -ENODEV;
+
+ memset(&arg, 0, sizeof(arg));
+ tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+ rc = tee_open_session(tee, &arg, 0, NULL);
+ if (rc < 0)
+ return -ENODEV;
+
+ data->tee = tee;
+ data->tee_session = arg.session;
+
+ return 0;
+}
+
+static int optee_ta_invoke(struct stm32prog_data *data, int cmd, int type,
+ void *buff, ulong size)
+{
+ struct tee_invoke_arg arg;
+ struct tee_param param[2];
+ struct tee_shm *buff_shm;
+ int rc;
+
+ rc = tee_shm_register(data->tee, buff, size, 0, &buff_shm);
+ if (rc)
+ return rc;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.func = cmd;
+ arg.session = data->tee_session;
+
+ memset(param, 0, sizeof(param));
+ param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = type;
+
+ if (cmd == TA_NVMEM_WRITE)
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ else
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+
+ param[1].u.memref.shm = buff_shm;
+ param[1].u.memref.size = size;
+
+ rc = tee_invoke_func(data->tee, &arg, 2, param);
+ if (rc < 0 || arg.ret != 0) {
+ dev_err(data->tee,
+ "TA_NVMEM invoke failed TEE err: %x, err:%x\n",
+ arg.ret, rc);
+ if (!rc)
+ rc = -EIO;
+ }
+
+ tee_shm_free(buff_shm);
+
+ return rc;
+}
+
/* partition handling routines : CONFIG_CMD_MTDPARTS */
int mtdparts_init(void);
int find_dev_and_part(const char *id, struct mtd_device **dev,
@@ -101,52 +229,98 @@ static bool stm32prog_is_fip_header(struct fip_toc_header *header)
return (header->name == FIP_TOC_HEADER_NAME) && header->serial_number;
}
-void stm32prog_header_check(struct raw_header_s *raw_header,
- struct image_header_s *header)
+static bool stm32prog_is_stm32_header_v1(struct stm32_header_v1 *header)
{
unsigned int i;
- if (!raw_header || !header) {
- log_debug("%s:no header data\n", __func__);
- return;
+ if (header->magic_number !=
+ (('S' << 0) | ('T' << 8) | ('M' << 16) | (0x32 << 24))) {
+ log_debug("%s:invalid magic number : 0x%x\n",
+ __func__, header->magic_number);
+ return false;
+ }
+ if (header->header_version != 0x00010000) {
+ log_debug("%s:invalid header version : 0x%x\n",
+ __func__, header->header_version);
+ return false;
}
- header->type = HEADER_NONE;
- header->image_checksum = 0x0;
- header->image_length = 0x0;
-
- if (stm32prog_is_fip_header((struct fip_toc_header *)raw_header)) {
- header->type = HEADER_FIP;
- return;
+ if (header->reserved1 || header->reserved2) {
+ log_debug("%s:invalid reserved field\n", __func__);
+ return false;
+ }
+ for (i = 0; i < sizeof(header->padding); i++) {
+ if (header->padding[i] != 0) {
+ log_debug("%s:invalid padding field\n", __func__);
+ return false;
+ }
}
- if (raw_header->magic_number !=
+ return true;
+}
+
+static bool stm32prog_is_stm32_header_v2(struct stm32_header_v2 *header)
+{
+ unsigned int i;
+
+ if (header->magic_number !=
(('S' << 0) | ('T' << 8) | ('M' << 16) | (0x32 << 24))) {
log_debug("%s:invalid magic number : 0x%x\n",
- __func__, raw_header->magic_number);
- return;
+ __func__, header->magic_number);
+ return false;
}
- /* only header v1.0 supported */
- if (raw_header->header_version != 0x00010000) {
+ if (header->header_version != 0x00020000) {
log_debug("%s:invalid header version : 0x%x\n",
- __func__, raw_header->header_version);
+ __func__, header->header_version);
+ return false;
+ }
+ if (header->reserved1 || header->reserved2)
+ return false;
+
+ for (i = 0; i < sizeof(header->padding); i++) {
+ if (header->padding[i] != 0) {
+ log_debug("%s:invalid padding field\n", __func__);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void stm32prog_header_check(uintptr_t raw_header, struct image_header_s *header)
+{
+ struct stm32_header_v1 *v1_header = (struct stm32_header_v1 *)raw_header;
+ struct stm32_header_v2 *v2_header = (struct stm32_header_v2 *)raw_header;
+
+ if (!raw_header || !header) {
+ log_debug("%s:no header data\n", __func__);
return;
}
- if (raw_header->reserved1 != 0x0 || raw_header->reserved2) {
- log_debug("%s:invalid reserved field\n", __func__);
+
+ if (stm32prog_is_fip_header((struct fip_toc_header *)raw_header)) {
+ header->type = HEADER_FIP;
+ header->length = 0;
return;
}
- for (i = 0; i < (sizeof(raw_header->padding) / 4); i++) {
- if (raw_header->padding[i] != 0) {
- log_debug("%s:invalid padding field\n", __func__);
- return;
- }
+ if (stm32prog_is_stm32_header_v1(v1_header)) {
+ header->type = HEADER_STM32IMAGE;
+ header->image_checksum = le32_to_cpu(v1_header->image_checksum);
+ header->image_length = le32_to_cpu(v1_header->image_length);
+ header->length = sizeof(struct stm32_header_v1);
+ return;
+ }
+ if (stm32prog_is_stm32_header_v2(v2_header)) {
+ header->type = HEADER_STM32IMAGE_V2;
+ header->image_checksum = le32_to_cpu(v2_header->image_checksum);
+ header->image_length = le32_to_cpu(v2_header->image_length);
+ header->length = sizeof(struct stm32_header_v1) +
+ v2_header->extension_headers_length;
+ return;
}
- header->type = HEADER_STM32IMAGE;
- header->image_checksum = le32_to_cpu(raw_header->image_checksum);
- header->image_length = le32_to_cpu(raw_header->image_length);
- return;
+ header->type = HEADER_NONE;
+ header->image_checksum = 0x0;
+ header->image_length = 0x0;
}
static u32 stm32prog_header_checksum(u32 addr, struct image_header_s *header)
@@ -255,6 +429,8 @@ static int parse_type(struct stm32prog_data *data,
part->bin_nb =
dectoul(&p[7], NULL);
}
+ } else if (!strcmp(p, "FIP")) {
+ part->part_type = PART_FIP;
} else if (!strcmp(p, "System")) {
part->part_type = PART_SYSTEM;
} else if (!strcmp(p, "FileSystem")) {
@@ -376,11 +552,11 @@ static int parse_flash_layout(struct stm32prog_data *data,
data->part_nb = 0;
/* check if STM32image is detected */
- stm32prog_header_check((struct raw_header_s *)addr, &header);
+ stm32prog_header_check(addr, &header);
if (header.type == HEADER_STM32IMAGE) {
u32 checksum;
- addr = addr + BL_HEADER_SIZE;
+ addr = addr + header.length;
size = header.image_length;
checksum = stm32prog_header_checksum(addr, &header);
@@ -835,8 +1011,8 @@ static int treat_partition_list(struct stm32prog_data *data)
/* skip partition with IP="none" */
if (part->target == STM32PROG_NONE) {
if (IS_SELECT(part)) {
- stm32prog_err("Layout: selected none phase = 0x%x",
- part->id);
+ stm32prog_err("Layout: selected none phase = 0x%x for part %s",
+ part->id, part->name);
return -EINVAL;
}
continue;
@@ -844,14 +1020,14 @@ static int treat_partition_list(struct stm32prog_data *data)
if (part->id == PHASE_FLASHLAYOUT ||
part->id > PHASE_LAST_USER) {
- stm32prog_err("Layout: invalid phase = 0x%x",
- part->id);
+ stm32prog_err("Layout: invalid phase = 0x%x for part %s",
+ part->id, part->name);
return -EINVAL;
}
for (j = i + 1; j < data->part_nb; j++) {
if (part->id == data->part_array[j].id) {
- stm32prog_err("Layout: duplicated phase 0x%x at line %d and %d",
- part->id, i, j);
+ stm32prog_err("Layout: duplicated phase 0x%x for part %s and %s",
+ part->id, part->name, data->part_array[j].name);
return -EINVAL;
}
}
@@ -906,9 +1082,10 @@ static int create_gpt_partitions(struct stm32prog_data *data)
char uuid[UUID_STR_LEN + 1];
unsigned char *uuid_bin;
unsigned int mmc_id;
- int i;
+ int i, j;
bool rootfs_found;
struct stm32prog_part_t *part;
+ const char *type_str;
buf = malloc(buflen);
if (!buf)
@@ -950,33 +1127,46 @@ static int create_gpt_partitions(struct stm32prog_data *data)
part->addr,
part->size);
- if (part->part_type == PART_BINARY)
- offset += snprintf(buf + offset,
- buflen - offset,
- ",type="
- LINUX_RESERVED_UUID);
- else
- offset += snprintf(buf + offset,
- buflen - offset,
- ",type=linux");
+ switch (part->part_type) {
+ case PART_BINARY:
+ type_str = LINUX_RESERVED_UUID;
+ break;
+ case PART_FIP:
+ type_str = FIP_TYPE_UUID;
+ break;
+ default:
+ type_str = "linux";
+ break;
+ }
+ offset += snprintf(buf + offset,
+ buflen - offset,
+ ",type=%s", type_str);
if (part->part_type == PART_SYSTEM)
offset += snprintf(buf + offset,
buflen - offset,
",bootable");
+ /* partition UUID */
+ uuid_bin = NULL;
if (!rootfs_found && !strcmp(part->name, "rootfs")) {
mmc_id = part->dev_id;
rootfs_found = true;
- if (mmc_id < ARRAY_SIZE(uuid_mmc)) {
- uuid_bin =
- (unsigned char *)uuid_mmc[mmc_id].b;
- uuid_bin_to_str(uuid_bin, uuid,
- UUID_STR_FORMAT_GUID);
- offset += snprintf(buf + offset,
- buflen - offset,
- ",uuid=%s", uuid);
- }
+ if (mmc_id < ARRAY_SIZE(uuid_mmc))
+ uuid_bin = (unsigned char *)uuid_mmc[mmc_id].b;
+ }
+ if (part->part_type == PART_FIP) {
+ for (j = 0; j < ARRAY_SIZE(fip_part_name); j++)
+ if (!strcmp(part->name, fip_part_name[j])) {
+ uuid_bin = (unsigned char *)fip_part_uuid[j].b;
+ break;
+ }
+ }
+ if (uuid_bin) {
+ uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID);
+ offset += snprintf(buf + offset,
+ buflen - offset,
+ ",uuid=%s", uuid);
}
offset += snprintf(buf + offset, buflen - offset, ";");
@@ -1154,7 +1344,9 @@ static int dfu_init_entities(struct stm32prog_data *data)
struct dfu_entity *dfu;
int alt_nb;
- alt_nb = 2; /* number of virtual = CMD, OTP*/
+ alt_nb = 1; /* number of virtual = CMD*/
+ if (IS_ENABLED(CONFIG_CMD_STM32PROG_OTP))
+ alt_nb++; /* OTP*/
if (CONFIG_IS_ENABLED(DM_PMIC))
alt_nb++; /* PMIC NVMEM*/
@@ -1205,8 +1397,12 @@ static int dfu_init_entities(struct stm32prog_data *data)
if (!ret)
ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, CMD_SIZE);
- if (!ret)
- ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, OTP_SIZE);
+ if (!ret && IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) {
+ ret = optee_ta_open(data);
+ log_debug("optee_ta result %d\n", ret);
+ ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP,
+ data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC);
+ }
if (!ret && CONFIG_IS_ENABLED(DM_PMIC))
ret = stm32prog_alt_add_virt(dfu, "PMIC", PHASE_PMIC, PMIC_SIZE);
@@ -1224,19 +1420,26 @@ static int dfu_init_entities(struct stm32prog_data *data)
int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
long *size)
{
+ u32 otp_size = data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC;
log_debug("%s: %x %lx\n", __func__, offset, *size);
+ if (!IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) {
+ stm32prog_err("OTP update not supported");
+
+ return -ENOTSUPP;
+ }
+
if (!data->otp_part) {
- data->otp_part = memalign(CONFIG_SYS_CACHELINE_SIZE, OTP_SIZE);
+ data->otp_part = memalign(CONFIG_SYS_CACHELINE_SIZE, otp_size);
if (!data->otp_part)
return -ENOMEM;
}
if (!offset)
- memset(data->otp_part, 0, OTP_SIZE);
+ memset(data->otp_part, 0, otp_size);
- if (offset + *size > OTP_SIZE)
- *size = OTP_SIZE - offset;
+ if (offset + *size > otp_size)
+ *size = otp_size - offset;
memcpy((void *)((u32)data->otp_part + offset), buffer, *size);
@@ -1246,12 +1449,13 @@ int stm32prog_otp_write(struct stm32prog_data *data, u32 offset, u8 *buffer,
int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
long *size)
{
+ u32 otp_size = data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC;
int result = 0;
- if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
+ if (!IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) {
stm32prog_err("OTP update not supported");
- return -1;
+ return -ENOTSUPP;
}
log_debug("%s: %x %lx\n", __func__, offset, *size);
@@ -1259,7 +1463,7 @@ int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
if (!offset) {
if (!data->otp_part)
data->otp_part =
- memalign(CONFIG_SYS_CACHELINE_SIZE, OTP_SIZE);
+ memalign(CONFIG_SYS_CACHELINE_SIZE, otp_size);
if (!data->otp_part) {
result = -ENOMEM;
@@ -1267,11 +1471,16 @@ int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
}
/* init struct with 0 */
- memset(data->otp_part, 0, OTP_SIZE);
+ memset(data->otp_part, 0, otp_size);
/* call the service */
- result = stm32_smc_exec(STM32_SMC_BSEC, STM32_SMC_READ_ALL,
- (u32)data->otp_part, 0);
+ result = -ENOTSUPP;
+ if (data->tee && CONFIG_IS_ENABLED(OPTEE))
+ result = optee_ta_invoke(data, TA_NVMEM_READ, NVMEM_OTP,
+ data->otp_part, OTP_SIZE_TA);
+ else if (IS_ENABLED(CONFIG_ARM_SMCCC))
+ result = stm32_smc_exec(STM32_SMC_BSEC, STM32_SMC_READ_ALL,
+ (u32)data->otp_part, 0);
if (result)
goto end_otp_read;
}
@@ -1281,8 +1490,8 @@ int stm32prog_otp_read(struct stm32prog_data *data, u32 offset, u8 *buffer,
goto end_otp_read;
}
- if (offset + *size > OTP_SIZE)
- *size = OTP_SIZE - offset;
+ if (offset + *size > otp_size)
+ *size = otp_size - offset;
memcpy(buffer, (void *)((u32)data->otp_part + offset), *size);
end_otp_read:
@@ -1296,10 +1505,10 @@ int stm32prog_otp_start(struct stm32prog_data *data)
int result = 0;
struct arm_smccc_res res;
- if (!IS_ENABLED(CONFIG_ARM_SMCCC)) {
+ if (!IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) {
stm32prog_err("OTP update not supported");
- return -1;
+ return -ENOTSUPP;
}
if (!data->otp_part) {
@@ -1307,28 +1516,34 @@ int stm32prog_otp_start(struct stm32prog_data *data)
return -1;
}
- arm_smccc_smc(STM32_SMC_BSEC, STM32_SMC_WRITE_ALL,
- (u32)data->otp_part, 0, 0, 0, 0, 0, &res);
-
- if (!res.a0) {
- switch (res.a1) {
- case 0:
- result = 0;
- break;
- case 1:
- stm32prog_err("Provisioning");
- result = 0;
- break;
- default:
- log_err("%s: OTP incorrect value (err = %ld)\n",
- __func__, res.a1);
+ result = -ENOTSUPP;
+ if (data->tee && CONFIG_IS_ENABLED(OPTEE)) {
+ result = optee_ta_invoke(data, TA_NVMEM_WRITE, NVMEM_OTP,
+ data->otp_part, OTP_SIZE_TA);
+ } else if (IS_ENABLED(CONFIG_ARM_SMCCC)) {
+ arm_smccc_smc(STM32_SMC_BSEC, STM32_SMC_WRITE_ALL,
+ (u32)data->otp_part, 0, 0, 0, 0, 0, &res);
+
+ if (!res.a0) {
+ switch (res.a1) {
+ case 0:
+ result = 0;
+ break;
+ case 1:
+ stm32prog_err("Provisioning");
+ result = 0;
+ break;
+ default:
+ log_err("%s: OTP incorrect value (err = %ld)\n",
+ __func__, res.a1);
+ result = -EINVAL;
+ break;
+ }
+ } else {
+ log_err("%s: Failed to exec svc=%x op=%x in secure mode (err = %ld)\n",
+ __func__, STM32_SMC_BSEC, STM32_SMC_WRITE_ALL, res.a0);
result = -EINVAL;
- break;
}
- } else {
- log_err("%s: Failed to exec svc=%x op=%x in secure mode (err = %ld)\n",
- __func__, STM32_SMC_BSEC, STM32_SMC_WRITE_ALL, res.a0);
- result = -EINVAL;
}
free(data->otp_part);
@@ -1431,7 +1646,7 @@ static int stm32prog_copy_fsbl(struct stm32prog_part_t *part)
int ret, i;
void *fsbl;
struct image_header_s header;
- struct raw_header_s raw_header;
+ struct stm32_header_v2 raw_header; /* V2 size > v1 size */
struct dfu_entity *dfu;
long size, offset;
@@ -1443,17 +1658,18 @@ static int stm32prog_copy_fsbl(struct stm32prog_part_t *part)
/* read header */
dfu_transaction_cleanup(dfu);
- size = BL_HEADER_SIZE;
+ size = sizeof(raw_header);
ret = dfu->read_medium(dfu, 0, (void *)&raw_header, &size);
if (ret)
return ret;
- stm32prog_header_check(&raw_header, &header);
- if (header.type != HEADER_STM32IMAGE)
+ stm32prog_header_check((ulong)&raw_header, &header);
+ if (header.type != HEADER_STM32IMAGE &&
+ header.type != HEADER_STM32IMAGE_V2)
return -ENOENT;
/* read header + payload */
- size = header.image_length + BL_HEADER_SIZE;
+ size = header.image_length + header.length;
size = round_up(size, part->dev->mtd->erasesize);
fsbl = calloc(1, size);
if (!fsbl)
@@ -1483,7 +1699,16 @@ error:
static void stm32prog_end_phase(struct stm32prog_data *data, u64 offset)
{
if (data->phase == PHASE_FLASHLAYOUT) {
- if (parse_flash_layout(data, STM32_DDR_BASE, 0))
+#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
+ if (genimg_get_format((void *)STM32_DDR_BASE) == IMAGE_FORMAT_LEGACY) {
+ data->script = STM32_DDR_BASE;
+ data->phase = PHASE_END;
+ log_notice("U-Boot script received\n");
+ return;
+ }
+#endif
+ log_notice("\nFlashLayout received, size = %lld\n", offset);
+ if (parse_flash_layout(data, STM32_DDR_BASE, offset))
stm32prog_err("Layout: invalid FlashLayout");
return;
}
@@ -1739,6 +1964,12 @@ void stm32prog_clean(struct stm32prog_data *data)
free(data->part_array);
free(data->otp_part);
free(data->buffer);
+
+ if (CONFIG_IS_ENABLED(OPTEE) && data->tee) {
+ tee_close_session(data->tee, data->tee_session);
+ data->tee = NULL;
+ data->tee_session = 0x0;
+ }
}
/* DFU callback: used after serial and direct DFU USB access */
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
index 240c5c44bc..ac300768ca 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
@@ -20,7 +20,8 @@
#define DEFAULT_ADDRESS 0xFFFFFFFF
#define CMD_SIZE 512
-#define OTP_SIZE 1024
+#define OTP_SIZE_SMC 1024
+#define OTP_SIZE_TA 776
#define PMIC_SIZE 8
enum stm32prog_target {
@@ -41,6 +42,7 @@ enum stm32prog_link_t {
enum stm32prog_header_t {
HEADER_NONE,
HEADER_STM32IMAGE,
+ HEADER_STM32IMAGE_V2,
HEADER_FIP,
};
@@ -48,11 +50,12 @@ struct image_header_s {
enum stm32prog_header_t type;
u32 image_checksum;
u32 image_length;
+ u32 length;
};
-struct raw_header_s {
+struct stm32_header_v1 {
u32 magic_number;
- u32 image_signature[64 / 4];
+ u8 image_signature[64];
u32 image_checksum;
u32 header_version;
u32 image_length;
@@ -63,19 +66,38 @@ struct raw_header_s {
u32 version_number;
u32 option_flags;
u32 ecdsa_algorithm;
- u32 ecdsa_public_key[64 / 4];
- u32 padding[83 / 4];
- u32 binary_type;
+ u8 ecdsa_public_key[64];
+ u8 padding[83];
+ u8 binary_type;
};
-#define BL_HEADER_SIZE sizeof(struct raw_header_s)
+struct stm32_header_v2 {
+ u32 magic_number;
+ u8 image_signature[64];
+ u32 image_checksum;
+ u32 header_version;
+ u32 image_length;
+ u32 image_entry_point;
+ u32 reserved1;
+ u32 load_address;
+ u32 reserved2;
+ u32 version_number;
+ u32 extension_flags;
+ u32 extension_headers_length;
+ u32 binary_type;
+ u8 padding[16];
+ u32 extension_header_type;
+ u32 extension_header_length;
+ u8 extension_padding[376];
+};
/* partition type in flashlayout file */
enum stm32prog_part_type {
PART_BINARY,
+ PART_FIP,
PART_SYSTEM,
PART_FILESYSTEM,
- RAW_IMAGE
+ RAW_IMAGE,
};
/* device information */
@@ -147,6 +169,12 @@ struct stm32prog_data {
u32 dtb;
u32 initrd;
u32 initrd_size;
+
+ u32 script;
+
+ /* OPTEE PTA NVMEM */
+ struct udevice *tee;
+ u32 tee_session;
};
extern struct stm32prog_data *stm32prog_data;
@@ -166,8 +194,7 @@ int stm32prog_pmic_read(struct stm32prog_data *data, u32 offset,
int stm32prog_pmic_start(struct stm32prog_data *data);
/* generic part*/
-void stm32prog_header_check(struct raw_header_s *raw_header,
- struct image_header_s *header);
+void stm32prog_header_check(uintptr_t raw_header, struct image_header_s *header);
int stm32prog_dfu_init(struct stm32prog_data *data);
void stm32prog_next_phase(struct stm32prog_data *data);
void stm32prog_do_reset(struct stm32prog_data *data);
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
index e8acc302f9..a8b57c4d8f 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c
@@ -181,7 +181,7 @@ int stm32prog_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
*size = CMD_SIZE;
break;
case PHASE_OTP:
- *size = OTP_SIZE;
+ *size = stm32prog_data->tee ? OTP_SIZE_TA : OTP_SIZE_SMC;
break;
case PHASE_PMIC:
*size = PMIC_SIZE;
@@ -206,9 +206,12 @@ bool stm32prog_usb_loop(struct stm32prog_data *data, int dev)
g_dnl_set_product(product);
if (stm32prog_data->phase == PHASE_FLASHLAYOUT) {
+ /* forget any previous Control C */
+ clear_ctrlc();
ret = run_usb_dnl_gadget(dev, "usb_dnl_dfu");
- if (ret || stm32prog_data->phase != PHASE_FLASHLAYOUT)
- return ret;
+ /* DFU reset received, no error or CtrlC */
+ if (ret || stm32prog_data->phase != PHASE_FLASHLAYOUT || had_ctrlc())
+ return ret; /* true = reset on DFU error */
/* prepare the second enumeration with the FlashLayout */
stm32prog_dfu_init(data);
}
diff --git a/arch/arm/mach-stm32mp/config.mk b/arch/arm/mach-stm32mp/config.mk
deleted file mode 100644
index f7f5b77c41..0000000000
--- a/arch/arm/mach-stm32mp/config.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-#
-# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
-#
-
-ifndef CONFIG_SPL
-INPUTS-$(CONFIG_STM32MP15x_STM32IMAGE) += u-boot.stm32
-else
-ifdef CONFIG_SPL_BUILD
-INPUTS-y += u-boot-spl.stm32
-endif
-endif
-
-MKIMAGEFLAGS_u-boot.stm32 = -T stm32image -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
-
-u-boot.stm32: MKIMAGEOUTPUT = u-boot.stm32.log
-
-u-boot.stm32: u-boot.bin FORCE
- $(call if_changed,mkimage)
-
-MKIMAGEFLAGS_u-boot-spl.stm32 = -T stm32image -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE)
-
-spl/u-boot-spl.stm32: MKIMAGEOUTPUT = spl/u-boot-spl.stm32.log
-
-spl/u-boot-spl.stm32: spl/u-boot-spl.bin FORCE
- $(call if_changed,mkimage)
-
-u-boot-spl.stm32 : spl/u-boot-spl.stm32
- $(call if_changed,copy)
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index eb79f3ffd2..2f17833579 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -16,7 +16,6 @@
#include <misc.h>
#include <net.h>
#include <asm/io.h>
-#include <asm/arch/bsec.h>
#include <asm/arch/stm32.h>
#include <asm/arch/sys_proto.h>
#include <asm/global_data.h>
@@ -24,66 +23,10 @@
#include <dm/uclass.h>
#include <linux/bitops.h>
-/* RCC register */
-#define RCC_TZCR (STM32_RCC_BASE + 0x00)
-#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C)
-#define RCC_BDCR (STM32_RCC_BASE + 0x0140)
-#define RCC_MP_APB5ENSETR (STM32_RCC_BASE + 0x0208)
-#define RCC_MP_AHB5ENSETR (STM32_RCC_BASE + 0x0210)
-#define RCC_BDCR_VSWRST BIT(31)
-#define RCC_BDCR_RTCSRC GENMASK(17, 16)
-#define RCC_DBGCFGR_DBGCKEN BIT(8)
-
-/* Security register */
-#define ETZPC_TZMA1_SIZE (STM32_ETZPC_BASE + 0x04)
-#define ETZPC_DECPROT0 (STM32_ETZPC_BASE + 0x10)
-
-#define TZC_GATE_KEEPER (STM32_TZC_BASE + 0x008)
-#define TZC_REGION_ATTRIBUTE0 (STM32_TZC_BASE + 0x110)
-#define TZC_REGION_ID_ACCESS0 (STM32_TZC_BASE + 0x114)
-
-#define TAMP_CR1 (STM32_TAMP_BASE + 0x00)
-
-#define PWR_CR1 (STM32_PWR_BASE + 0x00)
-#define PWR_MCUCR (STM32_PWR_BASE + 0x14)
-#define PWR_CR1_DBP BIT(8)
-#define PWR_MCUCR_SBF BIT(6)
-
-/* DBGMCU register */
-#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00)
-#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C)
-#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
-#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
-#define DBGMCU_IDC_DEV_ID_SHIFT 0
-#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
-#define DBGMCU_IDC_REV_ID_SHIFT 16
-
-/* GPIOZ registers */
-#define GPIOZ_SECCFGR 0x54004030
-
-/* boot interface from Bootrom
- * - boot instance = bit 31:16
- * - boot device = bit 15:0
- */
-#define BOOTROM_PARAM_ADDR 0x2FFC0078
-#define BOOTROM_MODE_MASK GENMASK(15, 0)
-#define BOOTROM_MODE_SHIFT 0
-#define BOOTROM_INSTANCE_MASK GENMASK(31, 16)
-#define BOOTROM_INSTANCE_SHIFT 16
-
/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
#define RPN_SHIFT 0
-#define RPN_MASK GENMASK(7, 0)
-
-/* Package = bit 27:29 of OTP16
- * - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
- * - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
- * - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
- * - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
- * - others: Reserved
- */
-#define PKG_SHIFT 27
-#define PKG_MASK GENMASK(2, 0)
+#define RPN_MASK_STM32MP13x GENMASK(14, 0)
+#define RPN_MASK_STM32MP15x GENMASK(7, 0)
/*
* early TLB into the .data section so that it not get cleared
@@ -93,120 +36,6 @@ u8 early_tlb[PGTABLE_SIZE] __section(".data") __aligned(0x4000);
struct lmb lmb;
-#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
-#ifndef CONFIG_TFABOOT
-static void security_init(void)
-{
- /* Disable the backup domain write protection */
- /* the protection is enable at each reset by hardware */
- /* And must be disable by software */
- setbits_le32(PWR_CR1, PWR_CR1_DBP);
-
- while (!(readl(PWR_CR1) & PWR_CR1_DBP))
- ;
-
- /* If RTC clock isn't enable so this is a cold boot then we need
- * to reset the backup domain
- */
- if (!(readl(RCC_BDCR) & RCC_BDCR_RTCSRC)) {
- setbits_le32(RCC_BDCR, RCC_BDCR_VSWRST);
- while (!(readl(RCC_BDCR) & RCC_BDCR_VSWRST))
- ;
- clrbits_le32(RCC_BDCR, RCC_BDCR_VSWRST);
- }
-
- /* allow non secure access in Write/Read for all peripheral */
- writel(GENMASK(25, 0), ETZPC_DECPROT0);
-
- /* Open SYSRAM for no secure access */
- writel(0x0, ETZPC_TZMA1_SIZE);
-
- /* enable TZC1 TZC2 clock */
- writel(BIT(11) | BIT(12), RCC_MP_APB5ENSETR);
-
- /* Region 0 set to no access by default */
- /* bit 0 / 16 => nsaid0 read/write Enable
- * bit 1 / 17 => nsaid1 read/write Enable
- * ...
- * bit 15 / 31 => nsaid15 read/write Enable
- */
- writel(0xFFFFFFFF, TZC_REGION_ID_ACCESS0);
- /* bit 30 / 31 => Secure Global Enable : write/read */
- /* bit 0 / 1 => Region Enable for filter 0/1 */
- writel(BIT(0) | BIT(1) | BIT(30) | BIT(31), TZC_REGION_ATTRIBUTE0);
-
- /* Enable Filter 0 and 1 */
- setbits_le32(TZC_GATE_KEEPER, BIT(0) | BIT(1));
-
- /* RCC trust zone deactivated */
- writel(0x0, RCC_TZCR);
-
- /* TAMP: deactivate the internal tamper
- * Bit 23 ITAMP8E: monotonic counter overflow
- * Bit 20 ITAMP5E: RTC calendar overflow
- * Bit 19 ITAMP4E: HSE monitoring
- * Bit 18 ITAMP3E: LSE monitoring
- * Bit 16 ITAMP1E: RTC power domain supply monitoring
- */
- writel(0x0, TAMP_CR1);
-
- /* GPIOZ: deactivate the security */
- writel(BIT(0), RCC_MP_AHB5ENSETR);
- writel(0x0, GPIOZ_SECCFGR);
-}
-#endif /* CONFIG_TFABOOT */
-
-/*
- * Debug init
- */
-static void dbgmcu_init(void)
-{
- /*
- * Freeze IWDG2 if Cortex-A7 is in debug mode
- * done in TF-A for TRUSTED boot and
- * DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE
- */
- if (!IS_ENABLED(CONFIG_TFABOOT) && bsec_dbgswenable()) {
- setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
- setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2);
- }
-}
-
-void spl_board_init(void)
-{
- dbgmcu_init();
-}
-#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
-
-#if !defined(CONFIG_TFABOOT) && \
- (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
-/* get bootmode from ROM code boot context: saved in TAMP register */
-static void update_bootmode(void)
-{
- u32 boot_mode;
- u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR);
- u32 bootrom_device, bootrom_instance;
-
- /* enable TAMP clock = RTCAPBEN */
- writel(BIT(8), RCC_MP_APB5ENSETR);
-
- /* read bootrom context */
- bootrom_device =
- (bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT;
- bootrom_instance =
- (bootrom_itf & BOOTROM_INSTANCE_MASK) >> BOOTROM_INSTANCE_SHIFT;
- boot_mode =
- ((bootrom_device << BOOT_TYPE_SHIFT) & BOOT_TYPE_MASK) |
- ((bootrom_instance << BOOT_INSTANCE_SHIFT) &
- BOOT_INSTANCE_MASK);
-
- /* save the boot mode in TAMP backup register */
- clrsetbits_le32(TAMP_BOOT_CONTEXT,
- TAMP_BOOT_MODE_MASK,
- boot_mode << TAMP_BOOT_MODE_SHIFT);
-}
-#endif
-
u32 get_bootmode(void)
{
/* read bootmode from TAMP backup register */
@@ -228,8 +57,11 @@ void dram_bank_mmu_setup(int bank)
enum dcache_option option;
if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+/* STM32_SYSRAM_BASE exist only when SPL is supported */
+#ifdef CONFIG_SPL
start = ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE);
size = ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE);
+#endif
} else if (gd->flags & GD_FLG_RELOC) {
/* bd->bi_dram is available only after relocation */
start = bd->bi_dram[bank].start;
@@ -276,36 +108,32 @@ static void early_enable_caches(void)
*/
int arch_cpu_init(void)
{
- u32 boot_mode;
-
early_enable_caches();
/* early armv7 timer init: needed for polling */
timer_init();
-#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
-#ifndef CONFIG_TFABOOT
- security_init();
- update_bootmode();
-#endif
- /* Reset Coprocessor state unless it wakes up from Standby power mode */
- if (!(readl(PWR_MCUCR) & PWR_MCUCR_SBF)) {
- writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE);
- writel(0, TAMP_COPRO_RSC_TBL_ADDRESS);
- }
-#endif
+ return 0;
+}
+
+/* weak function for SOC specific initialization */
+__weak void stm32mp_cpu_init(void)
+{
+}
+
+int mach_cpu_init(void)
+{
+ u32 boot_mode;
+
+ stm32mp_cpu_init();
boot_mode = get_bootmode();
if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) &&
(boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART)
gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
-#if defined(CONFIG_DEBUG_UART) && \
- !defined(CONFIG_TFABOOT) && \
- (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
- else
+ else if (IS_ENABLED(CONFIG_DEBUG_UART) && IS_ENABLED(CONFIG_SPL_BUILD))
debug_uart_init();
-#endif
return 0;
}
@@ -326,140 +154,26 @@ void enable_caches(void)
dcache_enable();
}
-static u32 read_idc(void)
-{
- /* DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE */
- if (bsec_dbgswenable()) {
- setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
-
- return readl(DBGMCU_IDC);
- }
-
- if (CONFIG_IS_ENABLED(STM32MP15x))
- return CPU_DEV_STM32MP15; /* STM32MP15x and unknown revision */
- else
- return 0x0;
-}
-
-u32 get_cpu_dev(void)
-{
- return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
-}
-
-u32 get_cpu_rev(void)
-{
- return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
-}
-
-static u32 get_otp(int index, int shift, int mask)
-{
- int ret;
- struct udevice *dev;
- u32 otp = 0;
-
- ret = uclass_get_device_by_driver(UCLASS_MISC,
- DM_DRIVER_GET(stm32mp_bsec),
- &dev);
-
- if (!ret)
- ret = misc_read(dev, STM32_BSEC_SHADOW(index),
- &otp, sizeof(otp));
-
- return (otp >> shift) & mask;
-}
-
/* Get Device Part Number (RPN) from OTP */
static u32 get_cpu_rpn(void)
{
- return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK);
-}
-
-u32 get_cpu_type(void)
-{
- return (get_cpu_dev() << 16) | get_cpu_rpn();
-}
-
-/* Get Package options from OTP */
-u32 get_cpu_package(void)
-{
- return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
-}
-
-static const char * const soc_type[] = {
- "????",
- "151C", "151A", "151F", "151D",
- "153C", "153A", "153F", "153D",
- "157C", "157A", "157F", "157D"
-};
-
-static const char * const soc_pkg[] = { "??", "AD", "AC", "AB", "AA" };
-static const char * const soc_rev[] = { "?", "A", "B", "Z" };
+ int mask;
-static void get_cpu_string_offsets(unsigned int *type, unsigned int *pkg,
- unsigned int *rev)
-{
- u32 cpu_type = get_cpu_type();
- u32 ct = cpu_type & ~(BIT(7) | BIT(0));
- u32 cm = ((cpu_type & BIT(7)) >> 6) | (cpu_type & BIT(0));
- u32 cp = get_cpu_package();
-
- /* Bits 0 and 7 are the ACDF, 00:C 01:A 10:F 11:D */
- switch (ct) {
- case CPU_STM32MP151Cxx:
- *type = cm + 1;
- break;
- case CPU_STM32MP153Cxx:
- *type = cm + 5;
- break;
- case CPU_STM32MP157Cxx:
- *type = cm + 9;
- break;
- default:
- *type = 0;
- break;
- }
+ if (IS_ENABLED(CONFIG_STM32MP13x))
+ mask = RPN_MASK_STM32MP13x;
- /* Package */
- switch (cp) {
- case PKG_AA_LBGA448:
- case PKG_AB_LBGA354:
- case PKG_AC_TFBGA361:
- case PKG_AD_TFBGA257:
- *pkg = cp;
- break;
- default:
- *pkg = 0;
- break;
- }
+ if (IS_ENABLED(CONFIG_STM32MP15x))
+ mask = RPN_MASK_STM32MP15x;
- /* Revision */
- switch (get_cpu_rev()) {
- case CPU_REVA:
- *rev = 1;
- break;
- case CPU_REVB:
- *rev = 2;
- break;
- case CPU_REVZ:
- *rev = 3;
- break;
- default:
- *rev = 0;
- break;
- }
+ return get_otp(BSEC_OTP_RPN, RPN_SHIFT, mask);
}
-void get_soc_name(char name[SOC_NAME_SIZE])
+u32 get_cpu_type(void)
{
- unsigned int type, pkg, rev;
-
- get_cpu_string_offsets(&type, &pkg, &rev);
-
- snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s",
- soc_type[type], soc_pkg[pkg], soc_rev[rev]);
+ return (get_cpu_dev() << 16) | get_cpu_rpn();
}
-#if defined(CONFIG_DISPLAY_CPUINFO)
+/* used when CONFIG_DISPLAY_CPUINFO is activated */
int print_cpuinfo(void)
{
char name[SOC_NAME_SIZE];
@@ -469,7 +183,6 @@ int print_cpuinfo(void)
return 0;
}
-#endif /* CONFIG_DISPLAY_CPUINFO */
static void setup_boot_mode(void)
{
@@ -599,40 +312,52 @@ static void setup_boot_mode(void)
*/
__weak int setup_mac_address(void)
{
-#if defined(CONFIG_NET)
int ret;
int i;
- u32 otp[2];
+ u32 otp[3];
uchar enetaddr[6];
struct udevice *dev;
+ int nb_eth, nb_otp, index;
- /* MAC already in environment */
- if (eth_env_get_enetaddr("ethaddr", enetaddr))
+ if (!IS_ENABLED(CONFIG_NET))
return 0;
+ nb_eth = get_eth_nb();
+
+ /* 6 bytes for each MAC addr and 4 bytes for each OTP */
+ nb_otp = DIV_ROUND_UP(6 * nb_eth, 4);
+
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(stm32mp_bsec),
&dev);
if (ret)
return ret;
- ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_MAC),
- otp, sizeof(otp));
+ ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_MAC), otp, 4 * nb_otp);
if (ret < 0)
return ret;
- for (i = 0; i < 6; i++)
- enetaddr[i] = ((uint8_t *)&otp)[i];
+ for (index = 0; index < nb_eth; index++) {
+ /* MAC already in environment */
+ if (eth_env_get_enetaddr_by_index("eth", index, enetaddr))
+ continue;
- if (!is_valid_ethaddr(enetaddr)) {
- log_err("invalid MAC address in OTP %pM\n", enetaddr);
- return -EINVAL;
+ for (i = 0; i < 6; i++)
+ enetaddr[i] = ((uint8_t *)&otp)[i + 6 * index];
+
+ if (!is_valid_ethaddr(enetaddr)) {
+ log_err("invalid MAC address %d in OTP %pM\n",
+ index, enetaddr);
+ return -EINVAL;
+ }
+ log_debug("OTP MAC address %d = %pM\n", index, enetaddr);
+ ret = eth_env_set_enetaddr_by_index("eth", index, enetaddr);
+ if (ret) {
+ log_err("Failed to set mac address %pM from OTP: %d\n",
+ enetaddr, ret);
+ return ret;
+ }
}
- log_debug("OTP MAC address = %pM\n", enetaddr);
- ret = eth_env_set_enetaddr("ethaddr", enetaddr);
- if (ret)
- log_err("Failed to set mac address %pM from OTP: %d\n", enetaddr, ret);
-#endif
return 0;
}
@@ -664,15 +389,8 @@ static int setup_serial_number(void)
return 0;
}
-static void setup_soc_type_pkg_rev(void)
+__weak void stm32mp_misc_init(void)
{
- unsigned int type, pkg, rev;
-
- get_cpu_string_offsets(&type, &pkg, &rev);
-
- env_set("soc_type", soc_type[type]);
- env_set("soc_pkg", soc_pkg[pkg]);
- env_set("soc_rev", soc_rev[rev]);
}
int arch_misc_init(void)
@@ -680,7 +398,7 @@ int arch_misc_init(void)
setup_boot_mode();
setup_mac_address();
setup_serial_number();
- setup_soc_type_pkg_rev();
+ stm32mp_misc_init();
return 0;
}
diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c
index a19e954cf7..3201aba03e 100644
--- a/arch/arm/mach-stm32mp/fdt.c
+++ b/arch/arm/mach-stm32mp/fdt.c
@@ -28,13 +28,120 @@
#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
+#define STM32MP13_FDCAN_BASE 0x4400F000
+#define STM32MP13_ADC1_BASE 0x48003000
+#define STM32MP13_TSC_BASE 0x5000B000
+#define STM32MP13_CRYP_BASE 0x54002000
+#define STM32MP13_ETH2_BASE 0x5800E000
+#define STM32MP13_DCMIPP_BASE 0x5A000000
+#define STM32MP13_LTDC_BASE 0x5A010000
+
+#define STM32MP15_FDCAN_BASE 0x4400e000
+#define STM32MP15_CRYP2_BASE 0x4c005000
+#define STM32MP15_CRYP1_BASE 0x54001000
+#define STM32MP15_GPU_BASE 0x59000000
+#define STM32MP15_DSI_BASE 0x5a000000
+
+static const u32 stm32mp13_ip_addr[] = {
+ 0x50025000, /* 0 VREFBUF APB3 */
+ 0x50021000, /* 1 LPTIM2 APB3 */
+ 0x50022000, /* 2 LPTIM3 APB3 */
+ STM32MP13_LTDC_BASE, /* 3 LTDC APB4 */
+ STM32MP13_DCMIPP_BASE, /* 4 DCMIPP APB4 */
+ 0x5A006000, /* 5 USBPHYCTRL APB4 */
+ 0x5A003000, /* 6 DDRCTRLPHY APB4 */
+ ETZPC_RESERVED, /* 7 Reserved*/
+ ETZPC_RESERVED, /* 8 Reserved*/
+ ETZPC_RESERVED, /* 9 Reserved*/
+ 0x5C006000, /* 10 TZC APB5 */
+ 0x58001000, /* 11 MCE APB5 */
+ 0x5C000000, /* 12 IWDG1 APB5 */
+ 0x5C008000, /* 13 STGENC APB5 */
+ ETZPC_RESERVED, /* 14 Reserved*/
+ ETZPC_RESERVED, /* 15 Reserved*/
+ 0x4C000000, /* 16 USART1 APB6 */
+ 0x4C001000, /* 17 USART2 APB6 */
+ 0x4C002000, /* 18 SPI4 APB6 */
+ 0x4C003000, /* 19 SPI5 APB6 */
+ 0x4C004000, /* 20 I2C3 APB6 */
+ 0x4C005000, /* 21 I2C4 APB6 */
+ 0x4C006000, /* 22 I2C5 APB6 */
+ 0x4C007000, /* 23 TIM12 APB6 */
+ 0x4C008000, /* 24 TIM13 APB6 */
+ 0x4C009000, /* 25 TIM14 APB6 */
+ 0x4C00A000, /* 26 TIM15 APB6 */
+ 0x4C00B000, /* 27 TIM16 APB6 */
+ 0x4C00C000, /* 28 TIM17 APB6 */
+ ETZPC_RESERVED, /* 29 Reserved*/
+ ETZPC_RESERVED, /* 30 Reserved*/
+ ETZPC_RESERVED, /* 31 Reserved*/
+ STM32MP13_ADC1_BASE, /* 32 ADC1 AHB2 */
+ 0x48004000, /* 33 ADC2 AHB2 */
+ 0x49000000, /* 34 OTG AHB2 */
+ ETZPC_RESERVED, /* 35 Reserved*/
+ ETZPC_RESERVED, /* 36 Reserved*/
+ STM32MP13_TSC_BASE, /* 37 TSC AHB4 */
+ ETZPC_RESERVED, /* 38 Reserved*/
+ ETZPC_RESERVED, /* 39 Reserved*/
+ 0x54004000, /* 40 RNG AHB5 */
+ 0x54003000, /* 41 HASH AHB5 */
+ STM32MP13_CRYP_BASE, /* 42 CRYPT AHB5 */
+ 0x54005000, /* 43 SAES AHB5 */
+ 0x54006000, /* 44 PKA AHB5 */
+ 0x54000000, /* 45 BKPSRAM AHB5 */
+ ETZPC_RESERVED, /* 46 Reserved*/
+ ETZPC_RESERVED, /* 47 Reserved*/
+ 0x5800A000, /* 48 ETH1 AHB6 */
+ STM32MP13_ETH2_BASE, /* 49 ETH2 AHB6 */
+ 0x58005000, /* 50 SDMMC1 AHB6 */
+ 0x58007000, /* 51 SDMMC2 AHB6 */
+ ETZPC_RESERVED, /* 52 Reserved*/
+ ETZPC_RESERVED, /* 53 Reserved*/
+ 0x58002000, /* 54 FMC AHB6 */
+ 0x58003000, /* 55 QSPI AHB6 */
+ ETZPC_RESERVED, /* 56 Reserved*/
+ ETZPC_RESERVED, /* 57 Reserved*/
+ ETZPC_RESERVED, /* 58 Reserved*/
+ ETZPC_RESERVED, /* 59 Reserved*/
+ 0x30000000, /* 60 SRAM1 MLAHB */
+ 0x30004000, /* 61 SRAM2 MLAHB */
+ 0x30006000, /* 62 SRAM3 MLAHB */
+ ETZPC_RESERVED, /* 63 Reserved*/
+ ETZPC_RESERVED, /* 64 Reserved*/
+ ETZPC_RESERVED, /* 65 Reserved*/
+ ETZPC_RESERVED, /* 66 Reserved*/
+ ETZPC_RESERVED, /* 67 Reserved*/
+ ETZPC_RESERVED, /* 68 Reserved*/
+ ETZPC_RESERVED, /* 69 Reserved*/
+ ETZPC_RESERVED, /* 70 Reserved*/
+ ETZPC_RESERVED, /* 71 Reserved*/
+ ETZPC_RESERVED, /* 72 Reserved*/
+ ETZPC_RESERVED, /* 73 Reserved*/
+ ETZPC_RESERVED, /* 74 Reserved*/
+ ETZPC_RESERVED, /* 75 Reserved*/
+ ETZPC_RESERVED, /* 76 Reserved*/
+ ETZPC_RESERVED, /* 77 Reserved*/
+ ETZPC_RESERVED, /* 78 Reserved*/
+ ETZPC_RESERVED, /* 79 Reserved*/
+ ETZPC_RESERVED, /* 80 Reserved*/
+ ETZPC_RESERVED, /* 81 Reserved*/
+ ETZPC_RESERVED, /* 82 Reserved*/
+ ETZPC_RESERVED, /* 83 Reserved*/
+ ETZPC_RESERVED, /* 84 Reserved*/
+ ETZPC_RESERVED, /* 85 Reserved*/
+ ETZPC_RESERVED, /* 86 Reserved*/
+ ETZPC_RESERVED, /* 87 Reserved*/
+ ETZPC_RESERVED, /* 88 Reserved*/
+ ETZPC_RESERVED, /* 89 Reserved*/
+ ETZPC_RESERVED, /* 90 Reserved*/
+ ETZPC_RESERVED, /* 91 Reserved*/
+ ETZPC_RESERVED, /* 92 Reserved*/
+ ETZPC_RESERVED, /* 93 Reserved*/
+ ETZPC_RESERVED, /* 94 Reserved*/
+ ETZPC_RESERVED, /* 95 Reserved*/
+};
-static const u32 stm32mp1_ip_addr[] = {
+static const u32 stm32mp15_ip_addr[] = {
0x5c008000, /* 00 stgenc */
0x54000000, /* 01 bkpsram */
0x5c003000, /* 02 iwdg1 */
@@ -44,7 +151,7 @@ static const u32 stm32mp1_ip_addr[] = {
ETZPC_RESERVED, /* 06 reserved */
0x54003000, /* 07 rng1 */
0x54002000, /* 08 hash1 */
- STM32_CRYP1_BASE, /* 09 cryp1 */
+ STM32MP15_CRYP1_BASE, /* 09 cryp1 */
0x5a003000, /* 0A ddrctrl */
0x5a004000, /* 0B ddrphyc */
0x5c009000, /* 0C i2c6 */
@@ -97,7 +204,7 @@ static const u32 stm32mp1_ip_addr[] = {
0x4400b000, /* 3B sai2 */
0x4400c000, /* 3C sai3 */
0x4400d000, /* 3D dfsdm */
- STM32_FDCAN_BASE, /* 3E tt_fdcan */
+ STM32MP15_FDCAN_BASE, /* 3E tt_fdcan */
ETZPC_RESERVED, /* 3F reserved */
0x50021000, /* 40 lptim2 */
0x50022000, /* 41 lptim3 */
@@ -110,7 +217,7 @@ static const u32 stm32mp1_ip_addr[] = {
0x48003000, /* 48 adc */
0x4c002000, /* 49 hash2 */
0x4c003000, /* 4A rng2 */
- STM32_CRYP2_BASE, /* 4B cryp2 */
+ STM32MP15_CRYP2_BASE, /* 4B cryp2 */
ETZPC_RESERVED, /* 4C reserved */
ETZPC_RESERVED, /* 4D reserved */
ETZPC_RESERVED, /* 4E reserved */
@@ -163,8 +270,14 @@ static int stm32_fdt_fixup_etzpc(void *fdt, int soc_node)
int offset, shift;
u32 addr, status, decprot[ETZPC_DECPROT_NB];
- array = stm32mp1_ip_addr;
- array_size = ARRAY_SIZE(stm32mp1_ip_addr);
+ if (IS_ENABLED(CONFIG_STM32MP13x)) {
+ array = stm32mp13_ip_addr;
+ array_size = ARRAY_SIZE(stm32mp13_ip_addr);
+ }
+ if (IS_ENABLED(CONFIG_STM32MP15x)) {
+ array = stm32mp15_ip_addr;
+ array_size = ARRAY_SIZE(stm32mp15_ip_addr);
+ }
for (i = 0; i < ETZPC_DECPROT_NB; i++)
decprot[i] = readl(ETZPC_DECPROT(i));
@@ -248,30 +361,46 @@ static void stm32_fdt_disable_optee(void *blob)
}
}
-/*
- * This function is called right before the kernel is booted. "blob" is the
- * device tree that will be passed to the kernel.
- */
-int ft_system_setup(void *blob, struct bd_info *bd)
+static void stm32mp13_fdt_fixup(void *blob, int soc, u32 cpu, char *name)
{
- int ret = 0;
- int soc;
- u32 pkg, cpu;
- char name[SOC_NAME_SIZE];
-
- soc = fdt_path_offset(blob, "/soc");
- if (soc < 0)
- return soc;
+ switch (cpu) {
+ case CPU_STM32MP131Fxx:
+ case CPU_STM32MP131Dxx:
+ case CPU_STM32MP131Cxx:
+ case CPU_STM32MP131Axx:
+ stm32_fdt_disable(blob, soc, STM32MP13_FDCAN_BASE, "can", name);
+ stm32_fdt_disable(blob, soc, STM32MP13_ADC1_BASE, "adc", name);
+ fallthrough;
+ case CPU_STM32MP133Fxx:
+ case CPU_STM32MP133Dxx:
+ case CPU_STM32MP133Cxx:
+ case CPU_STM32MP133Axx:
+ stm32_fdt_disable(blob, soc, STM32MP13_LTDC_BASE, "ltdc", name);
+ stm32_fdt_disable(blob, soc, STM32MP13_DCMIPP_BASE, "dcmipp",
+ name);
+ stm32_fdt_disable(blob, soc, STM32MP13_TSC_BASE, "tsc", name);
+ break;
+ default:
+ break;
+ }
- if (CONFIG_IS_ENABLED(STM32_ETZPC)) {
- ret = stm32_fdt_fixup_etzpc(blob, soc);
- if (ret)
- return ret;
+ switch (cpu) {
+ case CPU_STM32MP135Dxx:
+ case CPU_STM32MP135Axx:
+ case CPU_STM32MP133Dxx:
+ case CPU_STM32MP133Axx:
+ case CPU_STM32MP131Dxx:
+ case CPU_STM32MP131Axx:
+ stm32_fdt_disable(blob, soc, STM32MP13_CRYP_BASE, "cryp", name);
+ break;
+ default:
+ break;
}
+}
- /* MPUs Part Numbers and name*/
- cpu = get_cpu_type();
- get_soc_name(name);
+static void stm32mp15_fdt_fixup(void *blob, int soc, u32 cpu, char *name)
+{
+ u32 pkg;
switch (cpu) {
case CPU_STM32MP151Fxx:
@@ -281,19 +410,18 @@ int ft_system_setup(void *blob, struct bd_info *bd)
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 */
+ stm32_fdt_disable(blob, soc, STM32MP15_FDCAN_BASE, "can", name);
+ fallthrough;
case CPU_STM32MP153Fxx:
case CPU_STM32MP153Dxx:
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);
+ stm32_fdt_disable(blob, soc, STM32MP15_GPU_BASE, "gpu", name);
+ stm32_fdt_disable(blob, soc, STM32MP15_DSI_BASE, "dsi", name);
break;
default:
break;
}
-
switch (cpu) {
case CPU_STM32MP157Dxx:
case CPU_STM32MP157Axx:
@@ -301,24 +429,25 @@ int ft_system_setup(void *blob, struct bd_info *bd)
case CPU_STM32MP153Axx:
case CPU_STM32MP151Dxx:
case CPU_STM32MP151Axx:
- stm32_fdt_disable(blob, soc, STM32_CRYP1_BASE, "cryp", name);
- stm32_fdt_disable(blob, soc, STM32_CRYP2_BASE, "cryp", name);
+ stm32_fdt_disable(blob, soc, STM32MP15_CRYP1_BASE, "cryp",
+ name);
+ stm32_fdt_disable(blob, soc, STM32MP15_CRYP2_BASE, "cryp",
+ name);
break;
default:
break;
}
-
switch (get_cpu_package()) {
- case PKG_AA_LBGA448:
+ case STM32MP15_PKG_AA_LBGA448:
pkg = STM32MP_PKG_AA;
break;
- case PKG_AB_LBGA354:
+ case STM32MP15_PKG_AB_LBGA354:
pkg = STM32MP_PKG_AB;
break;
- case PKG_AC_TFBGA361:
+ case STM32MP15_PKG_AC_TFBGA361:
pkg = STM32MP_PKG_AC;
break;
- case PKG_AD_TFBGA257:
+ case STM32MP15_PKG_AD_TFBGA257:
pkg = STM32MP_PKG_AD;
break;
default:
@@ -331,19 +460,54 @@ int ft_system_setup(void *blob, struct bd_info *bd)
do_fixup_by_compat_u32(blob, "st,stm32mp157-z-pinctrl",
"st,package", pkg, false);
}
+}
+
+/*
+ * This function is called right before the kernel is booted. "blob" is the
+ * device tree that will be passed to the kernel.
+ */
+int ft_system_setup(void *blob, struct bd_info *bd)
+{
+ int ret = 0;
+ int soc;
+ u32 cpu;
+ char name[SOC_NAME_SIZE];
+
+ soc = fdt_path_offset(blob, "/soc");
+ /* when absent, nothing to do */
+ if (soc == -FDT_ERR_NOTFOUND)
+ return 0;
+ if (soc < 0)
+ return soc;
+
+ if (CONFIG_IS_ENABLED(STM32_ETZPC)) {
+ ret = stm32_fdt_fixup_etzpc(blob, soc);
+ if (ret)
+ return ret;
+ }
- /*
- * TEMP: remove OP-TEE nodes in kernel device tree
- * copied from U-Boot device tree by optee_copy_fdt_nodes
- * when OP-TEE is not detected (probe failed)
- * these OP-TEE nodes are present in <board>-u-boot.dtsi
- * under CONFIG_STM32MP15x_STM32IMAGE only for compatibility
- * when FIP is not used by TF-A
- */
- if (CONFIG_IS_ENABLED(STM32MP15x_STM32IMAGE) &&
- CONFIG_IS_ENABLED(OPTEE) &&
- !tee_find_device(NULL, NULL, NULL, NULL))
- stm32_fdt_disable_optee(blob);
+ /* MPUs Part Numbers and name*/
+ cpu = get_cpu_type();
+ get_soc_name(name);
+
+ if (IS_ENABLED(CONFIG_STM32MP13x))
+ stm32mp13_fdt_fixup(blob, soc, cpu, name);
+ if (IS_ENABLED(CONFIG_STM32MP15x)) {
+ stm32mp15_fdt_fixup(blob, soc, cpu, name);
+
+ /*
+ * TEMP: remove OP-TEE nodes in kernel device tree
+ * copied from U-Boot device tree by optee_copy_fdt_nodes
+ * when OP-TEE is not detected (probe failed)
+ * these OP-TEE nodes are present in <board>-u-boot.dtsi
+ * under CONFIG_STM32MP15x_STM32IMAGE only for compatibility
+ * when FIP is not used by TF-A
+ */
+ if (CONFIG_IS_ENABLED(STM32MP15x_STM32IMAGE) &&
+ CONFIG_IS_ENABLED(OPTEE) &&
+ !tee_find_device(NULL, NULL, NULL, NULL))
+ stm32_fdt_disable_optee(blob);
+ }
return ret;
}
diff --git a/arch/arm/mach-stm32mp/include/mach/bsec.h b/arch/arm/mach-stm32mp/include/mach/bsec.h
index 252eac3946..f2e3a102a1 100644
--- a/arch/arm/mach-stm32mp/include/mach/bsec.h
+++ b/arch/arm/mach-stm32mp/include/mach/bsec.h
@@ -5,3 +5,11 @@
/* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */
bool bsec_dbgswenable(void);
+
+/* Bitfield definition for LOCK status */
+/* warning: bit 31 is reserved in PTA NVEM for OTP_UPDATE_REQ */
+#define BSEC_LOCK_PERM BIT(30)
+#define BSEC_LOCK_SHADOW_R BIT(29)
+#define BSEC_LOCK_SHADOW_W BIT(28)
+#define BSEC_LOCK_SHADOW_P BIT(27)
+#define BSEC_LOCK_ERROR BIT(26)
diff --git a/arch/arm/mach-stm32mp/include/mach/gpio.h b/arch/arm/mach-stm32mp/include/mach/gpio.h
deleted file mode 100644
index 7a0f293519..0000000000
--- a/arch/arm/mach-stm32mp/include/mach/gpio.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2016
- * Vikas Manocha, <vikas.manocha@st.com>
- */
-
-#ifndef _STM32_GPIO_H_
-#define _STM32_GPIO_H_
-#include <asm/gpio.h>
-
-enum stm32_gpio_mode {
- STM32_GPIO_MODE_IN = 0,
- STM32_GPIO_MODE_OUT,
- STM32_GPIO_MODE_AF,
- STM32_GPIO_MODE_AN
-};
-
-enum stm32_gpio_otype {
- STM32_GPIO_OTYPE_PP = 0,
- STM32_GPIO_OTYPE_OD
-};
-
-enum stm32_gpio_speed {
- STM32_GPIO_SPEED_2M = 0,
- STM32_GPIO_SPEED_25M,
- STM32_GPIO_SPEED_50M,
- STM32_GPIO_SPEED_100M
-};
-
-enum stm32_gpio_pupd {
- STM32_GPIO_PUPD_NO = 0,
- STM32_GPIO_PUPD_UP,
- STM32_GPIO_PUPD_DOWN
-};
-
-enum stm32_gpio_af {
- STM32_GPIO_AF0 = 0,
- STM32_GPIO_AF1,
- STM32_GPIO_AF2,
- STM32_GPIO_AF3,
- STM32_GPIO_AF4,
- STM32_GPIO_AF5,
- STM32_GPIO_AF6,
- STM32_GPIO_AF7,
- STM32_GPIO_AF8,
- STM32_GPIO_AF9,
- STM32_GPIO_AF10,
- STM32_GPIO_AF11,
- STM32_GPIO_AF12,
- STM32_GPIO_AF13,
- STM32_GPIO_AF14,
- STM32_GPIO_AF15
-};
-
-struct stm32_gpio_dsc {
- u8 port;
- u8 pin;
-};
-
-struct stm32_gpio_ctl {
- enum stm32_gpio_mode mode;
- enum stm32_gpio_otype otype;
- enum stm32_gpio_speed speed;
- enum stm32_gpio_pupd pupd;
- enum stm32_gpio_af af;
-};
-
-struct stm32_gpio_regs {
- u32 moder; /* GPIO port mode */
- u32 otyper; /* GPIO port output type */
- u32 ospeedr; /* GPIO port output speed */
- u32 pupdr; /* GPIO port pull-up/pull-down */
- u32 idr; /* GPIO port input data */
- u32 odr; /* GPIO port output data */
- u32 bsrr; /* GPIO port bit set/reset */
- u32 lckr; /* GPIO port configuration lock */
- u32 afr[2]; /* GPIO alternate function */
-};
-
-struct stm32_gpio_priv {
- struct stm32_gpio_regs *regs;
- unsigned int gpio_range;
-};
-
-int stm32_offset_to_index(struct udevice *dev, unsigned int offset);
-
-#endif /* _STM32_GPIO_H_ */
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index c11a9903f2..62acd76c01 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -16,15 +16,23 @@
*/
#define STM32_RCC_BASE 0x50000000
#define STM32_PWR_BASE 0x50001000
+#ifdef CONFIG_STM32MP15x
#define STM32_DBGMCU_BASE 0x50081000
+#endif
#define STM32_FMC2_BASE 0x58002000
#define STM32_TZC_BASE 0x5C006000
#define STM32_ETZPC_BASE 0x5C007000
#define STM32_STGEN_BASE 0x5C008000
#define STM32_TAMP_BASE 0x5C00A000
+#ifdef CONFIG_STM32MP15x
#define STM32_USART1_BASE 0x5C000000
#define STM32_USART2_BASE 0x4000E000
+#endif
+#ifdef CONFIG_STM32MP13x
+#define STM32_USART1_BASE 0x4c000000
+#define STM32_USART2_BASE 0x4c001000
+#endif
#define STM32_USART3_BASE 0x4000F000
#define STM32_UART4_BASE 0x40010000
#define STM32_UART5_BASE 0x40011000
@@ -36,8 +44,10 @@
#define STM32_SDMMC2_BASE 0x58007000
#define STM32_SDMMC3_BASE 0x48004000
+#ifdef CONFIG_STM32MP15x
#define STM32_SYSRAM_BASE 0x2FFC0000
#define STM32_SYSRAM_SIZE SZ_256K
+#endif
#define STM32_DDR_BASE 0xC0000000
#define STM32_DDR_SIZE SZ_1G
@@ -95,8 +105,12 @@ enum boot_device {
/* TAMP registers */
#define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 * x)
+
+#ifdef CONFIG_STM32MP15x
+/* secure access */
#define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4)
#define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5)
+/* non secure access */
#define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17)
#define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18)
#define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20)
@@ -108,6 +122,12 @@ enum boot_device {
#define TAMP_COPRO_STATE_CSTOP 3
#define TAMP_COPRO_STATE_STANDBY 4
#define TAMP_COPRO_STATE_CRASH 5
+#endif
+
+#ifdef CONFIG_STM32MP13x
+#define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(31)
+#define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(30)
+#endif
#define TAMP_BOOT_MODE_MASK GENMASK(15, 8)
#define TAMP_BOOT_MODE_SHIFT 8
@@ -135,11 +155,19 @@ enum forced_boot_mode {
#define STM32_BSEC_LOCK(id) (STM32_BSEC_LOCK_OFFSET + (id) * 4)
/* BSEC OTP index */
+#ifdef CONFIG_STM32MP15x
#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
+#ifdef CONFIG_STM32MP13x
+#define BSEC_OTP_RPN 1
+#define BSEC_OTP_SERIAL 13
+#define BSEC_OTP_MAC 57
+#define BSEC_OTP_BOARD 60
+#endif
#endif /* __ASSEMBLY__ */
#endif /* _MACH_STM32_H_ */
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
index 4ad14f963b..d72747ca31 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
@@ -8,19 +8,53 @@
#include <linux/arm-smccc.h>
+/* SMC service generic return codes */
+#define STM32_SMC_OK 0x00000000U
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
+#define STM32_SMC_FAILED 0xFFFFFFFEU
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
+
/*
- * SMC function IDs for STM32 Service queries
+ * SMC function IDs for STM32 Service queries.
* STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
* like this is defined in SMC calling Convention by ARM
- * for SiP (silicon Partner)
- * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+ * for SiP (silicon Partner).
+ * https://developer.arm.com/docs/den0028/latest
*/
-#define STM32_SMC_VERSION 0x82000000
/* Secure Service access from Non-secure */
+
+/*
+ * SMC function STM32_SMC_PWR.
+ *
+ * Argument a0: (input) SMCC ID.
+ * (output) Status return code.
+ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx).
+ * Argument a2: (input) Register offset or physical address.
+ * (output) Register read value, if applicable.
+ * Argument a3: (input) Register target value if applicable.
+ */
+#define STM32_SMC_PWR 0x82001001
+
+/*
+ * SMC functions STM32_SMC_BSEC.
+ *
+ * Argument a0: (input) SMCC ID.
+ * (output) Status return code.
+ * Argument a1: (input) Service ID (STM32_SMC_READ_xxx/_PROG_xxx/_WRITE_xxx).
+ * (output) OTP read value, if applicable.
+ * Argument a2: (input) OTP index.
+ * Argument a3: (input) OTP value if applicable.
+ */
#define STM32_SMC_BSEC 0x82001003
-/* Service for BSEC */
+/* Service ID for STM32_SMC_PWR */
+#define STM32_SMC_REG_READ 0x0
+#define STM32_SMC_REG_WRITE 0x1
+#define STM32_SMC_REG_SET 0x2
+#define STM32_SMC_REG_CLEAR 0x3
+
+/* Service ID for STM32_SMC_BSEC */
#define STM32_SMC_READ_SHADOW 0x01
#define STM32_SMC_PROG_OTP 0x02
#define STM32_SMC_WRITE_SHADOW 0x03
@@ -29,12 +63,6 @@
#define STM32_SMC_WRITE_ALL 0x06
#define STM32_SMC_WRLOCK_OTP 0x07
-/* SMC error codes */
-#define STM32_SMC_OK 0x0
-#define STM32_SMC_NOT_SUPPORTED -1
-#define STM32_SMC_FAILED -2
-#define STM32_SMC_INVALID_PARAMS -3
-
#define stm32_smc_exec(svc, op, data1, data2) \
stm32_smc(svc, op, data1, data2, NULL)
diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
index 4149d3a133..02debea546 100644
--- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h
+++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
@@ -3,7 +3,7 @@
* Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved
*/
-/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit7:0) */
+/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0) */
#define CPU_STM32MP157Cxx 0x05000000
#define CPU_STM32MP157Axx 0x05000001
#define CPU_STM32MP153Cxx 0x05000024
@@ -17,28 +17,46 @@
#define CPU_STM32MP151Fxx 0x050000AE
#define CPU_STM32MP151Dxx 0x050000AF
+#define CPU_STM32MP135Cxx 0x05010000
+#define CPU_STM32MP135Axx 0x05010001
+#define CPU_STM32MP133Cxx 0x050100C0
+#define CPU_STM32MP133Axx 0x050100C1
+#define CPU_STM32MP131Cxx 0x050106C8
+#define CPU_STM32MP131Axx 0x050106C9
+#define CPU_STM32MP135Fxx 0x05010800
+#define CPU_STM32MP135Dxx 0x05010801
+#define CPU_STM32MP133Fxx 0x050108C0
+#define CPU_STM32MP133Dxx 0x050108C1
+#define CPU_STM32MP131Fxx 0x05010EC8
+#define CPU_STM32MP131Dxx 0x05010EC9
+
/* return CPU_STMP32MP...Xxx constants */
u32 get_cpu_type(void);
#define CPU_DEV_STM32MP15 0x500
+#define CPU_DEV_STM32MP13 0x501
/* return CPU_DEV constants */
u32 get_cpu_dev(void);
-#define CPU_REVA 0x1000
-#define CPU_REVB 0x2000
-#define CPU_REVZ 0x2001
+#define CPU_REV1 0x1000
+#define CPU_REV1_1 0x1001
+#define CPU_REV1_2 0x1002
+#define CPU_REV2 0x2000
+#define CPU_REV2_1 0x2001
-/* return CPU_REV constants */
+/* return Silicon revision = REV_ID[15:0] of Device Version */
u32 get_cpu_rev(void);
/* Get Package options from OTP */
u32 get_cpu_package(void);
-#define PKG_AA_LBGA448 4
-#define PKG_AB_LBGA354 3
-#define PKG_AC_TFBGA361 2
-#define PKG_AD_TFBGA257 1
+/* package used for STM32MP15x */
+#define STM32MP15_PKG_AA_LBGA448 4
+#define STM32MP15_PKG_AB_LBGA354 3
+#define STM32MP15_PKG_AC_TFBGA361 2
+#define STM32MP15_PKG_AD_TFBGA257 1
+#define STM32MP15_PKG_UNKNOWN 0
/* Get SOC name */
#define SOC_NAME_SIZE 20
@@ -47,7 +65,15 @@ void get_soc_name(char name[SOC_NAME_SIZE]);
/* return boot mode */
u32 get_bootmode(void);
+int get_eth_nb(void);
int setup_mac_address(void);
/* board power management : configure vddcore according OPP */
void board_vddcore_init(u32 voltage_mv);
+
+/* weak function */
+void stm32mp_cpu_init(void);
+void stm32mp_misc_init(void);
+
+/* helper function: read data from OTP */
+u32 get_otp(int index, int shift, int mask);
diff --git a/arch/arm/mach-stm32mp/pwr_regulator.c b/arch/arm/mach-stm32mp/pwr_regulator.c
index 846637ab16..c666f9f409 100644
--- a/arch/arm/mach-stm32mp/pwr_regulator.c
+++ b/arch/arm/mach-stm32mp/pwr_regulator.c
@@ -10,6 +10,7 @@
#include <errno.h>
#include <syscon.h>
#include <asm/io.h>
+#include <asm/arch/stm32mp1_smc.h>
#include <dm/device_compat.h>
#include <dm/device-internal.h>
#include <linux/bitops.h>
@@ -44,6 +45,10 @@ static int stm32mp_pwr_write(struct udevice *dev, uint reg,
if (len != 4)
return -EINVAL;
+ if (IS_ENABLED(CONFIG_ARM_SMCCC) && !IS_ENABLED(CONFIG_SPL_BUILD))
+ return stm32_smc_exec(STM32_SMC_PWR, STM32_SMC_REG_WRITE,
+ STM32MP_PWR_CR3, val);
+
writel(val, priv->base + STM32MP_PWR_CR3);
return 0;
diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c
index 405eff68a3..47d2724a70 100644
--- a/arch/arm/mach-stm32mp/spl.c
+++ b/arch/arm/mach-stm32mp/spl.c
@@ -190,6 +190,7 @@ void board_init_f(ulong dummy)
int ret;
arch_cpu_init();
+ mach_cpu_init();
ret = spl_early_init();
if (ret) {
diff --git a/arch/arm/mach-stm32mp/stm32mp13x.c b/arch/arm/mach-stm32mp/stm32mp13x.c
new file mode 100644
index 0000000000..4ec55e361d
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp13x.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ */
+
+#define LOG_CATEGORY LOGC_ARCH
+
+#include <common.h>
+#include <log.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
+
+/* SYSCFG register */
+#define SYSCFG_IDC_OFFSET 0x380
+#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define SYSCFG_IDC_DEV_ID_SHIFT 0
+#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
+#define SYSCFG_IDC_REV_ID_SHIFT 16
+
+static u32 read_idc(void)
+{
+ void *syscfg = syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+ return readl(syscfg + SYSCFG_IDC_OFFSET);
+}
+
+u32 get_cpu_dev(void)
+{
+ return (read_idc() & SYSCFG_IDC_DEV_ID_MASK) >> SYSCFG_IDC_DEV_ID_SHIFT;
+}
+
+u32 get_cpu_rev(void)
+{
+ return (read_idc() & SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
+}
+
+int get_eth_nb(void)
+{
+ int nb_eth = 2;
+
+ switch (get_cpu_type()) {
+ case CPU_STM32MP131Dxx:
+ fallthrough;
+ case CPU_STM32MP131Cxx:
+ fallthrough;
+ case CPU_STM32MP131Axx:
+ nb_eth = 1;
+ break;
+ default:
+ nb_eth = 2;
+ break;
+ }
+
+ return nb_eth;
+}
+
+void get_soc_name(char name[SOC_NAME_SIZE])
+{
+ char *cpu_s, *cpu_r;
+
+ /* MPUs Part Numbers */
+ switch (get_cpu_type()) {
+ case CPU_STM32MP135Fxx:
+ cpu_s = "135F";
+ break;
+ case CPU_STM32MP135Dxx:
+ cpu_s = "135D";
+ break;
+ case CPU_STM32MP135Cxx:
+ cpu_s = "135C";
+ break;
+ case CPU_STM32MP135Axx:
+ cpu_s = "135A";
+ break;
+ case CPU_STM32MP133Fxx:
+ cpu_s = "133F";
+ break;
+ case CPU_STM32MP133Dxx:
+ cpu_s = "133D";
+ break;
+ case CPU_STM32MP133Cxx:
+ cpu_s = "133C";
+ break;
+ case CPU_STM32MP133Axx:
+ cpu_s = "133A";
+ break;
+ case CPU_STM32MP131Fxx:
+ cpu_s = "131F";
+ break;
+ case CPU_STM32MP131Dxx:
+ cpu_s = "131D";
+ break;
+ case CPU_STM32MP131Cxx:
+ cpu_s = "131C";
+ break;
+ case CPU_STM32MP131Axx:
+ cpu_s = "131A";
+ break;
+ default:
+ cpu_s = "????";
+ break;
+ }
+
+ /* REVISION */
+ switch (get_cpu_rev()) {
+ case CPU_REV1:
+ cpu_r = "A";
+ break;
+ case CPU_REV1_1:
+ cpu_r = "Z";
+ break;
+ case CPU_REV1_2:
+ cpu_r = "Y";
+ break;
+ default:
+ cpu_r = "?";
+ break;
+ }
+
+ snprintf(name, SOC_NAME_SIZE, "STM32MP%s Rev.%s", cpu_s, cpu_r);
+}
diff --git a/arch/arm/mach-stm32mp/stm32mp15x.c b/arch/arm/mach-stm32mp/stm32mp15x.c
new file mode 100644
index 0000000000..0f55cc4753
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp15x.c
@@ -0,0 +1,330 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define LOG_CATEGORY LOGC_ARCH
+
+#include <common.h>
+#include <env.h>
+#include <log.h>
+#include <asm/io.h>
+#include <asm/arch/bsec.h>
+#include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+
+/* RCC register */
+#define RCC_TZCR (STM32_RCC_BASE + 0x00)
+#define RCC_BDCR (STM32_RCC_BASE + 0x0140)
+#define RCC_MP_APB5ENSETR (STM32_RCC_BASE + 0x0208)
+#define RCC_MP_AHB5ENSETR (STM32_RCC_BASE + 0x0210)
+#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C)
+
+#define RCC_BDCR_VSWRST BIT(31)
+#define RCC_BDCR_RTCSRC GENMASK(17, 16)
+
+#define RCC_DBGCFGR_DBGCKEN BIT(8)
+
+/* DBGMCU register */
+#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00)
+#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C)
+#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
+
+/* Security register */
+#define ETZPC_TZMA1_SIZE (STM32_ETZPC_BASE + 0x04)
+#define ETZPC_DECPROT0 (STM32_ETZPC_BASE + 0x10)
+
+#define TZC_GATE_KEEPER (STM32_TZC_BASE + 0x008)
+#define TZC_REGION_ATTRIBUTE0 (STM32_TZC_BASE + 0x110)
+#define TZC_REGION_ID_ACCESS0 (STM32_TZC_BASE + 0x114)
+
+#define TAMP_CR1 (STM32_TAMP_BASE + 0x00)
+
+#define PWR_CR1 (STM32_PWR_BASE + 0x00)
+#define PWR_MCUCR (STM32_PWR_BASE + 0x14)
+#define PWR_CR1_DBP BIT(8)
+#define PWR_MCUCR_SBF BIT(6)
+
+/* GPIOZ registers */
+#define GPIOZ_SECCFGR 0x54004030
+
+/* DBGMCU register */
+#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00)
+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define DBGMCU_IDC_DEV_ID_SHIFT 0
+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
+#define DBGMCU_IDC_REV_ID_SHIFT 16
+
+/* boot interface from Bootrom
+ * - boot instance = bit 31:16
+ * - boot device = bit 15:0
+ */
+#define BOOTROM_PARAM_ADDR 0x2FFC0078
+#define BOOTROM_MODE_MASK GENMASK(15, 0)
+#define BOOTROM_MODE_SHIFT 0
+#define BOOTROM_INSTANCE_MASK GENMASK(31, 16)
+#define BOOTROM_INSTANCE_SHIFT 16
+
+/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
+#define RPN_SHIFT 0
+#define RPN_MASK GENMASK(7, 0)
+
+/* Package = bit 27:29 of OTP16 => STM32MP15_PKG defines
+ * - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
+ * - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
+ * - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
+ * - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
+ * - others: Reserved
+ */
+#define PKG_SHIFT 27
+#define PKG_MASK GENMASK(2, 0)
+
+static void security_init(void)
+{
+ /* Disable the backup domain write protection */
+ /* the protection is enable at each reset by hardware */
+ /* And must be disable by software */
+ setbits_le32(PWR_CR1, PWR_CR1_DBP);
+
+ while (!(readl(PWR_CR1) & PWR_CR1_DBP))
+ ;
+
+ /* If RTC clock isn't enable so this is a cold boot then we need
+ * to reset the backup domain
+ */
+ if (!(readl(RCC_BDCR) & RCC_BDCR_RTCSRC)) {
+ setbits_le32(RCC_BDCR, RCC_BDCR_VSWRST);
+ while (!(readl(RCC_BDCR) & RCC_BDCR_VSWRST))
+ ;
+ clrbits_le32(RCC_BDCR, RCC_BDCR_VSWRST);
+ }
+
+ /* allow non secure access in Write/Read for all peripheral */
+ writel(GENMASK(25, 0), ETZPC_DECPROT0);
+
+ /* Open SYSRAM for no secure access */
+ writel(0x0, ETZPC_TZMA1_SIZE);
+
+ /* enable TZC1 TZC2 clock */
+ writel(BIT(11) | BIT(12), RCC_MP_APB5ENSETR);
+
+ /* Region 0 set to no access by default */
+ /* bit 0 / 16 => nsaid0 read/write Enable
+ * bit 1 / 17 => nsaid1 read/write Enable
+ * ...
+ * bit 15 / 31 => nsaid15 read/write Enable
+ */
+ writel(0xFFFFFFFF, TZC_REGION_ID_ACCESS0);
+ /* bit 30 / 31 => Secure Global Enable : write/read */
+ /* bit 0 / 1 => Region Enable for filter 0/1 */
+ writel(BIT(0) | BIT(1) | BIT(30) | BIT(31), TZC_REGION_ATTRIBUTE0);
+
+ /* Enable Filter 0 and 1 */
+ setbits_le32(TZC_GATE_KEEPER, BIT(0) | BIT(1));
+
+ /* RCC trust zone deactivated */
+ writel(0x0, RCC_TZCR);
+
+ /* TAMP: deactivate the internal tamper
+ * Bit 23 ITAMP8E: monotonic counter overflow
+ * Bit 20 ITAMP5E: RTC calendar overflow
+ * Bit 19 ITAMP4E: HSE monitoring
+ * Bit 18 ITAMP3E: LSE monitoring
+ * Bit 16 ITAMP1E: RTC power domain supply monitoring
+ */
+ writel(0x0, TAMP_CR1);
+
+ /* GPIOZ: deactivate the security */
+ writel(BIT(0), RCC_MP_AHB5ENSETR);
+ writel(0x0, GPIOZ_SECCFGR);
+}
+
+/*
+ * Debug init
+ */
+void dbgmcu_init(void)
+{
+ /*
+ * Freeze IWDG2 if Cortex-A7 is in debug mode
+ * done in TF-A for TRUSTED boot and
+ * DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE
+ */
+ if (bsec_dbgswenable()) {
+ setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+ setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2);
+ }
+}
+
+void spl_board_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ dbgmcu_init();
+
+ /* force probe of BSEC driver to shadow the upper OTP */
+ ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(stm32mp_bsec), &dev);
+ if (ret)
+ log_warning("BSEC probe failed: %d\n", ret);
+}
+
+/* get bootmode from ROM code boot context: saved in TAMP register */
+static void update_bootmode(void)
+{
+ u32 boot_mode;
+ u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR);
+ u32 bootrom_device, bootrom_instance;
+
+ /* enable TAMP clock = RTCAPBEN */
+ writel(BIT(8), RCC_MP_APB5ENSETR);
+
+ /* read bootrom context */
+ bootrom_device =
+ (bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT;
+ bootrom_instance =
+ (bootrom_itf & BOOTROM_INSTANCE_MASK) >> BOOTROM_INSTANCE_SHIFT;
+ boot_mode =
+ ((bootrom_device << BOOT_TYPE_SHIFT) & BOOT_TYPE_MASK) |
+ ((bootrom_instance << BOOT_INSTANCE_SHIFT) &
+ BOOT_INSTANCE_MASK);
+
+ /* save the boot mode in TAMP backup register */
+ clrsetbits_le32(TAMP_BOOT_CONTEXT,
+ TAMP_BOOT_MODE_MASK,
+ boot_mode << TAMP_BOOT_MODE_SHIFT);
+}
+
+/* weak function: STM32MP15x mach init for boot without TFA */
+void stm32mp_cpu_init(void)
+{
+ if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+ security_init();
+ update_bootmode();
+ }
+
+ /* reset copro state in SPL, when used, or in U-Boot */
+ if (!IS_ENABLED(CONFIG_SPL) || IS_ENABLED(CONFIG_SPL_BUILD)) {
+ /* Reset Coprocessor state unless it wakes up from Standby power mode */
+ if (!(readl(PWR_MCUCR) & PWR_MCUCR_SBF)) {
+ writel(TAMP_COPRO_STATE_OFF, TAMP_COPRO_STATE);
+ writel(0, TAMP_COPRO_RSC_TBL_ADDRESS);
+ }
+ }
+}
+
+static u32 read_idc(void)
+{
+ /* DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE */
+ if (bsec_dbgswenable()) {
+ setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+
+ return readl(DBGMCU_IDC);
+ }
+
+ return CPU_DEV_STM32MP15; /* STM32MP15x and unknown revision */
+}
+
+u32 get_cpu_dev(void)
+{
+ return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
+}
+
+u32 get_cpu_rev(void)
+{
+ return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
+}
+
+int get_eth_nb(void)
+{
+ return 1;
+}
+
+/* Get Package options from OTP */
+u32 get_cpu_package(void)
+{
+ return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
+}
+
+static const char * const soc_type[] = {
+ "????",
+ "151C", "151A", "151F", "151D",
+ "153C", "153A", "153F", "153D",
+ "157C", "157A", "157F", "157D"
+};
+
+static const char * const soc_pkg[] = { "??", "AD", "AC", "AB", "AA" };
+static const char * const soc_rev[] = { "?", "A", "B", "Z" };
+
+static void get_cpu_string_offsets(unsigned int *type, unsigned int *pkg,
+ unsigned int *rev)
+{
+ u32 cpu_type = get_cpu_type();
+ u32 ct = cpu_type & ~(BIT(7) | BIT(0));
+ u32 cm = ((cpu_type & BIT(7)) >> 6) | (cpu_type & BIT(0));
+
+ /* Bits 0 and 7 are the ACDF, 00:C 01:A 10:F 11:D */
+ switch (ct) {
+ case CPU_STM32MP151Cxx:
+ *type = cm + 1;
+ break;
+ case CPU_STM32MP153Cxx:
+ *type = cm + 5;
+ break;
+ case CPU_STM32MP157Cxx:
+ *type = cm + 9;
+ break;
+ default:
+ *type = 0;
+ break;
+ }
+
+ /* Package */
+ *pkg = get_cpu_package();
+ if (*pkg > STM32MP15_PKG_AA_LBGA448)
+ *pkg = STM32MP15_PKG_UNKNOWN;
+
+ /* Revision */
+ switch (get_cpu_rev()) {
+ case CPU_REV1:
+ *rev = 1;
+ break;
+ case CPU_REV2:
+ *rev = 2;
+ break;
+ case CPU_REV2_1:
+ *rev = 3;
+ break;
+ default:
+ *rev = 0;
+ break;
+ }
+}
+
+void get_soc_name(char name[SOC_NAME_SIZE])
+{
+ unsigned int type, pkg, rev;
+
+ get_cpu_string_offsets(&type, &pkg, &rev);
+
+ snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s",
+ soc_type[type], soc_pkg[pkg], soc_rev[rev]);
+}
+
+static void setup_soc_type_pkg_rev(void)
+{
+ unsigned int type, pkg, rev;
+
+ get_cpu_string_offsets(&type, &pkg, &rev);
+
+ env_set("soc_type", soc_type[type]);
+ env_set("soc_pkg", soc_pkg[pkg]);
+ env_set("soc_rev", soc_rev[rev]);
+}
+
+/* weak function called in arch_misc_init */
+void stm32mp_misc_init(void)
+{
+ setup_soc_type_pkg_rev();
+}
--
2.25.1