4093 lines
112 KiB
Diff
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
|
|
|