summaryrefslogtreecommitdiff
path: root/arch/arm/mach-stm32mp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-stm32mp')
-rw-r--r--arch/arm/mach-stm32mp/Kconfig28
-rw-r--r--arch/arm/mach-stm32mp/Makefile2
-rw-r--r--arch/arm/mach-stm32mp/bsec.c14
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32key.c101
-rw-r--r--arch/arm/mach-stm32mp/cpu.c9
-rw-r--r--arch/arm/mach-stm32mp/fdt.c223
-rw-r--r--arch/arm/mach-stm32mp/include/mach/stm32.h3
-rw-r--r--arch/arm/mach-stm32mp/include/mach/sys_proto.h9
-rw-r--r--arch/arm/mach-stm32mp/syscon.c2
9 files changed, 373 insertions, 18 deletions
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index d9ad6b423b..9dc3c4d1c5 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -38,6 +38,7 @@ config TARGET_STM32MP1
select CPU_V7A
select CPU_V7_HAS_NONSEC if !STM32MP1_TRUSTED
select CPU_V7_HAS_VIRT
+ select OF_BOARD_SETUP
select PINCTRL_STM32
select STM32_RCC
select STM32_RESET
@@ -62,7 +63,17 @@ config STM32MP1_TRUSTED
Say Y here to enable boot with TF-A
Trusted boot chain is :
BootRom => TF-A.stm32 (clock & DDR) => U-Boot.stm32
- TF-A monitor provides proprietary smc to manage secure devices
+ TF-A monitor provides proprietary SMC to manage secure devices
+
+config STM32MP1_OPTEE
+ bool "Support trusted boot with TF-A and OP-TEE"
+ depends on STM32MP1_TRUSTED
+ default n
+ help
+ Say Y here to enable boot with TF-A and OP-TEE
+ Trusted boot chain is :
+ BootRom => TF-A.stm32 (clock & DDR) => OP-TEE => U-Boot.stm32
+ OP-TEE monitor provides ST SMC to access to secure resources
config SYS_TEXT_BASE
prompt "U-Boot base address"
@@ -83,6 +94,21 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
Partition on the second MMC to load U-Boot from when the MMC is being
used in raw mode
+config STM32_ETZPC
+ bool "STM32 Extended TrustZone Protection"
+ depends on TARGET_STM32MP1
+ default y
+ help
+ Say y to enable STM32 Extended TrustZone Protection
+
+config CMD_STM32KEY
+ bool "command stm32key to fuse public key hash"
+ default y
+ depends on CMD_FUSE
+ help
+ fuse public key hash in corresponding fuse used to authenticate
+ binary.
+
config BOOTSTAGE_STASH_ADDR
default 0xC3000000
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index 1493914a11..77450604b0 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -11,9 +11,11 @@ ifdef CONFIG_SPL_BUILD
obj-y += spl.o
else
obj-y += bsec.o
+obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o
ifndef CONFIG_STM32MP1_TRUSTED
obj-$(CONFIG_SYSRESET) += cmd_poweroff.o
endif
endif
obj-$(CONFIG_ARMV7_PSCI) += psci.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += 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 0166649685..8018366885 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -358,12 +358,13 @@ static int stm32mp_bsec_read(struct udevice *dev, int offset,
bool shadow = true;
int nb_otp = size / sizeof(u32);
int otp;
+ unsigned int offs = offset;
- if (offset >= STM32_BSEC_OTP_OFFSET) {
- offset -= STM32_BSEC_OTP_OFFSET;
+ if (offs >= STM32_BSEC_OTP_OFFSET) {
+ offs -= STM32_BSEC_OTP_OFFSET;
shadow = false;
}
- otp = offset / sizeof(u32);
+ otp = offs / sizeof(u32);
if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) {
dev_err(dev, "wrong value for otp, max value : %i\n",
@@ -393,12 +394,13 @@ static int stm32mp_bsec_write(struct udevice *dev, int offset,
bool shadow = true;
int nb_otp = size / sizeof(u32);
int otp;
+ unsigned int offs = offset;
- if (offset >= STM32_BSEC_OTP_OFFSET) {
- offset -= STM32_BSEC_OTP_OFFSET;
+ if (offs >= STM32_BSEC_OTP_OFFSET) {
+ offs -= STM32_BSEC_OTP_OFFSET;
shadow = false;
}
- otp = offset / sizeof(u32);
+ otp = offs / sizeof(u32);
if (otp < 0 || (otp + nb_otp - 1) > BSEC_OTP_MAX_VALUE) {
dev_err(dev, "wrong value for otp, max value : %d\n",
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c
new file mode 100644
index 0000000000..f1f26e7c94
--- /dev/null
+++ b/arch/arm/mach-stm32mp/cmd_stm32key.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <misc.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+
+#define STM32_OTP_HASH_KEY_START 24
+#define STM32_OTP_HASH_KEY_SIZE 8
+
+static void read_hash_value(u32 addr)
+{
+ int i;
+
+ 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));
+ addr += 4;
+ }
+}
+
+static void fuse_hash_value(u32 addr, bool print)
+{
+ struct udevice *dev;
+ u32 word, val;
+ int i, ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_GET_DRIVER(stm32mp_bsec),
+ &dev);
+ if (ret) {
+ pr_err("Can't find stm32mp_bsec driver\n");
+ return;
+ }
+
+ for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
+ if (print)
+ printf("Fuse OTP %i : %x\n",
+ STM32_OTP_HASH_KEY_START + i,
+ __be32_to_cpu(*(u32 *)addr));
+
+ word = STM32_OTP_HASH_KEY_START + i;
+ val = __be32_to_cpu(*(u32 *)addr);
+ misc_write(dev, STM32_BSEC_OTP(word), &val, 4);
+
+ addr += 4;
+ }
+}
+
+static int confirm_prog(void)
+{
+ puts("Warning: Programming fuses is an irreversible operation!\n"
+ " This may brick your system.\n"
+ " Use this command only if you are sure of what you are doing!\n"
+ "\nReally perform this fuse programming? <y/N>\n");
+
+ if (confirm_yesno())
+ return 1;
+
+ puts("Fuse programming aborted\n");
+ return 0;
+}
+
+static int do_stm32key(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ u32 addr;
+ const char *op = argc >= 2 ? argv[1] : NULL;
+ int confirmed = argc > 3 && !strcmp(argv[2], "-y");
+
+ argc -= 2 + confirmed;
+ argv += 2 + confirmed;
+
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ addr = simple_strtoul(argv[0], NULL, 16);
+ if (!addr)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(op, "read"))
+ read_hash_value(addr);
+
+ if (!strcmp(op, "fuse")) {
+ if (!confirmed && !confirm_prog())
+ return CMD_RET_FAILURE;
+ fuse_hash_value(addr, !confirmed);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(stm32key, 4, 1, do_stm32key,
+ "Fuse ST Hash key",
+ "read <addr>: Read the hash store at addr in memory\n"
+ "stm32key fuse [-y] <addr> : Fuse hash store at addr in otp\n");
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index e1a0a13680..10190f40d4 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -78,11 +78,6 @@
#define PKG_SHIFT 27
#define PKG_MASK GENMASK(2, 0)
-#define PKG_AA_LBGA448 4
-#define PKG_AB_LBGA354 3
-#define PKG_AC_TFBGA361 2
-#define PKG_AD_TFBGA257 1
-
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
#ifndef CONFIG_STM32MP1_TRUSTED
static void security_init(void)
@@ -277,7 +272,7 @@ u32 get_cpu_type(void)
}
/* Get Package options from OTP */
-static u32 get_cpu_package(void)
+u32 get_cpu_package(void)
{
return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
}
@@ -366,7 +361,7 @@ static void setup_boot_mode(void)
u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
u32 boot_mode =
(boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
- int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
+ unsigned int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK);
struct udevice *dev;
int alias;
diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c
new file mode 100644
index 0000000000..82c430b7c7
--- /dev/null
+++ b/arch/arm/mach-stm32mp/fdt.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <fdt_support.h>
+#include <asm/arch/sys_proto.h>
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+#include <linux/io.h>
+
+#define ETZPC_DECPROT(n) (STM32_ETZPC_BASE + 0x10 + 4 * (n))
+#define ETZPC_DECPROT_NB 6
+
+#define DECPROT_MASK 0x03
+#define NB_PROT_PER_REG 0x10
+#define DECPROT_NB_BITS 2
+
+#define DECPROT_SECURED 0x00
+#define DECPROT_WRITE_SECURE 0x01
+#define DECPROT_MCU_ISOLATION 0x02
+#define DECPROT_NON_SECURED 0x03
+
+#define ETZPC_RESERVED 0xffffffff
+
+static const u32 stm32mp1_ip_addr[] = {
+ 0x5c008000, /* 00 stgenc */
+ 0x54000000, /* 01 bkpsram */
+ 0x5c003000, /* 02 iwdg1 */
+ 0x5c000000, /* 03 usart1 */
+ 0x5c001000, /* 04 spi6 */
+ 0x5c002000, /* 05 i2c4 */
+ ETZPC_RESERVED, /* 06 reserved */
+ 0x54003000, /* 07 rng1 */
+ 0x54002000, /* 08 hash1 */
+ 0x54001000, /* 09 cryp1 */
+ 0x5a003000, /* 0A ddrctrl */
+ 0x5a004000, /* 0B ddrphyc */
+ 0x5c009000, /* 0C i2c6 */
+ ETZPC_RESERVED, /* 0D reserved */
+ ETZPC_RESERVED, /* 0E reserved */
+ ETZPC_RESERVED, /* 0F reserved */
+ 0x40000000, /* 10 tim2 */
+ 0x40001000, /* 11 tim3 */
+ 0x40002000, /* 12 tim4 */
+ 0x40003000, /* 13 tim5 */
+ 0x40004000, /* 14 tim6 */
+ 0x40005000, /* 15 tim7 */
+ 0x40006000, /* 16 tim12 */
+ 0x40007000, /* 17 tim13 */
+ 0x40008000, /* 18 tim14 */
+ 0x40009000, /* 19 lptim1 */
+ 0x4000a000, /* 1A wwdg1 */
+ 0x4000b000, /* 1B spi2 */
+ 0x4000c000, /* 1C spi3 */
+ 0x4000d000, /* 1D spdifrx */
+ 0x4000e000, /* 1E usart2 */
+ 0x4000f000, /* 1F usart3 */
+ 0x40010000, /* 20 uart4 */
+ 0x40011000, /* 21 uart5 */
+ 0x40012000, /* 22 i2c1 */
+ 0x40013000, /* 23 i2c2 */
+ 0x40014000, /* 24 i2c3 */
+ 0x40015000, /* 25 i2c5 */
+ 0x40016000, /* 26 cec */
+ 0x40017000, /* 27 dac */
+ 0x40018000, /* 28 uart7 */
+ 0x40019000, /* 29 uart8 */
+ ETZPC_RESERVED, /* 2A reserved */
+ ETZPC_RESERVED, /* 2B reserved */
+ 0x4001c000, /* 2C mdios */
+ ETZPC_RESERVED, /* 2D reserved */
+ ETZPC_RESERVED, /* 2E reserved */
+ ETZPC_RESERVED, /* 2F reserved */
+ 0x44000000, /* 30 tim1 */
+ 0x44001000, /* 31 tim8 */
+ ETZPC_RESERVED, /* 32 reserved */
+ 0x44003000, /* 33 usart6 */
+ 0x44004000, /* 34 spi1 */
+ 0x44005000, /* 35 spi4 */
+ 0x44006000, /* 36 tim15 */
+ 0x44007000, /* 37 tim16 */
+ 0x44008000, /* 38 tim17 */
+ 0x44009000, /* 39 spi5 */
+ 0x4400a000, /* 3A sai1 */
+ 0x4400b000, /* 3B sai2 */
+ 0x4400c000, /* 3C sai3 */
+ 0x4400d000, /* 3D dfsdm */
+ 0x4400e000, /* 3E tt_fdcan */
+ ETZPC_RESERVED, /* 3F reserved */
+ 0x50021000, /* 40 lptim2 */
+ 0x50022000, /* 41 lptim3 */
+ 0x50023000, /* 42 lptim4 */
+ 0x50024000, /* 43 lptim5 */
+ 0x50027000, /* 44 sai4 */
+ 0x50025000, /* 45 vrefbuf */
+ 0x4c006000, /* 46 dcmi */
+ 0x4c004000, /* 47 crc2 */
+ 0x48003000, /* 48 adc */
+ 0x4c002000, /* 49 hash2 */
+ 0x4c003000, /* 4A rng2 */
+ 0x4c005000, /* 4B cryp2 */
+ ETZPC_RESERVED, /* 4C reserved */
+ ETZPC_RESERVED, /* 4D reserved */
+ ETZPC_RESERVED, /* 4E reserved */
+ ETZPC_RESERVED, /* 4F reserved */
+ ETZPC_RESERVED, /* 50 sram1 */
+ ETZPC_RESERVED, /* 51 sram2 */
+ ETZPC_RESERVED, /* 52 sram3 */
+ ETZPC_RESERVED, /* 53 sram4 */
+ ETZPC_RESERVED, /* 54 retram */
+ 0x49000000, /* 55 otg */
+ 0x48004000, /* 56 sdmmc3 */
+ 0x48005000, /* 57 dlybsd3 */
+ 0x48000000, /* 58 dma1 */
+ 0x48001000, /* 59 dma2 */
+ 0x48002000, /* 5A dmamux */
+ 0x58002000, /* 5B fmc */
+ 0x58003000, /* 5C qspi */
+ 0x58004000, /* 5D dlybq */
+ 0x5800a000, /* 5E eth */
+ ETZPC_RESERVED, /* 5F reserved */
+};
+
+/* fdt helper */
+static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr)
+{
+ int node;
+
+ for (node = fdt_first_subnode(fdt, offset);
+ node >= 0;
+ node = fdt_next_subnode(fdt, node)) {
+ if (addr == (u32)fdt_getprop(fdt, node, "reg", 0)) {
+ if (fdtdec_get_is_enabled(fdt, node)) {
+ fdt_status_disabled(fdt, node);
+
+ return true;
+ }
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static int stm32_fdt_fixup_etzpc(void *fdt)
+{
+ const u32 *array;
+ int array_size, i;
+ int soc_node, offset, shift;
+ u32 addr, status, decprot[ETZPC_DECPROT_NB];
+
+ array = stm32mp1_ip_addr;
+ array_size = ARRAY_SIZE(stm32mp1_ip_addr);
+
+ for (i = 0; i < ETZPC_DECPROT_NB; i++)
+ decprot[i] = readl(ETZPC_DECPROT(i));
+
+ soc_node = fdt_path_offset(fdt, "/soc");
+ if (soc_node < 0)
+ return soc_node;
+
+ for (i = 0; i < array_size; i++) {
+ offset = i / NB_PROT_PER_REG;
+ shift = (i % NB_PROT_PER_REG) * DECPROT_NB_BITS;
+ status = (decprot[offset] >> shift) & DECPROT_MASK;
+ addr = array[i];
+
+ debug("ETZPC: 0x%08x decprot %d=%d\n", addr, i, status);
+
+ if (addr == ETZPC_RESERVED ||
+ status == DECPROT_NON_SECURED)
+ continue;
+
+ if (fdt_disable_subnode_by_address(fdt, soc_node, addr))
+ printf("ETZPC: 0x%08x node disabled, decprot %d=%d\n",
+ addr, i, status);
+ }
+
+ return 0;
+}
+
+/*
+ * 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, bd_t *bd)
+{
+ int ret = 0;
+ u32 pkg;
+
+ if (CONFIG_IS_ENABLED(STM32_ETZPC)) {
+ ret = stm32_fdt_fixup_etzpc(blob);
+ if (ret)
+ return ret;
+ }
+
+ switch (get_cpu_package()) {
+ case PKG_AA_LBGA448:
+ pkg = STM32MP_PKG_AA;
+ break;
+ case PKG_AB_LBGA354:
+ pkg = STM32MP_PKG_AB;
+ break;
+ case PKG_AC_TFBGA361:
+ pkg = STM32MP_PKG_AC;
+ break;
+ case PKG_AD_TFBGA257:
+ pkg = STM32MP_PKG_AD;
+ break;
+ default:
+ pkg = 0;
+ break;
+ }
+ if (pkg) {
+ do_fixup_by_compat_u32(blob, "st,stm32mp157-pinctrl",
+ "st,package", pkg, false);
+ do_fixup_by_compat_u32(blob, "st,stm32mp157-z-pinctrl",
+ "st,package", pkg, false);
+ }
+
+ return ret;
+}
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index 6795352044..1d4b5482ac 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -15,6 +15,7 @@
#define STM32_DBGMCU_BASE 0x50081000
#define STM32_TZC_BASE 0x5C006000
#define STM32_ETZPC_BASE 0x5C007000
+#define STM32_STGEN_BASE 0x5C008000
#define STM32_TAMP_BASE 0x5C00A000
#define STM32_USART1_BASE 0x5C000000
@@ -36,9 +37,7 @@
/* enumerated used to identify the SYSCON driver instance */
enum {
STM32MP_SYSCON_UNKNOWN,
- STM32MP_SYSCON_ETZPC,
STM32MP_SYSCON_PWR,
- STM32MP_SYSCON_STGEN,
STM32MP_SYSCON_SYSCFG,
};
diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
index 71a3ba794d..99eefabf6e 100644
--- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h
+++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
@@ -19,5 +19,14 @@ u32 get_cpu_type(void);
/* return CPU_REV constants */
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
+
/* return boot mode */
u32 get_bootmode(void);
diff --git a/arch/arm/mach-stm32mp/syscon.c b/arch/arm/mach-stm32mp/syscon.c
index 242f8340ab..6070837bf0 100644
--- a/arch/arm/mach-stm32mp/syscon.c
+++ b/arch/arm/mach-stm32mp/syscon.c
@@ -9,9 +9,7 @@
#include <asm/arch/stm32.h>
static const struct udevice_id stm32mp_syscon_ids[] = {
- { .compatible = "st,stm32mp1-etzpc", .data = STM32MP_SYSCON_ETZPC },
{ .compatible = "st,stm32mp1-pwr", .data = STM32MP_SYSCON_PWR },
- { .compatible = "st,stm32-stgen", .data = STM32MP_SYSCON_STGEN },
{ .compatible = "st,stm32mp157-syscfg",
.data = STM32MP_SYSCON_SYSCFG },
{ }