diff options
Diffstat (limited to 'arch/arm/mach-stm32mp')
-rw-r--r-- | arch/arm/mach-stm32mp/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32key.c | 286 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/etzpc.h | 32 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/rif.h | 26 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/stm32.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/sys_proto.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp1/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp1/etzpc.c | 194 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp1/fdt.c | 258 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/cpu.c | 170 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/rifsc.c | 364 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c | 31 |
15 files changed, 1093 insertions, 331 deletions
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 002da2e3d3b..58250901101 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -52,6 +52,7 @@ config STM32MP13X select STM32_SERIAL select SYS_ARCH_TIMER imply CMD_NVEDIT_INFO + imply OF_UPSTREAM help support of STMicroelectronics SOC STM32MP13x family STMicroelectronics MPU with core ARMv7 @@ -73,6 +74,7 @@ config STM32MP15X select SUPPORT_SPL select SYS_ARCH_TIMER imply CMD_NVEDIT_INFO + imply OF_UPSTREAM help support of STMicroelectronics SOC STM32MP15x family STM32MP157, STM32MP153 or STM32MP151 @@ -94,6 +96,7 @@ config STM32MP25X imply CMD_NVEDIT_INFO imply DM_REGULATOR imply DM_REGULATOR_SCMI + imply OF_UPSTREAM imply OPTEE imply RESET_SCMI imply SYSRESET_PSCI @@ -127,14 +130,6 @@ 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 STM32MP15X || STM32MP13X - default y - imply BOOTP_SERVERIP - help - Say y to enable STM32 Extended TrustZone Protection - config STM32_ECDSA_VERIFY bool "STM32 ECDSA verification via the ROM API" depends on SPL_ECDSA_VERIFY diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 040a70f581c..6bfa67859e1 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -14,12 +14,23 @@ /* * Closed device: OTP0 - * STM32MP15x: bit 6 of OPT0 + * STM32MP15x: bit 6 of OTP0 * STM32MP13x: 0b111111 = 0x3F for OTP_SECURED closed device + * STM32MP25x: bit 0 of OTP18 */ -#define STM32_OTP_CLOSE_ID 0 -#define STM32_OTP_STM32MP13X_CLOSE_MASK 0x3F -#define STM32_OTP_STM32MP15X_CLOSE_MASK BIT(6) +#define STM32MP1_OTP_CLOSE_ID 0 +#define STM32_OTP_STM32MP13X_CLOSE_MASK GENMASK(5, 0) +#define STM32_OTP_STM32MP15X_CLOSE_MASK BIT(6) +#define STM32MP25_OTP_WORD8 8 +#define STM32_OTP_STM32MP25X_BOOTROM_CLOSE_MASK GENMASK(7, 0) +#define STM32MP25_OTP_CLOSE_ID 18 +#define STM32_OTP_STM32MP25X_CLOSE_MASK GENMASK(3, 0) +#define STM32_OTP_STM32MP25X_PROVISIONING_DONE_MASK GENMASK(7, 4) +#define STM32MP25_OTP_HWCONFIG 124 +#define STM32_OTP_STM32MP25X_DISABLE_SCAN_MASK BIT(20) + +#define STM32MP25_OTP_BOOTROM_CONF8 17 +#define STM32_OTP_STM32MP25X_OEM_KEY2_EN BIT(8) /* PKH is the first element of the key list */ #define STM32KEY_PKH 0 @@ -27,8 +38,9 @@ struct stm32key { char *name; char *desc; - u8 start; + u16 start; u8 size; + int (*post_process)(struct udevice *dev); }; const struct stm32key stm32mp13_list[] = { @@ -55,6 +67,99 @@ const struct stm32key stm32mp15_list[] = { } }; +static int post_process_oem_key2(struct udevice *dev); + +const struct stm32key stm32mp25_list[] = { + [STM32KEY_PKH] = { + .name = "OEM-KEY1", + .desc = "Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm) for FSBLA or M", + .start = 144, + .size = 8, + }, + { + .name = "OEM-KEY2", + .desc = "Hash of the 8 ECC Public Keys Hashes Table (ECDSA is the authentication algorithm) for FSBLM", + .start = 152, + .size = 8, + .post_process = post_process_oem_key2, + }, + { + .name = "FIP-EDMK", + .desc = "Encryption/Decryption Master Key for FIP", + .start = 260, + .size = 8, + }, + { + .name = "EDMK1", + .desc = "Encryption/Decryption Master Key for FSBLA or M", + .start = 364, + .size = 4, + }, + { + .name = "EDMK2", + .desc = "Encryption/Decryption Master Key for FSBLM", + .start = 360, + .size = 4, + } +}; + +struct otp_close { + u32 word; + u32 mask_wr; + u32 mask_rd; + bool (*close_status_ops)(u32 value, u32 mask); +}; + +static bool compare_mask_exact(u32 value, u32 mask) +{ + return ((value & mask) == mask); +} + +static bool compare_any_bits(u32 value, u32 mask) +{ + return ((value & mask) != 0); +} + +const struct otp_close stm32mp13_close_state_otp[] = { + { + .word = STM32MP1_OTP_CLOSE_ID, + .mask_wr = STM32_OTP_STM32MP13X_CLOSE_MASK, + .mask_rd = STM32_OTP_STM32MP13X_CLOSE_MASK, + .close_status_ops = compare_mask_exact, + } +}; + +const struct otp_close stm32mp15_close_state_otp[] = { + { + .word = STM32MP1_OTP_CLOSE_ID, + .mask_wr = STM32_OTP_STM32MP15X_CLOSE_MASK, + .mask_rd = STM32_OTP_STM32MP15X_CLOSE_MASK, + .close_status_ops = compare_mask_exact, + } +}; + +const struct otp_close stm32mp25_close_state_otp[] = { + { + .word = STM32MP25_OTP_WORD8, + .mask_wr = STM32_OTP_STM32MP25X_BOOTROM_CLOSE_MASK, + .mask_rd = 0, + .close_status_ops = NULL + }, + { + .word = STM32MP25_OTP_CLOSE_ID, + .mask_wr = STM32_OTP_STM32MP25X_CLOSE_MASK | + STM32_OTP_STM32MP25X_PROVISIONING_DONE_MASK, + .mask_rd = STM32_OTP_STM32MP25X_CLOSE_MASK, + .close_status_ops = compare_any_bits + }, + { + .word = STM32MP25_OTP_HWCONFIG, + .mask_wr = STM32_OTP_STM32MP25X_DISABLE_SCAN_MASK, + .mask_rd = 0, + .close_status_ops = NULL + }, +}; + /* index of current selected key in stm32key list, 0 = PKH by default */ static u8 stm32key_index; @@ -65,6 +170,9 @@ static u8 get_key_nb(void) if (IS_ENABLED(CONFIG_STM32MP15X)) return ARRAY_SIZE(stm32mp15_list); + + if (IS_ENABLED(CONFIG_STM32MP25X)) + return ARRAY_SIZE(stm32mp25_list); } static const struct stm32key *get_key(u8 index) @@ -74,15 +182,33 @@ static const struct stm32key *get_key(u8 index) if (IS_ENABLED(CONFIG_STM32MP15X)) return &stm32mp15_list[index]; + + if (IS_ENABLED(CONFIG_STM32MP25X)) + return &stm32mp25_list[index]; } -static u32 get_otp_close_mask(void) +static u8 get_otp_close_state_nb(void) { if (IS_ENABLED(CONFIG_STM32MP13X)) - return STM32_OTP_STM32MP13X_CLOSE_MASK; + return ARRAY_SIZE(stm32mp13_close_state_otp); if (IS_ENABLED(CONFIG_STM32MP15X)) - return STM32_OTP_STM32MP15X_CLOSE_MASK; + return ARRAY_SIZE(stm32mp15_close_state_otp); + + if (IS_ENABLED(CONFIG_STM32MP25X)) + return ARRAY_SIZE(stm32mp25_close_state_otp); +} + +static const struct otp_close *get_otp_close_state(u8 index) +{ + if (IS_ENABLED(CONFIG_STM32MP13X)) + return &stm32mp13_close_state_otp[index]; + + if (IS_ENABLED(CONFIG_STM32MP15X)) + return &stm32mp15_close_state_otp[index]; + + if (IS_ENABLED(CONFIG_STM32MP25X)) + return &stm32mp25_close_state_otp[index]; } static int get_misc_dev(struct udevice **dev) @@ -96,13 +222,13 @@ static int get_misc_dev(struct udevice **dev) return ret; } -static void read_key_value(const struct stm32key *key, u32 addr) +static void read_key_value(const struct stm32key *key, unsigned long addr) { int i; 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)); + (u32)addr, __be32_to_cpu(*(u32 *)addr)); addr += 4; } } @@ -157,26 +283,42 @@ static int read_key_otp(struct udevice *dev, const struct stm32key *key, bool pr static int read_close_status(struct udevice *dev, bool print, bool *closed) { - int word, ret, result; - u32 val, lock, mask; - bool status; + int ret, result, i; + const struct otp_close *otp_close = NULL; + u32 otp_close_nb = get_otp_close_state_nb(); + u32 val, lock, mask, word = 0; + bool status = true; + bool tested_once = false; 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; + for (i = 0; status && (i < otp_close_nb); i++) { + otp_close = get_otp_close_state(i); + + if (!otp_close->close_status_ops) + continue; + + mask = otp_close->mask_rd; + word = otp_close->word; + + 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; + + status = otp_close->close_status_ops(val, mask); + tested_once = true; + } + + if (!tested_once) + status = false; + if (closed) *closed = status; if (print) @@ -185,7 +327,49 @@ static int read_close_status(struct udevice *dev, bool print, bool *closed) return result; } -static int fuse_key_value(struct udevice *dev, const struct stm32key *key, u32 addr, bool print) +static int write_close_status(struct udevice *dev) +{ + int i; + u32 val, word, ret; + const struct otp_close *otp_close = NULL; + u32 otp_num = get_otp_close_state_nb(); + + for (i = 0; i < otp_num; i++) { + otp_close = get_otp_close_state(i); + val = otp_close->mask_wr; + word = otp_close->word; + ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4); + if (ret != 4) { + log_err("Error: can't update OTP %d\n", word); + return ret; + } + } + return 0; +} + +static int post_process_oem_key2(struct udevice *dev) +{ + int ret; + u32 val; + + ret = misc_read(dev, STM32_BSEC_OTP(STM32MP25_OTP_BOOTROM_CONF8), &val, 4); + if (ret != 4) { + log_err("Error %d failed to read STM32MP25_OTP_BOOTROM_CONF8\n", ret); + return -EIO; + } + + val |= STM32_OTP_STM32MP25X_OEM_KEY2_EN; + ret = misc_write(dev, STM32_BSEC_OTP(STM32MP25_OTP_BOOTROM_CONF8), &val, 4); + if (ret != 4) { + log_err("Error %d failed to write OEM_KEY2_ENABLE\n", ret); + return -EIO; + } + + return 0; +} + +static int fuse_key_value(struct udevice *dev, const struct stm32key *key, unsigned long addr, + bool print) { u32 word, val; int i, ret; @@ -229,7 +413,7 @@ static int confirm_prog(void) 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); + printf("\tOTP%d..%d\n", key->start, key->start + key->size - 1); } static int do_stm32key_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -272,7 +456,7 @@ static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *con { const struct stm32key *key; struct udevice *dev; - u32 addr; + unsigned long addr; int ret, i; int result; @@ -310,7 +494,7 @@ static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *con return CMD_RET_USAGE; key = get_key(stm32key_index); - printf("Read %s at 0x%08x\n", key->name, addr); + printf("Read %s at 0x%08x\n", key->name, (u32)addr); read_key_value(key, addr); return CMD_RET_SUCCESS; @@ -320,7 +504,7 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con { const struct stm32key *key = get_key(stm32key_index); struct udevice *dev; - u32 addr; + unsigned long addr; int ret; bool yes = false, lock; @@ -361,6 +545,13 @@ static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *con if (fuse_key_value(dev, key, addr, !yes)) return CMD_RET_FAILURE; + if (key->post_process) { + if (key->post_process(dev)) { + printf("Error: %s for post process\n", key->name); + return CMD_RET_FAILURE; + } + } + printf("%s updated !\n", key->name); return CMD_RET_SUCCESS; @@ -371,7 +562,6 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co const struct stm32key *key; bool yes, lock, closed; struct udevice *dev; - u32 val; int ret; yes = false; @@ -407,12 +597,8 @@ static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *co if (!yes && !confirm_prog()) return CMD_RET_FAILURE; - 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 %d\n", STM32_OTP_CLOSE_ID); + if (write_close_status(dev)) return CMD_RET_FAILURE; - } printf("Device is closed !\n"); @@ -432,3 +618,25 @@ U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Manage key on STM32", stm32key_help_text, 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)); + +/* + * Check the "closed" state in product life cycle, when product secrets have + * been provisioned into the device, by SSP tools for example. + * On closed devices, authentication is mandatory. + */ +bool stm32mp_is_closed(void) +{ + struct udevice *dev; + bool closed; + int ret; + + ret = get_misc_dev(&dev); + if (ret) + return false; + + ret = read_close_status(dev, false, &closed); + if (ret) + return false; + + return closed; +} diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig index 589276282e4..490097e98be 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/Kconfig @@ -27,6 +27,8 @@ config CMD_STM32PROG_USB config CMD_STM32PROG_SERIAL bool "support stm32prog over UART" depends on CMD_STM32PROG + imply DISABLE_CONSOLE + imply SILENT_CONSOLE default y help activate the command "stm32prog serial" for STM32MP soc family diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c index 353aecc09de..5b027fad048 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c @@ -13,6 +13,7 @@ #include <part.h> #include <tee.h> #include <asm/arch/stm32mp1_smc.h> +#include <asm/arch/sys_proto.h> #include <asm/global_data.h> #include <dm/device_compat.h> #include <dm/uclass.h> @@ -1156,7 +1157,8 @@ static int create_gpt_partitions(struct stm32prog_data *data) /* partition UUID */ uuid_bin = NULL; - if (!rootfs_found && !strcmp(part->name, "rootfs")) { + if (!rootfs_found && (!strcmp(part->name, "rootfs") || + !strcmp(part->name, "rootfs-a"))) { mmc_id = part->dev_id; rootfs_found = true; if (mmc_id < ARRAY_SIZE(uuid_mmc)) @@ -1357,7 +1359,7 @@ static int dfu_init_entities(struct stm32prog_data *data) alt_nb = 1; /* number of virtual = CMD*/ - if (IS_ENABLED(CONFIG_CMD_STM32PROG_OTP)) { + if (IS_ENABLED(CONFIG_CMD_STM32PROG_OTP) && !stm32mp_is_closed()) { /* OTP_SIZE_SMC = 0 if SMC is not supported */ otp_size = OTP_SIZE_SMC; /* check if PTA BSEC is supported */ diff --git a/arch/arm/mach-stm32mp/include/mach/etzpc.h b/arch/arm/mach-stm32mp/include/mach/etzpc.h new file mode 100644 index 00000000000..fd697c3e2ac --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/etzpc.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef MACH_ETZPC_H +#define MACH_ETZPC_H + +#include <linux/types.h> + +/** + * stm32_etzpc_check_access - Check ETZPC accesses for given device node + * + * @device_node Node of the device for which the accesses are checked + * + * @returns 0 on success (if access is granted), -EINVAL if access is denied. + * Else, returns an appropriate negative ERRNO value + */ +int stm32_etzpc_check_access(ofnode device_node); + +/** + * stm32_etzpc_check_access_by_id - Check ETZPC accesses for given id + * + * @device_node Node of the device to get a reference on ETZPC + * @id ID of the resource to check + * + * @returns 0 on success (if access is granted), -EINVAL if access is denied. + * Else, returns an appropriate negative ERRNO value + */ +int stm32_etzpc_check_access_by_id(ofnode device_node, u32 id); + +#endif /* MACH_ETZPC_H*/ diff --git a/arch/arm/mach-stm32mp/include/mach/rif.h b/arch/arm/mach-stm32mp/include/mach/rif.h new file mode 100644 index 00000000000..10b22108120 --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/rif.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef MACH_RIF_H +#define MACH_RIF_H + +#include <linux/types.h> + +/** + * stm32_rifsc_check_access - Check RIF accesses for given device node + * + * @device_node Node of the device for which the accesses are checked + */ +int stm32_rifsc_check_access(ofnode device_node); + +/** + * stm32_rifsc_check_access - Check RIF accesses for given id + * + * @device_node Node of the device to get a reference on RIFSC + * @id ID of the resource to check + */ +int stm32_rifsc_check_access_by_id(ofnode device_node, u32 id); + +#endif /* MACH_RIF_H*/ diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 6eb85ba7233..a9ac49bc5d2 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -42,6 +42,9 @@ enum boot_device { BOOT_FLASH_SPINAND = 0x70, BOOT_FLASH_SPINAND_1 = 0x71, + + BOOT_FLASH_HYPERFLASH = 0x80, + BOOT_FLASH_HYPERFLASH_1 = 0x81 }; #define TAMP_BOOT_MODE_MASK GENMASK(15, 8) @@ -158,8 +161,20 @@ enum forced_boot_mode { #endif /* CONFIG_STM32MP15X || CONFIG_STM32MP13X */ #ifdef CONFIG_STM32MP25X +#define STM32_USART2_BASE 0x400E0000 +#define STM32_USART3_BASE 0x400F0000 +#define STM32_UART4_BASE 0x40100000 +#define STM32_UART5_BASE 0x40110000 +#define STM32_USART6_BASE 0x40220000 +#define STM32_UART9_BASE 0x402C0000 +#define STM32_USART1_BASE 0x40330000 +#define STM32_UART7_BASE 0x40370000 +#define STM32_UART8_BASE 0x40380000 #define STM32_RCC_BASE 0x44200000 #define STM32_TAMP_BASE 0x46010000 +#define STM32_SDMMC1_BASE 0x48220000 +#define STM32_SDMMC2_BASE 0x48230000 +#define STM32_SDMMC3_BASE 0x48240000 #define STM32_DDR_BASE 0x80000000 @@ -197,6 +212,7 @@ enum forced_boot_mode { #ifdef CONFIG_STM32MP25X #define BSEC_OTP_SERIAL 5 #define BSEC_OTP_RPN 9 +#define BSEC_OTP_REVID 102 #define BSEC_OTP_PKG 122 #define BSEC_OTP_BOARD 246 #define BSEC_OTP_MAC 247 diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index 2a65efc0a50..19073668497 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h @@ -58,6 +58,7 @@ u32 get_cpu_type(void); /* return CPU_DEV constants */ u32 get_cpu_dev(void); +/* Silicon revision = REV_ID[15:0] of Device Version */ #define CPU_REV1 0x1000 #define CPU_REV1_1 0x1001 #define CPU_REV1_2 0x1003 @@ -65,7 +66,15 @@ u32 get_cpu_dev(void); #define CPU_REV2_1 0x2001 #define CPU_REV2_2 0x2003 -/* return Silicon revision = REV_ID[15:0] of Device Version */ +/* OTP revision ID = 6 bits : 3 for Major / 3 for Minor */ +#define OTP_REVID_1 0b001000 +#define OTP_REVID_1_1 0b001001 +#define OTP_REVID_1_2 0b001010 +#define OTP_REVID_2 0b010000 +#define OTP_REVID_2_1 0b010001 +#define OTP_REVID_2_2 0b010010 + +/* return SoC revision = Silicon revision (STM32MP1) or OTP revision ID (STM32MP2)*/ u32 get_cpu_rev(void); /* Get Package options from OTP */ @@ -80,9 +89,9 @@ u32 get_cpu_package(void); /* package used for STM32MP25x */ #define STM32MP25_PKG_CUSTOM 0 -#define STM32MP25_PKG_AL_TBGA361 3 -#define STM32MP25_PKG_AK_TBGA424 4 -#define STM32MP25_PKG_AI_TBGA436 5 +#define STM32MP25_PKG_AL_VFBGA361 1 +#define STM32MP25_PKG_AK_VFBGA424 3 +#define STM32MP25_PKG_AI_TFBGA436 5 #define STM32MP25_PKG_UNKNOWN 7 /* Get SOC name */ @@ -111,3 +120,10 @@ u32 get_otp(int index, int shift, int mask); uintptr_t get_stm32mp_rom_api_table(void); uintptr_t get_stm32mp_bl2_dtb(void); + +/* helper function: check "closed" state in product "Life Cycle" */ +#ifdef CONFIG_CMD_STM32KEY +bool stm32mp_is_closed(void); +#else +static inline bool stm32mp_is_closed(void) { return false; } +#endif diff --git a/arch/arm/mach-stm32mp/stm32mp1/Makefile b/arch/arm/mach-stm32mp/stm32mp1/Makefile index db160c24cbc..1f4ada3ac70 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/Makefile +++ b/arch/arm/mach-stm32mp/stm32mp1/Makefile @@ -4,6 +4,7 @@ # obj-y += cpu.o +obj-y += etzpc.o obj-$(CONFIG_STM32MP13X) += stm32mp13x.o obj-$(CONFIG_STM32MP15X) += stm32mp15x.o @@ -15,5 +16,5 @@ else obj-$(CONFIG_ARMV7_PSCI) += psci.o endif -obj-$(CONFIG_$(XPL_)STM32MP15_PWR) += pwr_regulator.o +obj-$(CONFIG_$(PHASE_)STM32MP15_PWR) += pwr_regulator.o obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o diff --git a/arch/arm/mach-stm32mp/stm32mp1/etzpc.c b/arch/arm/mach-stm32mp/stm32mp1/etzpc.c new file mode 100644 index 00000000000..7013bf97167 --- /dev/null +++ b/arch/arm/mach-stm32mp/stm32mp1/etzpc.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#define LOG_CATEGORY UCLASS_NOP + +#include <dm.h> +#include <asm/io.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <linux/bitfield.h> +#include <mach/etzpc.h> + +/* ETZPC peripheral as firewall bus */ +/* ETZPC registers */ +#define ETZPC_DECPROT 0x10 +#define ETZPC_HWCFGR 0x3F0 + +/* ETZPC miscellaneous */ +#define ETZPC_PROT_MASK GENMASK(1, 0) +#define ETZPC_PROT_A7NS 0x3 +#define ETZPC_DECPROT_SHIFT 1 + +#define IDS_PER_DECPROT_REGS 16 + +#define ETZPC_HWCFGR_NUM_PER_SEC GENMASK(15, 8) +#define ETZPC_HWCFGR_NUM_AHB_SEC GENMASK(23, 16) + +/* + * struct stm32_etzpc_plat: Information about ETZPC device + * + * @base: Base address of ETZPC + * @max_entries: Number of securable peripherals in ETZPC + */ +struct stm32_etzpc_plat { + void *base; + unsigned int max_entries; +}; + +static int etzpc_parse_feature_domain(ofnode node, struct ofnode_phandle_args *args) +{ + int ret; + + ret = ofnode_parse_phandle_with_args(node, "access-controllers", + "#access-controller-cells", 0, + 0, args); + if (ret) { + log_debug("failed to parse access-controller (%d)\n", ret); + return ret; + } + + if (args->args_count != 1) { + log_debug("invalid domain args_count: %d\n", args->args_count); + return -EINVAL; + } + + return 0; +} + +static int etzpc_check_access(void *base, u32 id) +{ + u32 reg_offset, offset, sec_val; + + /* Check access configuration, 16 peripherals per register */ + reg_offset = ETZPC_DECPROT + 0x4 * (id / IDS_PER_DECPROT_REGS); + offset = (id % IDS_PER_DECPROT_REGS) << ETZPC_DECPROT_SHIFT; + + /* Verify peripheral is non-secure and attributed to cortex A7 */ + sec_val = (readl(base + reg_offset) >> offset) & ETZPC_PROT_MASK; + if (sec_val != ETZPC_PROT_A7NS) { + log_debug("Invalid bus configuration: reg_offset %#x, value %d\n", + reg_offset, sec_val); + return -EACCES; + } + + return 0; +} + +int stm32_etzpc_check_access_by_id(ofnode device_node, u32 id) +{ + struct stm32_etzpc_plat *plat; + struct ofnode_phandle_args args; + struct udevice *dev; + int err; + + err = etzpc_parse_feature_domain(device_node, &args); + if (err) + return err; + + if (id == -1U) + id = args.args[0]; + + err = uclass_get_device_by_ofnode(UCLASS_NOP, args.node, &dev); + if (err || dev->driver != DM_DRIVER_GET(stm32_etzpc)) { + log_err("No device found\n"); + return -EINVAL; + } + + plat = dev_get_plat(dev); + + if (id >= plat->max_entries) { + dev_err(dev, "Invalid sys bus ID for %s\n", ofnode_get_name(device_node)); + return -EINVAL; + } + + return etzpc_check_access(plat->base, id); +} + +int stm32_etzpc_check_access(ofnode device_node) +{ + return stm32_etzpc_check_access_by_id(device_node, -1U); +} + +static int stm32_etzpc_bind(struct udevice *dev) +{ + struct stm32_etzpc_plat *plat = dev_get_plat(dev); + struct ofnode_phandle_args args; + u32 nb_per, nb_master; + int ret = 0, err = 0; + ofnode node, parent; + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) { + dev_err(dev, "can't get registers base address\n"); + return -ENOENT; + } + + /* Get number of etzpc entries*/ + nb_per = FIELD_GET(ETZPC_HWCFGR_NUM_PER_SEC, + readl(plat->base + ETZPC_HWCFGR)); + nb_master = FIELD_GET(ETZPC_HWCFGR_NUM_AHB_SEC, + readl(plat->base + ETZPC_HWCFGR)); + plat->max_entries = nb_per + nb_master; + + parent = dev_ofnode(dev); + for (node = ofnode_first_subnode(parent); + ofnode_valid(node); + node = ofnode_next_subnode(node)) { + const char *node_name = ofnode_get_name(node); + + if (!ofnode_is_enabled(node)) + continue; + + err = etzpc_parse_feature_domain(node, &args); + if (err) { + dev_err(dev, "%s failed to parse child on bus (%d)\n", node_name, err); + continue; + } + + if (!ofnode_equal(args.node, parent)) { + dev_err(dev, "%s phandle to %s\n", + node_name, ofnode_get_name(args.node)); + continue; + } + + if (args.args[0] >= plat->max_entries) { + dev_err(dev, "Invalid sys bus ID for %s\n", node_name); + return -EINVAL; + } + + err = etzpc_check_access(plat->base, args.args[0]); + if (err) { + dev_info(dev, "%s not allowed on bus (%d)\n", node_name, err); + continue; + } + + err = lists_bind_fdt(dev, node, NULL, NULL, + gd->flags & GD_FLG_RELOC ? false : true); + if (err) { + ret = err; + dev_err(dev, "%s failed to bind on bus (%d)\n", node_name, ret); + } + } + + if (ret) + dev_err(dev, "Some child failed to bind (%d)\n", ret); + + return ret; +} + +static const struct udevice_id stm32_etzpc_ids[] = { + { .compatible = "st,stm32-etzpc" }, + {}, +}; + +U_BOOT_DRIVER(stm32_etzpc) = { + .name = "stm32_etzpc", + .id = UCLASS_NOP, + .of_match = stm32_etzpc_ids, + .bind = stm32_etzpc_bind, + .plat_auto = sizeof(struct stm32_etzpc_plat), +}; diff --git a/arch/arm/mach-stm32mp/stm32mp1/fdt.c b/arch/arm/mach-stm32mp/stm32mp1/fdt.c index e1e4dc04e01..72474fa73f6 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/fdt.c +++ b/arch/arm/mach-stm32mp/stm32mp1/fdt.c @@ -14,20 +14,6 @@ #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 - #define STM32MP13_FDCAN_BASE 0x4400F000 #define STM32MP13_ADC1_BASE 0x48003000 #define STM32MP13_TSC_BASE 0x5000B000 @@ -42,204 +28,6 @@ #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 stm32mp15_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 */ - STM32MP15_CRYP1_BASE, /* 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 */ - STM32MP15_FDCAN_BASE, /* 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 */ - STM32MP15_CRYP2_BASE, /* 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) { @@ -263,46 +51,6 @@ static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr) return false; } -static int stm32_fdt_fixup_etzpc(void *fdt, int soc_node) -{ - const u32 *array; - int array_size, i; - int offset, shift; - u32 addr, status, decprot[ETZPC_DECPROT_NB]; - - 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)); - - 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]; - - log_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)) - log_notice("ETZPC: 0x%08x node disabled, decprot %d=%d\n", - addr, i, status); - } - - return 0; -} - /* deactivate all the cpu except core 0 */ static void stm32_fdt_fixup_cpu(void *blob, char *name) { @@ -481,12 +229,6 @@ int ft_system_setup(void *blob, struct bd_info *bd) if (soc < 0) return soc; - if (CONFIG_IS_ENABLED(STM32_ETZPC)) { - ret = stm32_fdt_fixup_etzpc(blob, soc); - if (ret) - return ret; - } - /* MPUs Part Numbers and name*/ cpu = get_cpu_type(); get_soc_name(name); diff --git a/arch/arm/mach-stm32mp/stm32mp2/Makefile b/arch/arm/mach-stm32mp/stm32mp2/Makefile index b579ce5a800..5dbf75daa76 100644 --- a/arch/arm/mach-stm32mp/stm32mp2/Makefile +++ b/arch/arm/mach-stm32mp/stm32mp2/Makefile @@ -5,5 +5,6 @@ obj-y += cpu.o obj-y += arm64-mmu.o +obj-y += rifsc.o obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o obj-$(CONFIG_STM32MP25X) += stm32mp25x.o diff --git a/arch/arm/mach-stm32mp/stm32mp2/cpu.c b/arch/arm/mach-stm32mp/stm32mp2/cpu.c index 9530aa8534b..c3b87d7f981 100644 --- a/arch/arm/mach-stm32mp/stm32mp2/cpu.c +++ b/arch/arm/mach-stm32mp/stm32mp2/cpu.c @@ -24,7 +24,7 @@ * early TLB into the .data section so that it not get cleared * with 16kB alignment */ -#define EARLY_TLB_SIZE 0xA000 +#define EARLY_TLB_SIZE 0x10000 u8 early_tlb[EARLY_TLB_SIZE] __section(".data") __aligned(0x4000); /* @@ -55,6 +55,19 @@ int arch_cpu_init(void) return 0; } +int mach_cpu_init(void) +{ + u32 boot_mode; + + 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; + + return 0; +} + void enable_caches(void) { /* deactivate the data cache, early enabled in arch_cpu_init() */ @@ -67,14 +80,6 @@ void enable_caches(void) dcache_enable(); } -int arch_misc_init(void) -{ - setup_serial_number(); - setup_mac_address(); - - return 0; -} - /* * Force data-section, as .bss will not be valid * when save_boot_params is invoked. @@ -97,3 +102,150 @@ void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2, save_boot_params_ret(); } + +u32 get_bootmode(void) +{ + /* read bootmode from TAMP backup register */ + return (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >> + TAMP_BOOT_MODE_SHIFT; +} + +static void setup_boot_mode(void) +{ + const u32 serial_addr[] = { + STM32_USART1_BASE, + STM32_USART2_BASE, + STM32_USART3_BASE, + STM32_UART4_BASE, + STM32_UART5_BASE, + STM32_USART6_BASE, + STM32_UART7_BASE, + STM32_UART8_BASE, + STM32_UART9_BASE + }; + const u32 sdmmc_addr[] = { + STM32_SDMMC1_BASE, + STM32_SDMMC2_BASE, + STM32_SDMMC3_BASE + }; + char cmd[60]; + u32 boot_ctx = readl(TAMP_BOOT_CONTEXT); + u32 boot_mode = + (boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT; + unsigned int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1; + u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK); + struct udevice *dev; + + log_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d forced=%x\n", + __func__, boot_ctx, boot_mode, instance, forced_mode); + switch (boot_mode & TAMP_BOOT_DEVICE_MASK) { + case BOOT_SERIAL_UART: + if (instance > ARRAY_SIZE(serial_addr)) + break; + /* serial : search associated node in devicetree */ + sprintf(cmd, "serial@%x", serial_addr[instance]); + if (uclass_get_device_by_name(UCLASS_SERIAL, cmd, &dev)) { + /* restore console on error */ + if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL)) + gd->flags &= ~(GD_FLG_SILENT | + GD_FLG_DISABLE_CONSOLE); + log_err("uart%d = %s not found in device tree!\n", + instance + 1, cmd); + break; + } + sprintf(cmd, "%d", dev_seq(dev)); + env_set("boot_device", "serial"); + env_set("boot_instance", cmd); + + /* restore console on uart when not used */ + if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && gd->cur_serial_dev != dev) { + gd->flags &= ~(GD_FLG_SILENT | + GD_FLG_DISABLE_CONSOLE); + log_info("serial boot with console enabled!\n"); + } + break; + case BOOT_SERIAL_USB: + env_set("boot_device", "usb"); + env_set("boot_instance", "0"); + break; + case BOOT_FLASH_SD: + case BOOT_FLASH_EMMC: + if (instance > ARRAY_SIZE(sdmmc_addr)) + break; + /* search associated sdmmc node in devicetree */ + sprintf(cmd, "mmc@%x", sdmmc_addr[instance]); + if (uclass_get_device_by_name(UCLASS_MMC, cmd, &dev)) { + printf("mmc%d = %s not found in device tree!\n", + instance, cmd); + break; + } + sprintf(cmd, "%d", dev_seq(dev)); + env_set("boot_device", "mmc"); + env_set("boot_instance", cmd); + break; + case BOOT_FLASH_NAND: + env_set("boot_device", "nand"); + env_set("boot_instance", "0"); + break; + case BOOT_FLASH_SPINAND: + env_set("boot_device", "spi-nand"); + env_set("boot_instance", "0"); + break; + case BOOT_FLASH_NOR: + env_set("boot_device", "nor"); + if (IS_ENABLED(CONFIG_SYS_MAX_FLASH_BANKS)) + sprintf(cmd, "%d", CONFIG_SYS_MAX_FLASH_BANKS); + else + sprintf(cmd, "%d", 0); + env_set("boot_instance", cmd); + break; + case BOOT_FLASH_HYPERFLASH: + env_set("boot_device", "nor"); + env_set("boot_instance", "0"); + break; + default: + env_set("boot_device", "invalid"); + env_set("boot_instance", ""); + log_err("unexpected boot mode = %x\n", boot_mode); + break; + } + + switch (forced_mode) { + case BOOT_FASTBOOT: + log_info("Enter fastboot!\n"); + env_set("preboot", "env set preboot; fastboot 0"); + break; + case BOOT_STM32PROG: + env_set("boot_device", "usb"); + env_set("boot_instance", "0"); + break; + case BOOT_UMS_MMC0: + case BOOT_UMS_MMC1: + case BOOT_UMS_MMC2: + log_info("Enter UMS!\n"); + instance = forced_mode - BOOT_UMS_MMC0; + sprintf(cmd, "env set preboot; ums 0 mmc %d", instance); + env_set("preboot", cmd); + break; + case BOOT_RECOVERY: + env_set("preboot", "env set preboot; run altbootcmd"); + break; + case BOOT_NORMAL: + break; + default: + log_debug("unexpected forced boot mode = %x\n", forced_mode); + break; + } + + /* clear TAMP for next reboot */ + clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_NORMAL); +} + +int arch_misc_init(void) +{ + setup_boot_mode(); + setup_serial_number(); + setup_mac_address(); + + return 0; +} diff --git a/arch/arm/mach-stm32mp/stm32mp2/rifsc.c b/arch/arm/mach-stm32mp/stm32mp2/rifsc.c new file mode 100644 index 00000000000..50dececf77b --- /dev/null +++ b/arch/arm/mach-stm32mp/stm32mp2/rifsc.c @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#define LOG_CATEGORY UCLASS_NOP + +#include <dm.h> +#include <asm/io.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <linux/bitfield.h> +#include <mach/rif.h> + +/* RIFSC offset register */ +#define RIFSC_RISC_SECCFGR0(id) (0x10 + 0x4 * (id)) +#define RIFSC_RISC_PER0_CIDCFGR(id) (0x100 + 0x8 * (id)) +#define RIFSC_RISC_PER0_SEMCR(id) (0x104 + 0x8 * (id)) + +/* + * SEMCR register + */ +#define SEMCR_MUTEX BIT(0) + +/* RIFSC miscellaneous */ +#define RIFSC_RISC_SCID_MASK GENMASK(6, 4) +#define RIFSC_RISC_SEMWL_MASK GENMASK(23, 16) + +#define IDS_PER_RISC_SEC_PRIV_REGS 32 + +/* + * CIDCFGR register fields + */ +#define CIDCFGR_CFEN BIT(0) +#define CIDCFGR_SEMEN BIT(1) + +#define SEMWL_SHIFT 16 + +#define STM32MP25_RIFSC_ENTRIES 178 + +/* Compartiment IDs */ +#define RIF_CID0 0x0 +#define RIF_CID1 0x1 + +/* + * struct stm32_rifsc_plat: Information about RIFSC device + * + * @base: Base address of RIFSC + */ +struct stm32_rifsc_plat { + void *base; +}; + +/* + * struct stm32_rifsc_child_plat: Information about each child + * + * @domain_id: Domain id + */ +struct stm32_rifsc_child_plat { + u32 domain_id; +}; + +static bool stm32_rif_is_semaphore_available(void *base, u32 id) +{ + void *addr = base + RIFSC_RISC_PER0_SEMCR(id); + + return !(readl(addr) & SEMCR_MUTEX); +} + +static int stm32_rif_acquire_semaphore(void *base, u32 id) +{ + void *addr = base + RIFSC_RISC_PER0_SEMCR(id); + + /* Check that the semaphore is available */ + if (!stm32_rif_is_semaphore_available(base, id)) + return -EACCES; + + setbits_le32(addr, SEMCR_MUTEX); + + /* Check that CID1 has the semaphore */ + if (stm32_rif_is_semaphore_available(base, id) || + FIELD_GET(RIFSC_RISC_SCID_MASK, (readl(addr)) != RIF_CID1)) + return -EACCES; + + return 0; +} + +static int stm32_rif_release_semaphore(void *base, u32 id) +{ + void *addr = base + RIFSC_RISC_PER0_SEMCR(id); + + if (stm32_rif_is_semaphore_available(base, id)) + return 0; + + clrbits_le32(addr, SEMCR_MUTEX); + + /* Ok if another compartment takes the semaphore before the check */ + if (!stm32_rif_is_semaphore_available(base, id) && + FIELD_GET(RIFSC_RISC_SCID_MASK, (readl(addr)) == RIF_CID1)) + return -EACCES; + + return 0; +} + +static int rifsc_parse_access_controller(ofnode node, struct ofnode_phandle_args *args) +{ + int ret; + + ret = ofnode_parse_phandle_with_args(node, "access-controllers", + "#access-controller-cells", 0, + 0, args); + if (ret) { + log_debug("failed to parse access-controller (%d)\n", ret); + return ret; + } + + if (args->args_count != 1) { + log_debug("invalid domain args_count: %d\n", args->args_count); + return -EINVAL; + } + + if (args->args[0] >= STM32MP25_RIFSC_ENTRIES) { + log_err("Invalid sys bus ID for %s\n", ofnode_get_name(node)); + return -EINVAL; + } + + return 0; +} + +static int rifsc_check_access(void *base, u32 id) +{ + u32 reg_offset, reg_id, sec_reg_value, cid_reg_value, sem_reg_value; + + /* + * RIFSC_RISC_PRIVCFGRx and RIFSC_RISC_SECCFGRx both handle configuration access for + * 32 peripherals. On the other hand, there is one _RIFSC_RISC_PERx_CIDCFGR register + * per peripheral + */ + reg_id = id / IDS_PER_RISC_SEC_PRIV_REGS; + reg_offset = id % IDS_PER_RISC_SEC_PRIV_REGS; + sec_reg_value = readl(base + RIFSC_RISC_SECCFGR0(reg_id)); + cid_reg_value = readl(base + RIFSC_RISC_PER0_CIDCFGR(id)); + sem_reg_value = readl(base + RIFSC_RISC_PER0_SEMCR(id)); + + /* + * First check conditions for semaphore mode, which doesn't take into + * account static CID. + */ + if (cid_reg_value & CIDCFGR_SEMEN) + goto skip_cid_check; + + /* + * Skip cid check if CID filtering isn't enabled or filtering is enabled on CID0, which + * corresponds to whatever CID. + */ + if (!(cid_reg_value & CIDCFGR_CFEN) || + FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) == RIF_CID0) + goto skip_cid_check; + + /* Coherency check with the CID configuration */ + if (FIELD_GET(RIFSC_RISC_SCID_MASK, cid_reg_value) != RIF_CID1) { + log_debug("Invalid CID configuration for peripheral %d\n", id); + return -EACCES; + } + + /* Check semaphore accesses */ + if (cid_reg_value & CIDCFGR_SEMEN) { + if (!(FIELD_GET(RIFSC_RISC_SEMWL_MASK, cid_reg_value) & BIT(RIF_CID1))) { + log_debug("Not in semaphore whitelist for peripheral %d\n", id); + return -EACCES; + } + if (!stm32_rif_is_semaphore_available(base, id) && + !(FIELD_GET(RIFSC_RISC_SCID_MASK, sem_reg_value) & BIT(RIF_CID1))) { + log_debug("Semaphore unavailable for peripheral %d\n", id); + return -EACCES; + } + } + +skip_cid_check: + /* Check security configuration */ + if (sec_reg_value & BIT(reg_offset)) { + log_debug("Invalid security configuration for peripheral %d\n", id); + return -EACCES; + } + + return 0; +} + +int stm32_rifsc_check_access_by_id(ofnode device_node, u32 id) +{ + struct ofnode_phandle_args args; + int err; + + if (id >= STM32MP25_RIFSC_ENTRIES) + return -EINVAL; + + err = rifsc_parse_access_controller(device_node, &args); + if (err) + return err; + + return rifsc_check_access((void *)ofnode_get_addr(args.node), id); +} + +int stm32_rifsc_check_access(ofnode device_node) +{ + struct ofnode_phandle_args args; + int err; + + err = rifsc_parse_access_controller(device_node, &args); + if (err) + return err; + + return rifsc_check_access((void *)ofnode_get_addr(args.node), args.args[0]); +} + +static int stm32_rifsc_child_pre_probe(struct udevice *dev) +{ + struct stm32_rifsc_plat *plat = dev_get_plat(dev->parent); + struct stm32_rifsc_child_plat *child_plat = dev_get_parent_plat(dev); + u32 cid_reg_value; + int err; + u32 id = child_plat->domain_id; + + cid_reg_value = readl(plat->base + RIFSC_RISC_PER0_CIDCFGR(id)); + + /* + * If the peripheral is in semaphore mode, take the semaphore so that + * the CID1 has the ownership. + */ + if (cid_reg_value & CIDCFGR_SEMEN && + (FIELD_GET(RIFSC_RISC_SEMWL_MASK, cid_reg_value) & BIT(RIF_CID1))) { + err = stm32_rif_acquire_semaphore(plat->base, id); + if (err) { + dev_err(dev, "Couldn't acquire RIF semaphore for peripheral %d (%d)\n", + id, err); + return err; + } + dev_dbg(dev, "Acquiring semaphore for peripheral %d\n", id); + } + + return 0; +} + +static int stm32_rifsc_child_post_remove(struct udevice *dev) +{ + struct stm32_rifsc_plat *plat = dev_get_plat(dev->parent); + struct stm32_rifsc_child_plat *child_plat = dev_get_parent_plat(dev); + u32 cid_reg_value; + int err; + u32 id = child_plat->domain_id; + + cid_reg_value = readl(plat->base + RIFSC_RISC_PER0_CIDCFGR(id)); + + /* + * If the peripheral is in semaphore mode, release the semaphore so that + * there's no ownership. + */ + if (cid_reg_value & CIDCFGR_SEMEN && + (FIELD_GET(RIFSC_RISC_SEMWL_MASK, cid_reg_value) & BIT(RIF_CID1))) { + err = stm32_rif_release_semaphore(plat->base, id); + if (err) + dev_err(dev, "Couldn't release rif semaphore for peripheral %d (%d)\n", + id, err); + } + + return 0; +} + +static int stm32_rifsc_child_post_bind(struct udevice *dev) +{ + struct stm32_rifsc_child_plat *child_plat = dev_get_parent_plat(dev); + struct ofnode_phandle_args args; + int ret; + + if (!dev_has_ofnode(dev)) + return -EPERM; + + ret = rifsc_parse_access_controller(dev_ofnode(dev), &args); + if (ret) + return ret; + + child_plat->domain_id = args.args[0]; + + return 0; +} + +static int stm32_rifsc_bind(struct udevice *dev) +{ + struct stm32_rifsc_plat *plat = dev_get_plat(dev); + struct ofnode_phandle_args args; + int ret = 0, err = 0; + ofnode node; + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) { + dev_err(dev, "can't get registers base address\n"); + return -ENOENT; + } + + for (node = ofnode_first_subnode(dev_ofnode(dev)); + ofnode_valid(node); + node = ofnode_next_subnode(node)) { + const char *node_name = ofnode_get_name(node); + + if (!ofnode_is_enabled(node)) + continue; + + err = rifsc_parse_access_controller(node, &args); + if (err) { + dev_dbg(dev, "%s failed to parse child on bus (%d)\n", node_name, err); + continue; + } + + err = rifsc_check_access(plat->base, args.args[0]); + if (err) { + dev_info(dev, "%s not allowed on bus (%d)\n", node_name, err); + continue; + } + + err = lists_bind_fdt(dev, node, NULL, NULL, + gd->flags & GD_FLG_RELOC ? false : true); + if (err && !ret) { + ret = err; + dev_err(dev, "%s failed to bind on bus (%d)\n", node_name, ret); + } + } + + if (ret) + dev_err(dev, "Some child failed to bind (%d)\n", ret); + + return ret; +} + +static int stm32_rifsc_remove(struct udevice *bus) +{ + struct udevice *dev; + + /* Deactivate all child devices not yet removed */ + for (device_find_first_child(bus, &dev); dev; device_find_next_child(&dev)) + if (device_active(dev)) + stm32_rifsc_child_post_remove(dev); + + return 0; +} + +static const struct udevice_id stm32_rifsc_ids[] = { + { .compatible = "st,stm32mp25-rifsc" }, + {}, +}; + +U_BOOT_DRIVER(stm32_rifsc) = { + .name = "stm32_rifsc", + .id = UCLASS_NOP, + .of_match = stm32_rifsc_ids, + .bind = stm32_rifsc_bind, + .remove = stm32_rifsc_remove, + .child_post_bind = stm32_rifsc_child_post_bind, + .child_pre_probe = stm32_rifsc_child_pre_probe, + .child_post_remove = stm32_rifsc_child_post_remove, + .plat_auto = sizeof(struct stm32_rifsc_plat), + .per_child_plat_auto = sizeof(struct stm32_rifsc_child_plat), + .flags = DM_FLAG_OS_PREPARE, +}; diff --git a/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c b/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c index 7f896a0d65d..12b43ea5cdf 100644 --- a/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c +++ b/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c @@ -15,8 +15,10 @@ #define SYSCFG_DEVICEID_OFFSET 0x6400 #define SYSCFG_DEVICEID_DEV_ID_MASK GENMASK(11, 0) #define SYSCFG_DEVICEID_DEV_ID_SHIFT 0 -#define SYSCFG_DEVICEID_REV_ID_MASK GENMASK(31, 16) -#define SYSCFG_DEVICEID_REV_ID_SHIFT 16 + +/* Revision ID = OTP102[5:0] 6 bits : 3 for Major / 3 for Minor*/ +#define REVID_SHIFT 0 +#define REVID_MASK GENMASK(5, 0) /* Device Part Number (RPN) = OTP9 */ #define RPN_SHIFT 0 @@ -24,8 +26,8 @@ /* Package = bit 0:2 of OTP122 => STM32MP25_PKG defines * - 000: Custom package - * - 011: TFBGA361 => AL = 10x10, 361 balls pith 0.5mm - * - 100: TFBGA424 => AK = 14x14, 424 balls pith 0.5mm + * - 001: VFBGA361 => AL = 10x10, 361 balls pith 0.5mm + * - 011: VFBGA424 => AK = 14x14, 424 balls pith 0.5mm * - 101: TFBGA436 => AI = 18x18, 436 balls pith 0.5mm * - others: Reserved */ @@ -46,7 +48,7 @@ u32 get_cpu_dev(void) u32 get_cpu_rev(void) { - return (read_deviceid() & SYSCFG_DEVICEID_REV_ID_MASK) >> SYSCFG_DEVICEID_REV_ID_SHIFT; + return get_otp(BSEC_OTP_REVID, REVID_SHIFT, REVID_MASK); } /* Get Device Part Number (RPN) from OTP */ @@ -164,12 +166,21 @@ void get_soc_name(char name[SOC_NAME_SIZE]) } /* REVISION */ switch (get_cpu_rev()) { - case CPU_REV1: + case OTP_REVID_1: cpu_r = "A"; break; - case CPU_REV2: + case OTP_REVID_1_1: + cpu_r = "Z"; + break; + case OTP_REVID_2: cpu_r = "B"; break; + case OTP_REVID_2_1: + cpu_r = "Y"; + break; + case OTP_REVID_2_2: + cpu_r = "X"; + break; default: break; } @@ -178,13 +189,13 @@ void get_soc_name(char name[SOC_NAME_SIZE]) case STM32MP25_PKG_CUSTOM: package = "XX"; break; - case STM32MP25_PKG_AL_TBGA361: + case STM32MP25_PKG_AL_VFBGA361: package = "AL"; break; - case STM32MP25_PKG_AK_TBGA424: + case STM32MP25_PKG_AK_VFBGA424: package = "AK"; break; - case STM32MP25_PKG_AI_TBGA436: + case STM32MP25_PKG_AI_TFBGA436: package = "AI"; break; default: |