GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,562 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/mmc.h>
#include <drivers/st/bsec.h>
#include <drivers/st/regulator_fixed.h>
#include <drivers/st/stm32_iwdg.h>
#include <drivers/st/stm32_rng.h>
#include <drivers/st/stm32_uart.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_pwr.h>
#include <drivers/st/stm32mp1_ram.h>
#include <drivers/st/stm32mp_pmic.h>
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <lib/mmio.h>
#include <lib/optee_utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <stm32mp_common.h>
#include <stm32mp1_dbgmcu.h>
#if DEBUG
static const char debug_msg[] = {
"***************************************************\n"
"** DEBUG ACCESS PORT IS OPEN! **\n"
"** This boot image is only for debugging purpose **\n"
"** and is unsafe for production use. **\n"
"** **\n"
"** If you see this message and you are not **\n"
"** debugging report this immediately to your **\n"
"** vendor! **\n"
"***************************************************\n"
};
#endif
static void print_reset_reason(void)
{
uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
if (rstsr == 0U) {
WARN("Reset reason unknown\n");
return;
}
INFO("Reset reason (0x%x):\n", rstsr);
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
INFO("System exits from STANDBY\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
INFO("MPU exits from CSTANDBY\n");
return;
}
}
if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
INFO(" Power-on Reset (rst_por)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
INFO(" Brownout Reset (rst_bor)\n");
return;
}
#if STM32MP15
if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) {
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
INFO(" System reset generated by MCU (MCSYSRST)\n");
} else {
INFO(" Local reset generated by MCU (MCSYSRST)\n");
}
return;
}
#endif
if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
INFO(" System reset generated by MPU (MPSYSRST)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
INFO(" Reset due to a clock failure on HSE\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
INFO(" IWDG1 Reset (rst_iwdg1)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
INFO(" IWDG2 Reset (rst_iwdg2)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) {
INFO(" MPU Processor 0 Reset\n");
return;
}
#if STM32MP15
if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) {
INFO(" MPU Processor 1 Reset\n");
return;
}
#endif
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
INFO(" Pad Reset from NRST\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
INFO(" Reset due to a failure of VDD_CORE\n");
return;
}
ERROR(" Unidentified reset reason\n");
}
void bl2_el3_early_platform_setup(u_register_t arg0,
u_register_t arg1 __unused,
u_register_t arg2 __unused,
u_register_t arg3 __unused)
{
stm32mp_setup_early_console();
stm32mp_save_boot_ctx_address(arg0);
}
void bl2_platform_setup(void)
{
int ret;
ret = stm32mp1_ddr_probe();
if (ret < 0) {
ERROR("Invalid DDR init: error %d\n", ret);
panic();
}
/* Map DDR for binary load, now with cacheable attribute */
ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
if (ret < 0) {
ERROR("DDR mapping: error %d\n", ret);
panic();
}
}
#if STM32MP15
static void update_monotonic_counter(void)
{
uint32_t version;
uint32_t otp;
CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE,
assert_stm32mp1_monotonic_counter_reach_max);
/* Check if monotonic counter needs to be incremented */
if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) {
panic();
}
if (stm32_get_otp_value_from_idx(otp, &version) != 0) {
panic();
}
if ((version + 1U) < BIT(STM32_TF_VERSION)) {
uint32_t result;
/* Need to increment the monotonic counter. */
version = BIT(STM32_TF_VERSION) - 1U;
result = bsec_program_otp(version, otp);
if (result != BSEC_OK) {
ERROR("BSEC: MONOTONIC_OTP program Error %u\n",
result);
panic();
}
INFO("Monotonic counter has been incremented (value 0x%x)\n",
version);
}
}
#endif
void bl2_el3_plat_arch_setup(void)
{
const char *board_model;
boot_api_context_t *boot_context =
(boot_api_context_t *)stm32mp_get_boot_ctx_address();
uintptr_t pwr_base;
uintptr_t rcc_base;
if (bsec_probe() != 0U) {
panic();
}
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
BL_CODE_END - BL_CODE_BASE,
MT_CODE | MT_SECURE);
/* Prevent corruption of preloaded Device Tree */
mmap_add_region(DTB_BASE, DTB_BASE,
DTB_LIMIT - DTB_BASE,
MT_RO_DATA | MT_SECURE);
configure_mmu();
if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
panic();
}
pwr_base = stm32mp_pwr_base();
rcc_base = stm32mp_rcc_base();
/*
* Disable the backup domain write protection.
* The protection is enable at each reset by hardware
* and must be disabled by software.
*/
mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
;
}
/* Reset backup domain on cold boot cases */
if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
0U) {
;
}
mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
}
#if STM32MP15
/* Disable MCKPROT */
mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
#endif
/*
* Set minimum reset pulse duration to 31ms for discrete power
* supplied boards.
*/
if (dt_pmic_status() <= 0) {
mmio_clrsetbits_32(rcc_base + RCC_RDLSICR,
RCC_RDLSICR_MRD_MASK,
31U << RCC_RDLSICR_MRD_SHIFT);
}
generic_delay_timer_init();
#if STM32MP_UART_PROGRAMMER
/* Disable programmer UART before changing clock tree */
if (boot_context->boot_interface_selected ==
BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) {
uintptr_t uart_prog_addr =
get_uart_address(boot_context->boot_interface_instance);
stm32_uart_stop(uart_prog_addr);
}
#endif
if (stm32mp1_clk_probe() < 0) {
panic();
}
if (stm32mp1_clk_init() < 0) {
panic();
}
stm32_save_boot_interface(boot_context->boot_interface_selected,
boot_context->boot_interface_instance);
stm32_save_boot_auth(boot_context->auth_status,
boot_context->boot_partition_used_toboot);
#if STM32MP_USB_PROGRAMMER && STM32MP15
/* Deconfigure all UART RX pins configured by ROM code */
stm32mp1_deconfigure_uart_pins();
#endif
if (stm32mp_uart_console_setup() != 0) {
goto skip_console_init;
}
stm32mp_print_cpuinfo();
board_model = dt_get_board_model();
if (board_model != NULL) {
NOTICE("Model: %s\n", board_model);
}
stm32mp_print_boardinfo();
if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
NOTICE("Bootrom authentication %s\n",
(boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ?
"failed" : "succeeded");
}
skip_console_init:
#if !TRUSTED_BOARD_BOOT
if (stm32mp_is_closed_device()) {
/* Closed chip mandates authentication */
ERROR("Secure chip: TRUSTED_BOARD_BOOT must be enabled\n");
panic();
}
#endif
if (fixed_regulator_register() != 0) {
panic();
}
if (dt_pmic_status() > 0) {
initialize_pmic();
if (pmic_voltages_init() != 0) {
ERROR("PMIC voltages init failed\n");
panic();
}
print_pmic_info_and_debug();
}
stm32mp1_syscfg_init();
if (stm32_iwdg_init() < 0) {
panic();
}
stm32_iwdg_refresh();
if (bsec_read_debug_conf() != 0U) {
if (stm32mp_is_closed_device()) {
#if DEBUG
WARN("\n%s", debug_msg);
#else
ERROR("***Debug opened on closed chip***\n");
#endif
}
}
#if STM32MP13
if (stm32_rng_init() != 0) {
panic();
}
#endif
stm32mp1_arch_security_setup();
print_reset_reason();
#if STM32MP15
update_monotonic_counter();
#endif
stm32mp1_syscfg_enable_io_compensation_finish();
fconf_populate("TB_FW", STM32MP_DTB_BASE);
stm32mp_io_setup();
}
/*******************************************************************************
* This function can be used by the platforms to update/use image
* information for given `image_id`.
******************************************************************************/
int bl2_plat_handle_post_image_load(unsigned int image_id)
{
int err = 0;
bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
bl_mem_params_node_t *bl32_mem_params;
bl_mem_params_node_t *pager_mem_params __unused;
bl_mem_params_node_t *paged_mem_params __unused;
const struct dyn_cfg_dtb_info_t *config_info;
bl_mem_params_node_t *tos_fw_mem_params;
unsigned int i;
unsigned int idx;
unsigned long long ddr_top __unused;
const unsigned int image_ids[] = {
BL32_IMAGE_ID,
BL33_IMAGE_ID,
HW_CONFIG_ID,
TOS_FW_CONFIG_ID,
};
assert(bl_mem_params != NULL);
switch (image_id) {
case FW_CONFIG_ID:
/* Set global DTB info for fixed fw_config information */
set_config_info(STM32MP_FW_CONFIG_BASE, ~0UL, STM32MP_FW_CONFIG_MAX_SIZE,
FW_CONFIG_ID);
fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID);
/* Iterate through all the fw config IDs */
for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) {
continue;
}
bl_mem_params = get_bl_mem_params_node(image_ids[i]);
assert(bl_mem_params != NULL);
config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
if (config_info == NULL) {
continue;
}
bl_mem_params->image_info.image_base = config_info->config_addr;
bl_mem_params->image_info.image_max_size = config_info->config_max_size;
bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
switch (image_ids[i]) {
case BL32_IMAGE_ID:
bl_mem_params->ep_info.pc = config_info->config_addr;
/* In case of OPTEE, initialize address space with tos_fw addr */
pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
assert(pager_mem_params != NULL);
pager_mem_params->image_info.image_base = config_info->config_addr;
pager_mem_params->image_info.image_max_size =
config_info->config_max_size;
/* Init base and size for pager if exist */
paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
if (paged_mem_params != NULL) {
paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
(dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
STM32MP_DDR_SHMEM_SIZE);
paged_mem_params->image_info.image_max_size =
STM32MP_DDR_S_SIZE;
}
break;
case BL33_IMAGE_ID:
bl_mem_params->ep_info.pc = config_info->config_addr;
break;
case HW_CONFIG_ID:
case TOS_FW_CONFIG_ID:
break;
default:
return -EINVAL;
}
}
break;
case BL32_IMAGE_ID:
if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
image_info_t *paged_image_info = NULL;
/* BL32 is OP-TEE header */
bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
assert(pager_mem_params != NULL);
paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
if (paged_mem_params != NULL) {
paged_image_info = &paged_mem_params->image_info;
}
err = parse_optee_header(&bl_mem_params->ep_info,
&pager_mem_params->image_info,
paged_image_info);
if (err != 0) {
ERROR("OPTEE header parse error.\n");
panic();
}
/* Set optee boot info from parsed header data */
if (paged_mem_params != NULL) {
bl_mem_params->ep_info.args.arg0 =
paged_mem_params->image_info.image_base;
} else {
bl_mem_params->ep_info.args.arg0 = 0U;
}
bl_mem_params->ep_info.args.arg1 = 0U; /* Unused */
bl_mem_params->ep_info.args.arg2 = 0U; /* No DT supported */
} else {
bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
assert(tos_fw_mem_params != NULL);
bl_mem_params->image_info.image_max_size +=
tos_fw_mem_params->image_info.image_max_size;
bl_mem_params->ep_info.args.arg0 = 0;
}
break;
case BL33_IMAGE_ID:
bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
assert(bl32_mem_params != NULL);
bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
#if PSA_FWU_SUPPORT
stm32mp1_fwu_set_boot_idx();
#endif /* PSA_FWU_SUPPORT */
break;
default:
/* Do nothing in default case */
break;
}
#if STM32MP_SDMMC || STM32MP_EMMC
/*
* Invalidate remaining data read from MMC but not flushed by load_image_flush().
* We take the worst case which is 2 MMC blocks.
*/
if ((image_id != FW_CONFIG_ID) &&
((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
inv_dcache_range(bl_mem_params->image_info.image_base +
bl_mem_params->image_info.image_size,
2U * MMC_BLOCK_SIZE);
}
#endif /* STM32MP_SDMMC || STM32MP_EMMC */
return err;
}
void bl2_el3_plat_prepare_exit(void)
{
uint16_t boot_itf = stm32mp_get_boot_itf_selected();
switch (boot_itf) {
#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
/* Invalidate the downloaded buffer used with io_memmap */
inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
break;
#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
default:
/* Do nothing in default case */
break;
}
stm32mp1_security_setup();
}
@@ -0,0 +1,19 @@
#
# Copyright (c) 2022, STMicroelectronics - All Rights Reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Override TBBR Cert to update generic certificate
$(eval $(call add_define,PDEF_CERTS))
PLAT_INCLUDE += -I${PLAT_DIR}include
src/stm32mp1_tbb_cert.o: ${PLAT_DIR}stm32mp1_tbb_cert.c
${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
PLAT_OBJECTS = src/stm32mp1_tbb_cert.o
OBJECTS += $(PLAT_OBJECTS)
@@ -0,0 +1,409 @@
/*
* Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BOOT_API_H
#define BOOT_API_H
#include <stdint.h>
#include <stdio.h>
/*
* Possible value of boot context field 'auth_status'
*/
#if STM32MP13
/* No authentication done */
#define BOOT_API_CTX_AUTH_NO 0x7CFDD351U
/* Authentication done and failed */
#define BOOT_API_CTX_AUTH_FAILED 0x51330884U
/* Authentication done and success */
#define BOOT_API_CTX_AUTH_SUCCESS 0x67E8CAE1U
#endif
#if STM32MP15
/* No authentication done */
#define BOOT_API_CTX_AUTH_NO 0x0U
/* Authentication done and failed */
#define BOOT_API_CTX_AUTH_FAILED 0x1U
/* Authentication done and succeeded */
#define BOOT_API_CTX_AUTH_SUCCESS 0x2U
#endif
/*
* Possible value of boot context field 'boot_interface_sel'
*/
/* Value of field 'boot_interface_sel' when no boot occurred */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_NO 0x0U
/* Boot occurred on SD */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD 0x1U
/* Boot occurred on EMMC */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U
/* Boot occurred on FMC */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC 0x3U
/* Boot occurred on QSPI NOR */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI 0x4U
/* Boot occurred on UART */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U
/* Boot occurred on USB */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U
/* Boot occurred on QSPI NAND */
#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U
/**
* @brief Possible value of boot context field 'EmmcXferStatus'
*/
/*
* Possible value of boot context field 'emmc_xfer_status'
*/
#define BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED 0x0U
#define BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED 0x1U
#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED 0x2U
#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT 0x3U
/*
* Possible value of boot context field 'emmc_error_status'
*/
#define BOOT_API_CTX_EMMC_ERROR_STATUS_NONE 0x0U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT 0x1U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT 0x2U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL 0x3U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX 0x4U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND 0x5U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U
#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_ERROR 0x8U
/* Image Header related definitions */
/* Definition of header version */
#if STM32MP13
#define BOOT_API_HEADER_VERSION 0x00020000U
#endif
#if STM32MP15
#define BOOT_API_HEADER_VERSION 0x00010000U
#endif
/*
* Magic number used to detect header in memory
* Its value must be 'S' 'T' 'M' 0x32, i.e 0x324D5453 as field
* 'bootapi_image_header_t.magic'
* This identifies the start of a boot image.
*/
#define BOOT_API_IMAGE_HEADER_MAGIC_NB 0x324D5453U
/* Definitions related to Authentication used in image header structure */
#define BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES 64
#define BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES 64
#define BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES 32
/* Possible values of the field 'boot_api_image_header_t.ecc_algo_type' */
#define BOOT_API_ECDSA_ALGO_TYPE_P256NIST 1
#define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256 2
/*
* Extension headers related definitions
*/
/* 'bootapi_image_header_t.extension_flag' used for authentication feature */
#define BOOT_API_AUTHENTICATION_EXTENSION_BIT BIT(0)
/* 'bootapi_image_header_t.extension_flag' used for FSBL decryption feature */
#define BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT BIT(1)
/* 'bootapi_image_header_t.extension_flag' used for padding header feature */
#define BOOT_API_PADDING_EXTENSION_BIT BIT(31)
/*
* mask of bits of field 'bootapi_image_header_t.extension_flag'
* used for extension headers
*/
#define BOOT_API_ALL_EXTENSIONS_MASK \
(BOOT_API_AUTHENTICATION_EXTENSION_BIT | \
BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT | \
BOOT_API_PADDING_EXTENSION_BIT)
/*
* Magic number of FSBL decryption extension header
* The value shall gives the four bytes 'S','T',0x00,0x01 in memory
*/
#define BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB 0x01005453U
/*
* Magic number of PKH revocation extension header
* The value shall gives the four bytes 'S','T',0x00,0x02 in memory
*/
#define BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB 0x02005453U
/* Max number of ECDSA public key hash in table */
#define BOOT_API_AUTHENTICATION_NB_PKH_MAX 8U
/* ECDSA public key hash table size in bytes */
#define BOOT_API_AUTHENTICATION_TABLE_SIZE_BYTES \
(BOOT_API_AUTHENTICATION_NB_PKH_MAX * \
BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)
/*
* Magic number of padding extension header
* The value shall gives the four bytes 'S','T',0xFF,0xFF in memory
*/
#define BOOT_API_PADDING_HEADER_MAGIC_NB 0xFFFF5453U
/*
* Cores secure magic numbers
* Constant to be stored in bakcup register
* BOOT_API_MAGIC_NUMBER_TAMP_BCK_REG_IDX
*/
#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U
#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U
/*
* TAMP_BCK4R register index
* This register is used to write a Magic Number in order to restart
* Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R
*/
#define BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX 4U
/*
* TAMP_BCK5R register index
* This register is used to contain the branch address of
* Cortex A7 Core 1 when restarted by a TAMP_BCK4R magic number writing
*/
#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U
/*
* Possible value of boot context field 'hse_clock_value_in_hz'
*/
#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U
#define BOOT_API_CTX_HSE_CLOCK_VALUE_24_MHZ 24000000U
#define BOOT_API_CTX_HSE_CLOCK_VALUE_25_MHZ 25000000U
#define BOOT_API_CTX_HSE_CLOCK_VALUE_26_MHZ 26000000U
/*
* Possible value of boot context field 'boot_partition_used_toboot'
*/
#define BOOT_API_CTX_BOOT_PARTITION_UNDEFINED 0U
/* Used FSBL1 to boot */
#define BOOT_API_CTX_BOOT_PARTITION_FSBL1 1U
/* Used FSBL2 to boot */
#define BOOT_API_CTX_BOOT_PARTITION_FSBL2 2U
/* OTP_CFG0 */
#define BOOT_API_OTP_MODE_WORD_NB 0
/* Closed = OTP_CFG0[6] */
#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6
#define BOOT_API_RETURN_OK 0x77U
/*
* Boot Context related definitions
*/
/*
* Boot core boot configuration structure
* Specifies all items of the cold boot configuration
* Memory and peripheral part.
*/
typedef struct {
/*
* Boot interface used to boot : take values from defines
* BOOT_API_CTX_BOOT_INTERFACE_SEL_XXX above
*/
uint16_t boot_interface_selected;
uint16_t boot_interface_instance;
#if STM32MP13
uint32_t reserved1[12];
#endif
#if STM32MP15
uint32_t reserved1[13];
#endif
uint32_t otp_afmux_values[3];
uint32_t reserved[3];
#if STM32MP15
uint32_t reserved2[2];
#endif
uint32_t auth_status;
#if STM32MP15
/*
* Pointers to bootROM External Secure Services
* - ECDSA verify signature
*/
uint32_t reserved3;
uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in,
uint8_t *pubkey_in,
uint8_t *signature,
uint32_t ecc_algo);
uint32_t reserved4;
#endif
/*
* Information specific to an SD boot
* Updated each time an SD boot is at least attempted,
* even if not successful
* Note : This is useful to understand why an SD boot failed
* in particular
*/
uint32_t sd_err_internal_timeout_cnt;
uint32_t sd_err_dcrc_fail_cnt;
uint32_t sd_err_dtimeout_cnt;
uint32_t sd_err_ctimeout_cnt;
uint32_t sd_err_ccrc_fail_cnt;
uint32_t sd_overall_retry_cnt;
/*
* Information specific to an eMMC boot
* Updated each time an eMMC boot is at least attempted,
* even if not successful
* Note : This is useful to understand why an eMMC boot failed
* in particular
*/
uint32_t emmc_xfer_status;
uint32_t emmc_error_status;
uint32_t emmc_nbbytes_rxcopied_tosysram_download_area;
uint32_t hse_clock_value_in_hz;
/*
* Boot partition :
* ie FSBL partition on which the boot was successful
*/
uint32_t boot_partition_used_toboot;
} __packed boot_api_context_t;
/*
* Image Header related definitions
*/
/*
* Structure used to define the common Header format used for FSBL, xloader,
* ... and in particular used by bootROM for FSBL header readout.
* FSBL header size is 256 Bytes = 0x100
*/
typedef struct {
/* BOOT_API_IMAGE_HEADER_MAGIC_NB */
uint32_t magic;
uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES];
/*
* Checksum of payload
* 32-bit sum all payload bytes considered as 8 bit unsigned
* numbers, discarding any overflow bits.
* Use to check UART/USB downloaded image integrity when signature
* is not used
*/
uint32_t payload_checksum;
/* Image header version : should have value BOOT_API_HEADER_VERSION */
uint32_t header_version;
/* Image length in bytes */
uint32_t image_length;
/*
* Image Entry point address : should be in the SYSRAM area
* and at least within the download area range
*/
uint32_t image_entry_point;
/* Reserved */
uint32_t reserved1;
/*
* Image load address : not used by bootROM but to be consistent
* with header format for other packages (xloader, ...)
*/
uint32_t load_address;
/* Reserved */
uint32_t reserved2;
/* Image version to be compared by bootROM with monotonic
* counter value in OTP_CFG4 prior executing the downloaded image
*/
uint32_t image_version;
#if STM32MP13
/*
* Extension flags :
*
* Bit 0 : Authentication extension header
* value 0 : No signature check request
* Bit 1 : Encryption extension header
* Bit 2 : Padding extension header
*/
uint32_t extension_flags;
/* Length in bytes of all extension headers */
uint32_t extension_headers_length;
/* Add binary type information */
uint32_t binary_type;
/* Pad up to 128 byte total size */
uint8_t pad[16];
/* Followed by extension header */
uint8_t ext_header[];
#endif
#if STM32MP15
/*
* Option flags:
* Bit 0 : No signature check request : 'No_sig_check'
* value 1 : for No signature check request
* value 0 : No request to bypass the signature check
* Note : No signature check is never allowed on a Secured chip
*/
uint32_t option_flags;
/*
* Type of ECC algorithm to use :
* value 1 : for P-256 NIST algorithm
* value 2 : for Brainpool 256 algorithm
* See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
*/
uint32_t ecc_algo_type;
/*
* OEM ECC Public Key (aka Root pubk) provided in header on 512 bits.
* The SHA-256 hash of the OEM ECC pubk must match the one stored
* in OTP cells.
*/
uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
/* Pad up to 256 byte total size */
uint8_t pad[83];
/* Add binary type information */
uint8_t binary_type;
#endif
} __packed boot_api_image_header_t;
typedef uint8_t boot_api_sha256_t[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
typedef struct {
/* Extension header type:
* BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB or
* BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB
* BOOT_API_PADDING_HEADER_MAGIC_NB
*/
uint32_t type;
/* Extension header len in byte */
uint32_t len;
/* parameters of this extension */
uint8_t params[];
} __packed boot_extension_header_t;
typedef struct {
/* Idx of ECDSA public key to be used in table */
uint32_t pk_idx;
/* Number of ECDSA public key in table */
uint32_t nb_pk;
/*
* Type of ECC algorithm to use :
* value 1 : for P-256 NIST algorithm
* value 2 : for Brainpool 256 algorithm
* See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
*/
uint32_t ecc_algo_type;
/* ECDSA public key to be used to check signature. */
uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
/* table of Hash of Algo+ECDSA public key */
boot_api_sha256_t pk_hashes[];
} __packed boot_ext_header_params_authentication_t;
typedef struct {
/* Size of encryption key (128 or 256) */
uint32_t key_size;
uint32_t derivation_cont;
/* 128 msb bits of plain payload SHA256 */
uint32_t hash[4];
} __packed boot_ext_header_params_encrypted_fsbl_t;
#endif /* BOOT_API_H */
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_DEF_FIP_UUID_H
#define PLAT_DEF_FIP_UUID_H
#define UUID_STM32MP_CONFIG_CERT \
{{0x50, 0x1d, 0x8d, 0xd2}, {0x8b, 0xce}, {0x49, 0xa5}, 0x84, 0xeb, \
{0x55, 0x9a, 0x9f, 0x2e, 0xae, 0xaf} }
#endif /* PLAT_DEF_FIP_UUID_H */
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef STM32MP1_IMG_DEF_H
#define STM32MP1_IMG_DEF_H
#include <export/common/tbbr/tbbr_img_def_exp.h>
/* Undef the existing values */
#undef BL32_EXTRA1_IMAGE_ID
#undef BL32_EXTRA2_IMAGE_ID
#undef TOS_FW_CONFIG_ID
#undef TRUSTED_BOOT_FW_CERT_ID
#undef FWU_METADATA_IMAGE_ID
#undef BKUP_FWU_METADATA_IMAGE_ID
#undef FW_CONFIG_ID
#undef HW_CONFIG_ID
#undef GPT_IMAGE_ID
#undef ENC_IMAGE_ID
/* Define the STM32MP1 used ID */
#define FW_CONFIG_ID U(1)
#define HW_CONFIG_ID U(2)
#define GPT_IMAGE_ID U(3)
#define ENC_IMAGE_ID U(6)
#define BL32_EXTRA1_IMAGE_ID U(8)
#define BL32_EXTRA2_IMAGE_ID U(9)
#define FWU_METADATA_IMAGE_ID U(12)
#define BKUP_FWU_METADATA_IMAGE_ID U(13)
#define TOS_FW_CONFIG_ID U(16)
#define STM32MP_CONFIG_CERT_ID U(17)
/* Increase the MAX_NUMBER_IDS to match the authentication pool required */
#define MAX_NUMBER_IDS U(19)
#endif /* STM32MP1_IMG_DEF_H */
@@ -0,0 +1,218 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLATFORM_DEF_H
#define PLATFORM_DEF_H
#include <arch.h>
#include <drivers/arm/gic_common.h>
#include <lib/utils_def.h>
#include <plat/common/common_def.h>
#include "../stm32mp1_def.h"
/*******************************************************************************
* Generic platform constants
******************************************************************************/
/* Size of cacheable stacks */
#if defined(IMAGE_BL32)
#define PLATFORM_STACK_SIZE 0x600
#else
#define PLATFORM_STACK_SIZE 0xC00
#endif
#define FIP_IMAGE_NAME "fip"
#define METADATA_PART_1 "metadata1"
#define METADATA_PART_2 "metadata2"
#define STM32MP_PRIMARY_CPU U(0x0)
#define STM32MP_SECONDARY_CPU U(0x1)
#define PLATFORM_CLUSTER_COUNT U(1)
#define PLATFORM_CLUSTER0_CORE_COUNT U(2)
#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
PLATFORM_CLUSTER0_CORE_COUNT)
#define PLATFORM_MAX_CPUS_PER_CLUSTER 2
#define MAX_IO_DEVICES U(4)
#define MAX_IO_HANDLES U(4)
#define MAX_IO_BLOCK_DEVICES U(1)
#define MAX_IO_MTD_DEVICES U(1)
/*******************************************************************************
* BL2 specific defines.
******************************************************************************/
/*
* Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
* size plus a little space for growth.
*/
#define BL2_BASE STM32MP_BL2_BASE
#define BL2_LIMIT (STM32MP_BL2_BASE + \
STM32MP_BL2_SIZE)
#define BL2_RO_BASE STM32MP_BL2_RO_BASE
#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \
STM32MP_BL2_RO_SIZE)
#define BL2_RW_BASE STM32MP_BL2_RW_BASE
#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \
STM32MP_BL2_RW_SIZE)
/*******************************************************************************
* BL32 specific defines.
******************************************************************************/
#if defined(IMAGE_BL32)
#if ENABLE_PIE
#define BL32_BASE 0
#define BL32_LIMIT STM32MP_BL32_SIZE
#else
#define BL32_BASE STM32MP_BL32_BASE
#define BL32_LIMIT (STM32MP_BL32_BASE + \
STM32MP_BL32_SIZE)
#endif
#endif /* defined(IMAGE_BL32) */
/*******************************************************************************
* BL33 specific defines.
******************************************************************************/
#define BL33_BASE STM32MP_BL33_BASE
/*
* Load address of BL33 for this platform port
*/
#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE
/* Needed by STM32CubeProgrammer support */
#define DWL_BUFFER_SIZE U(0x01000000)
/*
* SSBL offset in case it's stored in eMMC boot partition.
* We can fix it to 256K because TF-A size can't be bigger than SRAM
*/
#define PLAT_EMMC_BOOT_SSBL_OFFSET U(0x40000)
/*******************************************************************************
* DTB specific defines.
******************************************************************************/
#define DTB_BASE STM32MP_DTB_BASE
#define DTB_LIMIT (STM32MP_DTB_BASE + \
STM32MP_DTB_SIZE)
/*******************************************************************************
* Platform specific page table and MMU setup constants
******************************************************************************/
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
/*******************************************************************************
* Declarations and constants to access the mailboxes safely. Each mailbox is
* aligned on the biggest cache line size in the platform. This is known only
* to the platform as it might have a combination of integrated and external
* caches. Such alignment ensures that two maiboxes do not sit on the same cache
* line at any cache level. They could belong to different cpus/clusters &
* get written while being protected by different locks causing corruption of
* a valid mailbox address.
******************************************************************************/
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
/*
* Secure Interrupt: based on the standard ARM mapping
*/
#define ARM_IRQ_SEC_PHY_TIMER U(29)
#define ARM_IRQ_SEC_SGI_0 U(8)
#define ARM_IRQ_SEC_SGI_1 U(9)
#define ARM_IRQ_SEC_SGI_2 U(10)
#define ARM_IRQ_SEC_SGI_3 U(11)
#define ARM_IRQ_SEC_SGI_4 U(12)
#define ARM_IRQ_SEC_SGI_5 U(13)
#define ARM_IRQ_SEC_SGI_6 U(14)
#define ARM_IRQ_SEC_SGI_7 U(15)
#define STM32MP1_IRQ_TZC400 U(36)
#define STM32MP1_IRQ_TAMPSERRS U(229)
#define STM32MP1_IRQ_AXIERRIRQ U(244)
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
* terminology. On a GICv2 system or mode, the lists will be merged and treated
* as Group 0 interrupts.
*/
#define PLATFORM_G1S_PROPS(grp) \
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(STM32MP1_IRQ_TZC400, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE)
#define PLATFORM_G0_PROPS(grp) \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE), \
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_EDGE)
/*
* Power
*/
#define PLAT_MAX_PWR_LVL U(1)
/* Local power state for power domains in Run state. */
#define ARM_LOCAL_STATE_RUN U(0)
/* Local power state for retention. Valid only for CPU power domains */
#define ARM_LOCAL_STATE_RET U(1)
/* Local power state for power-down. Valid for CPU and cluster power domains */
#define ARM_LOCAL_STATE_OFF U(2)
/*
* This macro defines the deepest retention state possible.
* A higher state id will represent an invalid or a power down state.
*/
#define PLAT_MAX_RET_STATE ARM_LOCAL_STATE_RET
/*
* This macro defines the deepest power down states possible. Any state ID
* higher than this is invalid.
*/
#define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF
/*******************************************************************************
* Size of the per-cpu data in bytes that should be reserved in the generic
* per-cpu data structure for the FVP port.
******************************************************************************/
#define PLAT_PCPU_DATA_SIZE 2
/*******************************************************************************
* Number of parallel entry slots in SMT SCMI server entry context. For this
* platform, SCMI server is reached through SMC only, hence the number of
* entry slots.
******************************************************************************/
#define PLAT_SMT_ENTRY_COUNT PLATFORM_CORE_COUNT
#endif /* PLATFORM_DEF_H */
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_DBGMCU_H
#define STM32MP1_DBGMCU_H
#include <stdint.h>
/* Get chip version and ID from DBGMCU registers */
int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version);
int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id);
#endif /* STM32MP1_DBGMCU_H */
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H
/*
* Key algorithms currently supported on mbed TLS libraries
*/
#define TF_MBEDTLS_USE_RSA 0
#define TF_MBEDTLS_USE_ECDSA 1
/*
* Hash algorithms currently supported on mbed TLS libraries
*/
#define TF_MBEDTLS_SHA256 1
#define TF_MBEDTLS_SHA384 2
#define TF_MBEDTLS_SHA512 3
/*
* Configuration file to build mbed TLS with the required features for
* Trusted Boot
*/
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
#define MBEDTLS_X509_CHECK_KEY_USAGE
#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_BASE64_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_ERROR_C
#define MBEDTLS_MD_C
#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_PLATFORM_C
#if TF_MBEDTLS_USE_ECDSA
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_NO_INTERNAL_RNG
#endif
#if TF_MBEDTLS_USE_RSA
#define MBEDTLS_RSA_C
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
#endif
#define MBEDTLS_SHA256_C
#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256)
#define MBEDTLS_SHA512_C
#endif
#define MBEDTLS_VERSION_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
#if TF_MBEDTLS_USE_AES_GCM
#define MBEDTLS_AES_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_GCM_C
#endif
/* MPI / BIGNUM options */
#define MBEDTLS_MPI_WINDOW_SIZE 2
#if TF_MBEDTLS_USE_RSA
#if TF_MBEDTLS_KEY_SIZE <= 2048
#define MBEDTLS_MPI_MAX_SIZE 256
#else
#define MBEDTLS_MPI_MAX_SIZE 512
#endif
#else
#define MBEDTLS_MPI_MAX_SIZE 256
#endif
/* Memory buffer allocator options */
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8
/*
* Prevent the use of 128-bit division which
* creates dependency on external libraries.
*/
#define MBEDTLS_NO_UDBL_DIVISION
#ifndef __ASSEMBLER__
/* System headers required to build mbed TLS with the current configuration */
#include <stdlib.h>
#include <mbedtls/check_config.h>
#endif
/*
* Mbed TLS heap size is smal as we only use the asn1
* parsing functions
* digest, signature and crypto algorithm are done by
* other library.
*/
#define TF_MBEDTLS_HEAP_SIZE U(5120)
#endif /* MBEDTLS_CONFIG_H */
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_PRIVATE_H
#define STM32MP1_PRIVATE_H
#include <stdint.h>
void configure_mmu(void);
void stm32mp1_arch_security_setup(void);
void stm32mp1_security_setup(void);
void stm32mp1_gic_pcpu_init(void);
void stm32mp1_gic_init(void);
void stm32mp1_syscfg_init(void);
void stm32mp1_syscfg_enable_io_compensation_start(void);
void stm32mp1_syscfg_enable_io_compensation_finish(void);
void stm32mp1_syscfg_disable_io_compensation(void);
uint32_t stm32mp1_syscfg_get_chip_version(void);
uint32_t stm32mp1_syscfg_get_chip_dev_id(void);
#if STM32MP13
void stm32mp1_syscfg_boot_mode_enable(void);
void stm32mp1_syscfg_boot_mode_disable(void);
#endif
#if STM32MP15
static inline void stm32mp1_syscfg_boot_mode_enable(void){}
static inline void stm32mp1_syscfg_boot_mode_disable(void){}
#endif
void stm32mp1_deconfigure_uart_pins(void);
void stm32mp1_init_scmi_server(void);
#endif /* STM32MP1_PRIVATE_H */
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_SHARED_RESOURCES_H
#define STM32MP1_SHARED_RESOURCES_H
#include <stm32mp_shared_resources.h>
#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i))
enum stm32mp_shres {
STM32MP1_SHRES_CRYP1,
STM32MP1_SHRES_GPIOZ_0,
STM32MP1_SHRES_GPIOZ_1,
STM32MP1_SHRES_GPIOZ_2,
STM32MP1_SHRES_GPIOZ_3,
STM32MP1_SHRES_GPIOZ_4,
STM32MP1_SHRES_GPIOZ_5,
STM32MP1_SHRES_GPIOZ_6,
STM32MP1_SHRES_GPIOZ_7,
STM32MP1_SHRES_HASH1,
STM32MP1_SHRES_I2C4,
STM32MP1_SHRES_I2C6,
STM32MP1_SHRES_IWDG1,
STM32MP1_SHRES_MCU,
STM32MP1_SHRES_MDMA,
STM32MP1_SHRES_PLL3,
STM32MP1_SHRES_RNG1,
STM32MP1_SHRES_RTC,
STM32MP1_SHRES_SPI6,
STM32MP1_SHRES_USART1,
STM32MP1_SHRES_COUNT
};
#endif /* STM32MP1_SHARED_RESOURCES_H */
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_SMC_H
#define STM32MP1_SMC_H
/*
* 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)
* https://developer.arm.com/docs/den0028/latest
*/
/* Secure Service access from Non-secure */
/*
* STM32_SMC_BSEC call API
*
* Argument a0: (input) SMCC ID
* (output) status return code
* Argument a1: (input) Service ID (STM32_SMC_BSEC_xxx)
* Argument a2: (input) OTP index
* (output) OTP read value, if applicable
* Argument a3: (input) OTP value if applicable
*/
#define STM32_SMC_BSEC 0x82001003
/*
* STM32_SIP_SMC_SCMI_AGENT0
* STM32_SIP_SMC_SCMI_AGENT1
* Process SCMI message pending in SCMI shared memory buffer.
*
* Argument a0: (input) SMCC ID
*/
#define STM32_SIP_SMC_SCMI_AGENT0 0x82002000
#define STM32_SIP_SMC_SCMI_AGENT1 0x82002001
/* SMC function IDs for SiP Service queries */
#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
#define STM32_SIP_SVC_UID 0x8200ff01
/* 0x8200ff02 is reserved */
#define STM32_SIP_SVC_VERSION 0x8200ff03
/* STM32 SiP Service Calls version numbers */
#define STM32_SIP_SVC_VERSION_MAJOR 0x0
#define STM32_SIP_SVC_VERSION_MINOR 0x1
/* Number of STM32 SiP Calls implemented */
#define STM32_COMMON_SIP_NUM_CALLS 3
/* Service for BSEC */
#define STM32_SMC_READ_SHADOW 0x01
#define STM32_SMC_PROG_OTP 0x02
#define STM32_SMC_WRITE_SHADOW 0x03
#define STM32_SMC_READ_OTP 0x04
/* SMC error codes */
#define STM32_SMC_OK 0x00000000U
#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
#define STM32_SMC_FAILED 0xFFFFFFFEU
#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
#endif /* STM32MP1_SMC_H */
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_TBB_CERT_H
#define STM32MP1_TBB_CERT_H
#include <tbbr/tbb_cert.h>
/*
* Enumerate the certificates that are used to establish the chain of trust
*/
enum {
STM32MP_CONFIG_CERT = FWU_CERT + 1
};
#endif /* STM32MP1_TBB_CERT_H */
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/bl_common.h>
#include <common/desc_image_load.h>
#include <plat/common/platform.h>
#include <platform_def.h>
/*******************************************************************************
* Following descriptor provides BL image/ep information that gets used
* by BL2 to load the images and also subset of this information is
* passed to next BL image. The image loading sequence is managed by
* populating the images in required loading order. The image execution
* sequence is managed by populating the `next_handoff_image_id` with
* the next executable image id.
******************************************************************************/
static bl_mem_params_node_t bl2_mem_params_descs[] = {
/* Fill FW_CONFIG related information if it exists */
{
.image_id = FW_CONFIG_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
VERSION_2, entry_point_info_t,
SECURE | NON_EXECUTABLE),
SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
VERSION_2, image_info_t,
IMAGE_ATTRIB_PLAT_SETUP),
.image_info.image_base = STM32MP_FW_CONFIG_BASE,
.image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
.next_handoff_image_id = INVALID_IMAGE_ID,
},
/* Fill BL32 related information */
{
.image_id = BL32_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
SECURE | EXECUTABLE | EP_FIRST_EXE),
.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
SPSR_E_LITTLE,
DISABLE_ALL_EXCEPTIONS),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t,
IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = BL33_IMAGE_ID,
},
/* Fill BL32 external 1 image related information */
{
.image_id = BL32_EXTRA1_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
SECURE | NON_EXECUTABLE),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t,
IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
#if STM32MP15
/* Fill BL32 external 2 image related information */
{
.image_id = BL32_EXTRA2_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
SECURE | NON_EXECUTABLE),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t,
IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
#endif
/* Fill HW_CONFIG related information if it exists */
{
.image_id = HW_CONFIG_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
VERSION_2, entry_point_info_t,
NON_SECURE | NON_EXECUTABLE),
SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
VERSION_2, image_info_t,
IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
/* Fill TOS_FW_CONFIG related information if it exists */
{
.image_id = TOS_FW_CONFIG_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
VERSION_2, entry_point_info_t,
SECURE | NON_EXECUTABLE),
SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
VERSION_2, image_info_t,
IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = INVALID_IMAGE_ID,
},
/* Fill BL33 related information */
{
.image_id = BL33_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t,
NON_SECURE | EXECUTABLE),
.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
SPSR_E_LITTLE,
DISABLE_ALL_EXCEPTIONS),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t,
IMAGE_ATTRIB_SKIP_LOADING),
.next_handoff_image_id = INVALID_IMAGE_ID,
}
};
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <firmware_image_package.h>
#include "tbbr_config.h"
toc_entry_t plat_def_toc_entries[] = {
{
.name = "STM32MP CONFIG CERT",
.uuid = UUID_STM32MP_CONFIG_CERT,
.cmdline_name = "stm32mp-cfg-cert"
}
};
@@ -0,0 +1,25 @@
#
# Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
# Name of the platform defined source file name,
# which contains platform defined UUID entries populated
# in the plat_def_toc_entries[].
PLAT_DEF_UUID_FILE_NAME := plat_def_uuid_config
INCLUDE_PATHS += -I${PLAT_DIR}/include -I./
PLAT_DEF_UUID := yes
ifeq (${PLAT_DEF_UUID},yes)
HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
${PLAT_DEF_UUID_FILE_NAME}.o: ${PLAT_DIR}${PLAT_DEF_UUID_FILE_NAME}.c
${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o
endif
OBJECTS += ${PLAT_OBJECTS}
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/desc_image_load.h>
/*******************************************************************************
* This function flushes the data structures so that they are visible
* in memory for the next BL image.
******************************************************************************/
void plat_flush_next_bl_params(void)
{
flush_bl_params_desc();
}
/*******************************************************************************
* This function returns the list of loadable images.
******************************************************************************/
bl_load_info_t *plat_get_bl_image_load_info(void)
{
return get_bl_load_info_from_mem_params_desc();
}
/*******************************************************************************
* This function returns the list of executable images.
******************************************************************************/
bl_params_t *plat_get_next_bl_params(void)
{
bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc();
populate_next_bl_params_config(bl_params);
return bl_params;
}
@@ -0,0 +1,553 @@
#
# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
ARM_CORTEX_A7 := yes
ARM_WITH_NEON := yes
BL2_AT_EL3 := 1
USE_COHERENT_MEM := 0
STM32MP_EARLY_CONSOLE ?= 0
STM32MP_RECONFIGURE_CONSOLE ?= 0
STM32MP_UART_BAUDRATE ?= 115200
TRUSTED_BOARD_BOOT ?= 0
STM32MP_USE_EXTERNAL_HEAP ?= 0
# Use secure library from the ROM code for authentication
STM32MP_CRYPTO_ROM_LIB ?= 0
# Please don't increment this value without good understanding of
# the monotonic counter
STM32_TF_VERSION ?= 0
# Enable dynamic memory mapping
PLAT_XLAT_TABLES_DYNAMIC := 1
# Default Device tree
DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
STM32MP13 ?= 0
STM32MP15 ?= 0
ifeq ($(STM32MP13),1)
ifeq ($(STM32MP15),1)
$(error Cannot enable both flags STM32MP13 and STM32MP15)
endif
STM32MP13 := 1
STM32MP15 := 0
else ifeq ($(STM32MP15),1)
STM32MP13 := 0
STM32MP15 := 1
else ifneq ($(findstring stm32mp13,$(DTB_FILE_NAME)),)
STM32MP13 := 1
STM32MP15 := 0
else ifneq ($(findstring stm32mp15,$(DTB_FILE_NAME)),)
STM32MP13 := 0
STM32MP15 := 1
endif
ifeq ($(STM32MP13),1)
# Will use SRAM2 as mbedtls heap
STM32MP_USE_EXTERNAL_HEAP := 1
# DDR controller with single AXI port and 16-bit interface
STM32MP_DDR_DUAL_AXI_PORT:= 0
STM32MP_DDR_32BIT_INTERFACE:= 0
ifeq (${TRUSTED_BOARD_BOOT},1)
# PKA algo to include
PKA_USE_NIST_P256 := 1
PKA_USE_BRAINPOOL_P256T1:= 1
endif
# STM32 image header version v2.0
STM32_HEADER_VERSION_MAJOR:= 2
STM32_HEADER_VERSION_MINOR:= 0
endif
ifeq ($(STM32MP15),1)
# DDR controller with dual AXI port and 32-bit interface
STM32MP_DDR_DUAL_AXI_PORT:= 1
STM32MP_DDR_32BIT_INTERFACE:= 1
# STM32 image header version v1.0
STM32_HEADER_VERSION_MAJOR:= 1
STM32_HEADER_VERSION_MINOR:= 0
# Add OP-TEE reserved shared memory area in mapping
STM32MP15_OPTEE_RSV_SHM := 1
$(eval $(call add_defines,STM32MP15_OPTEE_RSV_SHM))
STM32MP_CRYPTO_ROM_LIB := 1
# Decryption support
ifneq ($(DECRYPTION_SUPPORT),none)
$(error "DECRYPTION_SUPPORT not supported on STM32MP15")
endif
endif
# STM32 image header binary type for BL2
STM32_HEADER_BL2_BINARY_TYPE:= 0x10
ifeq ($(AARCH32_SP),sp_min)
# Disable Neon support: sp_min runtime may conflict with non-secure world
TF_CFLAGS += -mfloat-abi=soft
endif
TF_CFLAGS += -Wsign-compare
TF_CFLAGS += -Wformat-signedness
# Not needed for Cortex-A7
WORKAROUND_CVE_2017_5715:= 0
WORKAROUND_CVE_2022_23960:= 0
# Number of TF-A copies in the device
STM32_TF_A_COPIES := 2
# PLAT_PARTITION_MAX_ENTRIES must take care of STM32_TF-A_COPIES and other partitions
# such as metadata (2) to find all the FIP partitions (default is 2).
PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 4)))
ifeq (${PSA_FWU_SUPPORT},1)
# Number of banks of updatable firmware
NR_OF_FW_BANKS := 2
NR_OF_IMAGES_IN_FW_BANK := 1
FWU_MAX_PART = $(shell echo $$(($(STM32_TF_A_COPIES) + 2 + $(NR_OF_FW_BANKS))))
ifeq ($(shell test $(FWU_MAX_PART) -gt $(PLAT_PARTITION_MAX_ENTRIES); echo $$?),0)
$(error "Required partition number is $(FWU_MAX_PART) where PLAT_PARTITION_MAX_ENTRIES is only \
$(PLAT_PARTITION_MAX_ENTRIES)")
endif
endif
ifeq ($(STM32MP13),1)
STM32_HASH_VER := 4
STM32_RNG_VER := 4
else # Assuming STM32MP15
STM32_HASH_VER := 2
STM32_RNG_VER := 2
endif
# Boot devices
STM32MP_EMMC ?= 0
STM32MP_SDMMC ?= 0
STM32MP_RAW_NAND ?= 0
STM32MP_SPI_NAND ?= 0
STM32MP_SPI_NOR ?= 0
STM32MP_EMMC_BOOT ?= 0
# Serial boot devices
STM32MP_USB_PROGRAMMER ?= 0
STM32MP_UART_PROGRAMMER ?= 0
# Download load address for serial boot devices
DWL_BUFFER_BASE ?= 0xC7000000
# Device tree
ifeq ($(STM32MP13),1)
BL2_DTSI := stm32mp13-bl2.dtsi
FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
else
BL2_DTSI := stm32mp15-bl2.dtsi
FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
ifeq ($(AARCH32_SP),sp_min)
BL32_DTSI := stm32mp15-bl32.dtsi
FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
endif
endif
$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g" | grep -o "[0-9]*")))
DTC_CPPFLAGS += ${INCLUDES}
DTC_FLAGS += -Wno-unit_address_vs_reg
ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0)
DTC_FLAGS += -Wno-interrupt_provider
endif
# Macros and rules to build TF binary
STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
STM32_TF_LINKERFILE := ${BUILD_PLAT}/stm32mp1.ld
ASFLAGS += -DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\"
ifeq ($(AARCH32_SP),sp_min)
# BL32 is built only if using SP_MIN
BL32_DEP := bl32
ASFLAGS += -DBL32_BIN_PATH=\"${BUILD_PLAT}/bl32.bin\"
endif
# Variables for use with stm32image
STM32IMAGEPATH ?= tools/stm32image
STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c
FIP_DEPS += dtbs
STM32MP_HW_CONFIG := ${BL33_CFG}
STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
ifneq (${AARCH32_SP},none)
FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
endif
# Add the FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
# Add the HW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
ifeq ($(GENERATE_COT),1)
STM32MP_CFG_CERT := $(BUILD_PLAT)/stm32mp_cfg_cert.crt
# Add the STM32MP_CFG_CERT to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_CFG_CERT},--stm32mp-cfg-cert))
endif
ifeq ($(AARCH32_SP),sp_min)
STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
else
# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
# in the FIP if the platform requires.
ifneq ($(BL32_EXTRA1),)
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
endif
ifneq ($(BL32_EXTRA2),)
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
endif
endif
# Enable flags for C files
$(eval $(call assert_booleans,\
$(sort \
PKA_USE_BRAINPOOL_P256T1 \
PKA_USE_NIST_P256 \
PLAT_TBBR_IMG_DEF \
PLAT_XLAT_TABLES_DYNAMIC \
STM32MP_CRYPTO_ROM_LIB \
STM32MP_DDR_32BIT_INTERFACE \
STM32MP_DDR_DUAL_AXI_PORT \
STM32MP_EARLY_CONSOLE \
STM32MP_EMMC \
STM32MP_EMMC_BOOT \
STM32MP_RAW_NAND \
STM32MP_RECONFIGURE_CONSOLE \
STM32MP_SDMMC \
STM32MP_SPI_NAND \
STM32MP_SPI_NOR \
STM32MP_UART_PROGRAMMER \
STM32MP_USB_PROGRAMMER \
STM32MP_USE_EXTERNAL_HEAP \
STM32MP13 \
STM32MP15 \
)))
$(eval $(call assert_numerics,\
$(sort \
PLAT_PARTITION_MAX_ENTRIES \
STM32_HASH_VER \
STM32_HEADER_VERSION_MAJOR \
STM32_RNG_VER \
STM32_TF_A_COPIES \
STM32_TF_VERSION \
STM32MP_UART_BAUDRATE \
)))
$(eval $(call add_defines,\
$(sort \
DWL_BUFFER_BASE \
PKA_USE_BRAINPOOL_P256T1 \
PKA_USE_NIST_P256 \
PLAT_PARTITION_MAX_ENTRIES \
PLAT_TBBR_IMG_DEF \
PLAT_XLAT_TABLES_DYNAMIC \
STM32_HASH_VER \
STM32_HEADER_VERSION_MAJOR \
STM32_RNG_VER \
STM32_TF_A_COPIES \
STM32_TF_VERSION \
STM32MP_CRYPTO_ROM_LIB \
STM32MP_DDR_32BIT_INTERFACE \
STM32MP_DDR_DUAL_AXI_PORT \
STM32MP_EARLY_CONSOLE \
STM32MP_EMMC \
STM32MP_EMMC_BOOT \
STM32MP_RAW_NAND \
STM32MP_RECONFIGURE_CONSOLE \
STM32MP_SDMMC \
STM32MP_SPI_NAND \
STM32MP_SPI_NOR \
STM32MP_UART_BAUDRATE \
STM32MP_UART_PROGRAMMER \
STM32MP_USB_PROGRAMMER \
STM32MP_USE_EXTERNAL_HEAP \
STM32MP13 \
STM32MP15 \
)))
# Include paths and source files
PLAT_INCLUDES := -Iplat/st/common/include/
PLAT_INCLUDES += -Iplat/st/stm32mp1/include/
include lib/fconf/fconf.mk
include lib/libfdt/libfdt.mk
PLAT_BL_COMMON_SOURCES := common/uuid.c \
plat/st/common/stm32mp_common.c \
plat/st/stm32mp1/stm32mp1_private.c
PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S
ifneq (${ENABLE_STACK_PROTECTOR},0)
PLAT_BL_COMMON_SOURCES += plat/st/stm32mp1/stm32mp1_stack_protector.c
endif
include lib/xlat_tables_v2/xlat_tables.mk
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S
PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \
drivers/clk/clk.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/st/bsec/bsec2.c \
drivers/st/clk/stm32mp_clkfunc.c \
drivers/st/ddr/stm32mp_ddr.c \
drivers/st/ddr/stm32mp1_ddr_helpers.c \
drivers/st/gpio/stm32_gpio.c \
drivers/st/i2c/stm32_i2c.c \
drivers/st/iwdg/stm32_iwdg.c \
drivers/st/pmic/stm32mp_pmic.c \
drivers/st/pmic/stpmic1.c \
drivers/st/regulator/regulator_core.c \
drivers/st/regulator/regulator_fixed.c \
drivers/st/reset/stm32mp1_reset.c \
plat/st/common/stm32mp_dt.c \
plat/st/stm32mp1/stm32mp1_dbgmcu.c \
plat/st/stm32mp1/stm32mp1_helper.S \
plat/st/stm32mp1/stm32mp1_syscfg.c
ifeq ($(STM32MP13),1)
PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \
drivers/st/clk/clk-stm32mp13.c \
drivers/st/crypto/stm32_rng.c
else
PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c
endif
BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
BL2_SOURCES += drivers/io/io_fip.c \
plat/st/common/bl2_io_storage.c \
plat/st/common/stm32mp_fconf_io.c \
plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
plat/st/stm32mp1/stm32mp1_fconf_firewall.c
include lib/zlib/zlib.mk
ifeq (${PSA_FWU_SUPPORT},1)
include drivers/fwu/fwu.mk
endif
BL2_SOURCES += $(ZLIB_SOURCES)
BL2_SOURCES += drivers/io/io_block.c \
drivers/io/io_mtd.c \
drivers/io/io_storage.c \
drivers/st/crypto/stm32_hash.c \
plat/st/stm32mp1/bl2_plat_setup.c
ifneq (${DECRYPTION_SUPPORT},none)
BL2_SOURCES += drivers/io/io_encrypted.c
endif
ifeq (${TRUSTED_BOARD_BOOT},1)
AUTH_SOURCES := drivers/auth/auth_mod.c \
drivers/auth/crypto_mod.c \
drivers/auth/img_parser_mod.c
ifeq (${GENERATE_COT},1)
TFW_NVCTR_VAL := 0
NTFW_NVCTR_VAL := 0
KEY_SIZE :=
KEY_ALG := ecdsa
HASH_ALG := sha256
ifeq (${SAVE_KEYS},1)
TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/trusted.pem
NON_TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/non-trusted.pem
BL32_KEY ?= ${BUILD_PLAT}/trusted_os.pem
BL33_KEY ?= ${BUILD_PLAT}/non-trusted_os.pem
endif
endif
TF_MBEDTLS_KEY_ALG := ecdsa
MBEDTLS_CONFIG_FILE ?= "<stm32mp1_mbedtls_config.h>"
include drivers/auth/mbedtls/mbedtls_x509.mk
COT_DESC_IN_DTB := 1
AUTH_SOURCES += lib/fconf/fconf_cot_getter.c \
lib/fconf/fconf_tbbr_getter.c \
plat/st/common/stm32mp_crypto_lib.c
ifeq ($(STM32MP13),1)
AUTH_SOURCES += drivers/st/crypto/stm32_pka.c
AUTH_SOURCES += drivers/st/crypto/stm32_saes.c
endif
BL2_SOURCES += $(AUTH_SOURCES) \
plat/st/common/stm32mp_trusted_boot.c
endif
ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
BL2_SOURCES += drivers/mmc/mmc.c \
drivers/partition/gpt.c \
drivers/partition/partition.c \
drivers/st/io/io_mmc.c \
drivers/st/mmc/stm32_sdmmc2.c
endif
ifeq (${STM32MP_RAW_NAND},1)
$(eval $(call add_define_val,NAND_ONFI_DETECT,1))
BL2_SOURCES += drivers/mtd/nand/raw_nand.c \
drivers/st/fmc/stm32_fmc2_nand.c
endif
ifeq (${STM32MP_SPI_NAND},1)
BL2_SOURCES += drivers/mtd/nand/spi_nand.c
endif
ifeq (${STM32MP_SPI_NOR},1)
ifneq (${STM32MP_FORCE_MTD_START_OFFSET},)
$(eval $(call add_define_val,STM32MP_NOR_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET}))
endif
BL2_SOURCES += drivers/mtd/nor/spi_nor.c
endif
ifneq ($(filter 1,${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
BL2_SOURCES += drivers/mtd/spi-mem/spi_mem.c \
drivers/st/spi/stm32_qspi.c
endif
ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),)
ifneq (${STM32MP_FORCE_MTD_START_OFFSET},)
$(eval $(call add_define_val,STM32MP_NAND_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET}))
endif
BL2_SOURCES += drivers/mtd/nand/core.c
endif
ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
BL2_SOURCES += plat/st/stm32mp1/stm32mp1_boot_device.c
endif
ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),)
BL2_SOURCES += drivers/io/io_memmap.c
endif
ifeq (${STM32MP_UART_PROGRAMMER},1)
BL2_SOURCES += drivers/st/uart/stm32_uart.c \
plat/st/common/stm32cubeprogrammer_uart.c
endif
ifeq (${STM32MP_USB_PROGRAMMER},1)
#The DFU stack uses only one end point, reduce the USB stack footprint
$(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U))
BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \
drivers/usb/usb_device.c \
plat/st/common/stm32cubeprogrammer_usb.c \
plat/st/common/usb_dfu.c \
plat/st/stm32mp1/stm32mp1_usb_dfu.c
endif
BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \
drivers/st/ddr/stm32mp_ram.c \
drivers/st/ddr/stm32mp1_ddr.c \
drivers/st/ddr/stm32mp1_ram.c
BL2_SOURCES += common/desc_image_load.c \
plat/st/stm32mp1/plat_image_load.c
BL2_SOURCES += lib/optee/optee_utils.c
# Compilation rules
.PHONY: check_dtc_version stm32image clean_stm32image check_boot_device
.SUFFIXES:
all: check_dtc_version stm32image ${STM32_TF_STM32}
distclean realclean clean: clean_stm32image
bl2: check_boot_device
check_boot_device:
@if [ ${STM32MP_EMMC} != 1 ] && \
[ ${STM32MP_SDMMC} != 1 ] && \
[ ${STM32MP_RAW_NAND} != 1 ] && \
[ ${STM32MP_SPI_NAND} != 1 ] && \
[ ${STM32MP_SPI_NOR} != 1 ] && \
[ ${STM32MP_UART_PROGRAMMER} != 1 ] && \
[ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \
echo "No boot device driver is enabled"; \
false; \
fi
stm32image: ${STM32IMAGE}
${STM32IMAGE}: ${STM32IMAGE_SRC}
${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH}
clean_stm32image:
${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean
check_dtc_version:
@if [ ${DTC_VERSION} -lt 10404 ]; then \
echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \
false; \
fi
# Create DTB file for BL2
${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
@echo '#include "${BL2_DTSI}"' >> $@
${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts
ifeq ($(AARCH32_SP),sp_min)
# Create DTB file for BL32
${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
@echo '#include "${BL32_DTSI}"' >> $@
${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
endif
${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2
@echo " AS stm32mp1.S"
${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
-DDTB_BIN_PATH=\"$<\" \
-c plat/st/stm32mp1/stm32mp1.S -o $@
$(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,bl2))
tf-a-%.elf: stm32mp1-%.o ${STM32_TF_LINKERFILE}
@echo " LDS $<"
${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
tf-a-%.bin: tf-a-%.elf
${Q}${OC} -O binary $< $@
@echo
@echo "Built $@ successfully"
@echo
tf-a-%.stm32: ${STM32IMAGE} tf-a-%.bin
@echo
@echo "Generate $@"
$(eval LOADADDR = $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}'))
$(eval ENTRY = $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
${Q}${STM32IMAGE} -s $(word 2,$^) -d $@ \
-l $(LOADADDR) -e ${ENTRY} \
-v ${STM32_TF_VERSION} \
-m ${STM32_HEADER_VERSION_MAJOR} \
-n ${STM32_HEADER_VERSION_MINOR} \
-b ${STM32_HEADER_BL2_BINARY_TYPE}
@echo
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <common/debug.h>
#include <drivers/st/bsec.h>
#include <drivers/st/bsec2_reg.h>
#include <stm32mp1_smc.h>
#include "bsec_svc.h"
uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
uint32_t *ret_otp_value)
{
uint32_t result;
uint32_t tmp_data = 0U;
switch (x1) {
case STM32_SMC_READ_SHADOW:
result = bsec_read_otp(ret_otp_value, x2);
break;
case STM32_SMC_PROG_OTP:
*ret_otp_value = 0U;
result = bsec_program_otp(x3, x2);
break;
case STM32_SMC_WRITE_SHADOW:
*ret_otp_value = 0U;
result = bsec_write_otp(x3, x2);
break;
case STM32_SMC_READ_OTP:
*ret_otp_value = 0U;
result = bsec_read_otp(&tmp_data, x2);
if (result != BSEC_OK) {
break;
}
result = bsec_shadow_register(x2);
if (result != BSEC_OK) {
break;
}
result = bsec_read_otp(ret_otp_value, x2);
if (result != BSEC_OK) {
break;
}
result = bsec_write_otp(tmp_data, x2);
break;
default:
return STM32_SMC_INVALID_PARAMS;
}
return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED;
}
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BSEC_SVC_H
#define BSEC_SVC_H
#include <stdint.h>
/* version of this service */
/* must be increase at each structure modification */
#define BSEC_SERVICE_VERSION 0x01U
uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
uint32_t *ret_otp_value);
#endif /* BSEC_SVC_H */
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdbool.h>
#include <stdint.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <drivers/scmi-msg.h>
#include <lib/psci/psci.h>
#include <tools_share/uuid.h>
#include <stm32mp1_smc.h>
#include "bsec_svc.h"
/* STM32 SiP Service UUID */
DEFINE_SVC_UUID2(stm32_sip_svc_uid,
0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e,
0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14);
/* Setup STM32MP1 Standard Services */
static int32_t stm32mp1_svc_setup(void)
{
/*
* PSCI is the only specification implemented as a Standard Service.
* Invoke PSCI setup from here.
*/
return 0;
}
/*
* Top-level Standard Service SMC handler. This handler will in turn dispatch
* calls to PSCI SMC handler.
*/
static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
u_register_t x2, u_register_t x3,
u_register_t x4, void *cookie,
void *handle, u_register_t flags)
{
uint32_t ret1 = 0U, ret2 = 0U;
bool ret_uid = false, ret2_enabled = false;
switch (smc_fid) {
case STM32_SIP_SVC_CALL_COUNT:
ret1 = STM32_COMMON_SIP_NUM_CALLS;
break;
case STM32_SIP_SVC_UID:
/* Return UUID to the caller */
ret_uid = true;
break;
case STM32_SIP_SVC_VERSION:
/* Return the version of current implementation */
ret1 = STM32_SIP_SVC_VERSION_MAJOR;
ret2 = STM32_SIP_SVC_VERSION_MINOR;
ret2_enabled = true;
break;
case STM32_SMC_BSEC:
ret1 = bsec_main(x1, x2, x3, &ret2);
ret2_enabled = true;
break;
case STM32_SIP_SMC_SCMI_AGENT0:
scmi_smt_fastcall_smc_entry(0);
break;
case STM32_SIP_SMC_SCMI_AGENT1:
scmi_smt_fastcall_smc_entry(1);
break;
default:
WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
ret1 = STM32_SMC_NOT_SUPPORTED;
break;
}
if (ret_uid) {
SMC_UUID_RET(handle, stm32_sip_svc_uid);
}
if (ret2_enabled) {
SMC_RET2(handle, ret1, ret2);
}
SMC_RET1(handle, ret1);
}
/* Register Standard Service Calls as runtime service */
DECLARE_RT_SVC(stm32mp1_sip_svc,
OEN_SIP_START,
OEN_SIP_END,
SMC_TYPE_FAST,
stm32mp1_svc_setup,
stm32mp1_svc_smc_handler
);
@@ -0,0 +1,53 @@
#
# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifeq ($(STM32MP13),1)
$(error "SP_min is not supported on STM32MP13 platform")
endif
SP_MIN_WITH_SECURE_FIQ := 1
override ENABLE_PIE := 1
BL32_CFLAGS += -fpie -DENABLE_PIE
BL32_LDFLAGS += $(PIE_LDFLAGS)
BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES
BL32_SOURCES += drivers/st/etzpc/etzpc.c \
plat/common/aarch32/platform_mp_stack.S \
plat/st/stm32mp1/sp_min/sp_min_setup.c \
plat/st/stm32mp1/stm32mp1_pm.c \
plat/st/stm32mp1/stm32mp1_shared_resources.c \
plat/st/stm32mp1/stm32mp1_topology.c
# FDT wrappers
include common/fdt_wrappers.mk
BL32_SOURCES += ${FDT_WRAPPERS_SOURCES}
# Generic GIC v2
include drivers/arm/gic/v2/gicv2.mk
BL32_SOURCES += ${GICV2_SOURCES} \
plat/common/plat_gicv2.c \
plat/st/stm32mp1/stm32mp1_gic.c
# Generic PSCI
BL32_SOURCES += plat/common/plat_psci_common.c
# SCMI server drivers
BL32_SOURCES += drivers/scmi-msg/base.c \
drivers/scmi-msg/clock.c \
drivers/scmi-msg/entry.c \
drivers/scmi-msg/reset_domain.c \
drivers/scmi-msg/smt.c
# stm32mp1 specific services
BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
plat/st/stm32mp1/services/stm32mp1_svc_setup.c \
plat/st/stm32mp1/stm32mp1_scmi.c
# Arm Archtecture services
BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c
@@ -0,0 +1,197 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <context.h>
#include <drivers/arm/gicv2.h>
#include <drivers/arm/tzc400.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/st/bsec.h>
#include <drivers/st/etzpc.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_iwdg.h>
#include <drivers/st/stm32mp1_clk.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <platform_sp_min.h>
/******************************************************************************
* Placeholder variables for copying the arguments that have been passed to
* BL32 from BL2.
******************************************************************************/
static entry_point_info_t bl33_image_ep_info;
/*******************************************************************************
* Interrupt handler for FIQ (secure IRQ)
******************************************************************************/
void sp_min_plat_fiq_handler(uint32_t id)
{
(void)plat_crash_console_init();
switch (id & INT_ID_MASK) {
case STM32MP1_IRQ_TZC400:
tzc400_init(STM32MP1_TZC_BASE);
(void)tzc400_it_handler();
panic();
break;
case STM32MP1_IRQ_AXIERRIRQ:
ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n");
panic();
break;
default:
ERROR("SECURE IT handler not define for it : %u\n", id);
break;
}
}
/*******************************************************************************
* Return a pointer to the 'entry_point_info' structure of the next image for
* the security state specified. BL33 corresponds to the non-secure image type
* while BL32 corresponds to the secure image type. A NULL pointer is returned
* if the image does not exist.
******************************************************************************/
entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
{
entry_point_info_t *next_image_info;
next_image_info = &bl33_image_ep_info;
if (next_image_info->pc == 0U) {
return NULL;
}
return next_image_info;
}
CASSERT((STM32MP_SEC_SYSRAM_BASE == STM32MP_SYSRAM_BASE) &&
((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <=
(STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
assert_secure_sysram_fits_at_begining_of_sysram);
#ifdef STM32MP_NS_SYSRAM_BASE
CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) &&
((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) ==
(STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
assert_non_secure_sysram_fits_at_end_of_sysram);
CASSERT((STM32MP_NS_SYSRAM_BASE & (PAGE_SIZE_4KB - U(1))) == 0U,
assert_non_secure_sysram_base_is_4kbyte_aligned);
#define TZMA1_SECURE_RANGE \
(((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> FOUR_KB_SHIFT) - 1U)
#else
#define TZMA1_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
#endif /* STM32MP_NS_SYSRAM_BASE */
#define TZMA0_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
static void stm32mp1_etzpc_early_setup(void)
{
if (etzpc_init() != 0) {
panic();
}
etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
}
/*******************************************************************************
* Perform any BL32 specific platform actions.
******************************************************************************/
void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
uintptr_t dt_addr = arg1;
stm32mp_setup_early_console();
/* Imprecise aborts can be masked in NonSecure */
write_scr(read_scr() | SCR_AW_BIT);
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
BL_CODE_END - BL_CODE_BASE,
MT_CODE | MT_SECURE);
configure_mmu();
assert(params_from_bl2 != NULL);
assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
assert(params_from_bl2->h.version >= VERSION_2);
bl_params_node_t *bl_params = params_from_bl2->head;
/*
* Copy BL33 entry point information.
* They are stored in Secure RAM, in BL2's address space.
*/
while (bl_params != NULL) {
if (bl_params->image_id == BL33_IMAGE_ID) {
bl33_image_ep_info = *bl_params->ep_info;
/*
* Check if hw_configuration is given to BL32 and
* share it to BL33.
*/
if (arg2 != 0U) {
bl33_image_ep_info.args.arg0 = 0U;
bl33_image_ep_info.args.arg1 = 0U;
bl33_image_ep_info.args.arg2 = arg2;
}
break;
}
bl_params = bl_params->next_params_info;
}
if (dt_open_and_check(dt_addr) < 0) {
panic();
}
if (bsec_probe() != 0) {
panic();
}
if (stm32mp1_clk_probe() < 0) {
panic();
}
(void)stm32mp_uart_console_setup();
stm32mp1_etzpc_early_setup();
}
/*******************************************************************************
* Initialize the MMU, security and the GIC.
******************************************************************************/
void sp_min_platform_setup(void)
{
generic_delay_timer_init();
stm32mp1_gic_init();
if (stm32_iwdg_init() < 0) {
panic();
}
stm32mp_lock_periph_registering();
stm32mp1_init_scmi_server();
}
void sp_min_plat_arch_setup(void)
{
}
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
.section .bl2_image
.incbin BL2_BIN_PATH
.section .dtb_image
.incbin DTB_BIN_PATH
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_LD_S
#define STM32MP1_LD_S
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <platform_def.h>
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
ENTRY(__BL2_IMAGE_START__)
MEMORY {
HEADER (rw) : ORIGIN = 0x00000000, LENGTH = STM32MP_HEADER_RESERVED_SIZE
RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE
}
SECTIONS
{
/*
* TF mapping must conform to ROM code specification.
*/
.header : {
__HEADER_START__ = .;
KEEP(*(.header))
. = ALIGN(4);
__HEADER_END__ = .;
} >HEADER
. = STM32MP_BINARY_BASE;
.data . : {
. = ALIGN(PAGE_SIZE);
__DATA_START__ = .;
*(.data*)
/*
* dtb.
* The strongest and only alignment contraint is MMU 4K page.
* Indeed as images below will be removed, 4K pages will be re-used.
*/
. = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE );
__DTB_IMAGE_START__ = .;
*(.dtb_image*)
__DTB_IMAGE_END__ = .;
/*
* bl2.
* The strongest and only alignment contraint is MMU 4K page.
* Indeed as images below will be removed, 4K pages will be re-used.
*/
#if SEPARATE_CODE_AND_RODATA
. = ( STM32MP_BL2_RO_BASE - STM32MP_BINARY_BASE );
#else
. = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE );
#endif
__BL2_IMAGE_START__ = .;
*(.bl2_image*)
__BL2_IMAGE_END__ = .;
__DATA_END__ = .;
} >RAM
__TF_END__ = .;
}
#endif /* STM32MP1_LD_S */
@@ -0,0 +1,209 @@
/*
* Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <common/debug.h>
#include <drivers/nand.h>
#include <drivers/raw_nand.h>
#include <drivers/spi_nand.h>
#include <drivers/spi_nor.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
#if STM32MP13
void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size)
{
assert(buffer_addr != NULL);
assert(buf_size != NULL);
*buffer_addr = (void *)STM32MP_MTD_BUFFER;
*buf_size = PLATFORM_MTD_MAX_PAGE_SIZE;
}
#endif
static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc)
{
uint32_t nand_param;
uint32_t nand2_param __maybe_unused;
/* Check if NAND parameters are stored in OTP */
if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) {
ERROR("BSEC: NAND_OTP Error\n");
return -EACCES;
}
if (nand_param == 0U) {
#if STM32MP13
if (is_slc) {
return 0;
}
#endif
#if STM32MP15
return 0;
#endif
}
if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) {
#if STM32MP13
if (is_slc) {
goto ecc;
}
#endif
#if STM32MP15
goto ecc;
#endif
}
#if STM32MP13
if (stm32_get_otp_value(NAND2_OTP, &nand2_param) != 0) {
ERROR("BSEC: NAND_OTP Error\n");
return -EACCES;
}
/* Check OTP configuration for this device */
if ((((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND1_SNAND_NAND2) && !is_slc) ||
(((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND2_SNAND_NAND1) && is_slc)) {
nand_param = nand2_param << (NAND_PAGE_SIZE_SHIFT - NAND2_PAGE_SIZE_SHIFT);
}
#endif
/* NAND parameter shall be read from OTP */
if ((nand_param & NAND_WIDTH_MASK) != 0U) {
nand_dev->buswidth = NAND_BUS_WIDTH_16;
} else {
nand_dev->buswidth = NAND_BUS_WIDTH_8;
}
switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) {
case NAND_PAGE_SIZE_2K:
nand_dev->page_size = 0x800U;
break;
case NAND_PAGE_SIZE_4K:
nand_dev->page_size = 0x1000U;
break;
case NAND_PAGE_SIZE_8K:
nand_dev->page_size = 0x2000U;
break;
default:
ERROR("Cannot read NAND page size\n");
return -EINVAL;
}
switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) {
case NAND_BLOCK_SIZE_64_PAGES:
nand_dev->block_size = 64U * nand_dev->page_size;
break;
case NAND_BLOCK_SIZE_128_PAGES:
nand_dev->block_size = 128U * nand_dev->page_size;
break;
case NAND_BLOCK_SIZE_256_PAGES:
nand_dev->block_size = 256U * nand_dev->page_size;
break;
default:
ERROR("Cannot read NAND block size\n");
return -EINVAL;
}
nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >>
NAND_BLOCK_NB_SHIFT) *
NAND_BLOCK_NB_UNIT * nand_dev->block_size;
ecc:
if (is_slc) {
switch ((nand_param & NAND_ECC_BIT_NB_MASK) >>
NAND_ECC_BIT_NB_SHIFT) {
case NAND_ECC_BIT_NB_1_BITS:
nand_dev->ecc.max_bit_corr = 1U;
break;
case NAND_ECC_BIT_NB_4_BITS:
nand_dev->ecc.max_bit_corr = 4U;
break;
case NAND_ECC_BIT_NB_8_BITS:
nand_dev->ecc.max_bit_corr = 8U;
break;
case NAND_ECC_ON_DIE:
nand_dev->ecc.mode = NAND_ECC_ONDIE;
break;
default:
if (nand_dev->ecc.max_bit_corr == 0U) {
ERROR("No valid eccbit number\n");
return -EINVAL;
}
}
} else {
/* Selected multiple plane NAND */
if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) {
nand_dev->nb_planes = 2U;
} else {
nand_dev->nb_planes = 1U;
}
}
VERBOSE("OTP: Block %u Page %u Size %llu\n", nand_dev->block_size,
nand_dev->page_size, nand_dev->size);
return 0;
}
#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */
#if STM32MP_RAW_NAND
int plat_get_raw_nand_data(struct rawnand_device *device)
{
device->nand_dev->ecc.mode = NAND_ECC_HW;
device->nand_dev->ecc.size = SZ_512;
return get_data_from_otp(device->nand_dev, true);
}
#endif
#if STM32MP_SPI_NAND
int plat_get_spi_nand_data(struct spinand_device *device)
{
zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op));
device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X;
device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
device->spi_read_cache_op.addr.nbytes = 2U;
device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
device->spi_read_cache_op.dummy.nbytes = 1U;
device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN;
return get_data_from_otp(device->nand_dev, false);
}
#endif
#if STM32MP_SPI_NOR
int plat_get_nor_data(struct nor_device *device)
{
device->size = SZ_64M;
zeromem(&device->read_op, sizeof(struct spi_mem_op));
device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4;
device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
device->read_op.addr.nbytes = 3U;
device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
device->read_op.dummy.nbytes = 1U;
device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
device->read_op.data.dir = SPI_MEM_DATA_IN;
return 0;
}
#endif
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <common/debug.h>
#include <drivers/st/bsec.h>
#include <drivers/st/bsec2_reg.h>
#include <drivers/st/stm32mp1_rcc.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <platform_def.h>
#include <stm32mp1_dbgmcu.h>
#define DBGMCU_IDC U(0x00)
#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
#define DBGMCU_IDC_REV_ID_SHIFT 16
static int stm32mp1_dbgmcu_init(void)
{
if ((bsec_read_debug_conf() & BSEC_DBGSWGEN) == 0U) {
INFO("Software access to all debug components is disabled\n");
return -1;
}
mmio_setbits_32(RCC_BASE + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
return 0;
}
/*
* @brief Get silicon revision from DBGMCU registers.
* @param chip_version: pointer to the read value.
* @retval 0 on success, negative value on failure.
*/
int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version)
{
assert(chip_version != NULL);
if (stm32mp1_dbgmcu_init() != 0) {
return -EPERM;
}
*chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
return 0;
}
/*
* @brief Get device ID from DBGMCU registers.
* @param chip_dev_id: pointer to the read value.
* @retval 0 on success, negative value on failure.
*/
int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id)
{
assert(chip_dev_id != NULL);
if (stm32mp1_dbgmcu_init() != 0) {
return -EPERM;
}
*chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
DBGMCU_IDC_DEV_ID_MASK;
return 0;
}
@@ -0,0 +1,669 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_DEF_H
#define STM32MP1_DEF_H
#include <common/tbbr/tbbr_img_def.h>
#include <drivers/st/stm32mp1_rcc.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
#ifndef __ASSEMBLER__
#include <drivers/st/bsec.h>
#include <drivers/st/stm32mp1_clk.h>
#include <boot_api.h>
#include <stm32mp_common.h>
#include <stm32mp_dt.h>
#include <stm32mp1_dbgmcu.h>
#include <stm32mp1_private.h>
#include <stm32mp1_shared_resources.h>
#endif
#include "stm32mp1_fip_def.h"
/*******************************************************************************
* CHIP ID
******************************************************************************/
#if STM32MP13
#define STM32MP1_CHIP_ID U(0x501)
#define STM32MP135C_PART_NB U(0x05010000)
#define STM32MP135A_PART_NB U(0x05010001)
#define STM32MP133C_PART_NB U(0x050100C0)
#define STM32MP133A_PART_NB U(0x050100C1)
#define STM32MP131C_PART_NB U(0x050106C8)
#define STM32MP131A_PART_NB U(0x050106C9)
#define STM32MP135F_PART_NB U(0x05010800)
#define STM32MP135D_PART_NB U(0x05010801)
#define STM32MP133F_PART_NB U(0x050108C0)
#define STM32MP133D_PART_NB U(0x050108C1)
#define STM32MP131F_PART_NB U(0x05010EC8)
#define STM32MP131D_PART_NB U(0x05010EC9)
#endif
#if STM32MP15
#define STM32MP1_CHIP_ID U(0x500)
#define STM32MP157C_PART_NB U(0x05000000)
#define STM32MP157A_PART_NB U(0x05000001)
#define STM32MP153C_PART_NB U(0x05000024)
#define STM32MP153A_PART_NB U(0x05000025)
#define STM32MP151C_PART_NB U(0x0500002E)
#define STM32MP151A_PART_NB U(0x0500002F)
#define STM32MP157F_PART_NB U(0x05000080)
#define STM32MP157D_PART_NB U(0x05000081)
#define STM32MP153F_PART_NB U(0x050000A4)
#define STM32MP153D_PART_NB U(0x050000A5)
#define STM32MP151F_PART_NB U(0x050000AE)
#define STM32MP151D_PART_NB U(0x050000AF)
#endif
#define STM32MP1_REV_B U(0x2000)
#if STM32MP13
#define STM32MP1_REV_Y U(0x1003)
#define STM32MP1_REV_Z U(0x1001)
#endif
#if STM32MP15
#define STM32MP1_REV_Z U(0x2001)
#endif
/*******************************************************************************
* PACKAGE ID
******************************************************************************/
#if STM32MP15
#define PKG_AA_LFBGA448 U(4)
#define PKG_AB_LFBGA354 U(3)
#define PKG_AC_TFBGA361 U(2)
#define PKG_AD_TFBGA257 U(1)
#endif
/*******************************************************************************
* STM32MP1 memory map related constants
******************************************************************************/
#define STM32MP_ROM_BASE U(0x00000000)
#define STM32MP_ROM_SIZE U(0x00020000)
#define STM32MP_ROM_SIZE_2MB_ALIGNED U(0x00200000)
#if STM32MP13
#define STM32MP_SYSRAM_BASE U(0x2FFE0000)
#define STM32MP_SYSRAM_SIZE U(0x00020000)
#define SRAM1_BASE U(0x30000000)
#define SRAM1_SIZE U(0x00004000)
#define SRAM2_BASE U(0x30004000)
#define SRAM2_SIZE U(0x00002000)
#define SRAM3_BASE U(0x30006000)
#define SRAM3_SIZE U(0x00002000)
#define SRAMS_BASE SRAM1_BASE
#define SRAMS_SIZE_2MB_ALIGNED U(0x00200000)
#endif /* STM32MP13 */
#if STM32MP15
#define STM32MP_SYSRAM_BASE U(0x2FFC0000)
#define STM32MP_SYSRAM_SIZE U(0x00040000)
#endif /* STM32MP15 */
#define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE
#define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \
STM32MP_SYSRAM_SIZE - \
STM32MP_NS_SYSRAM_SIZE)
#define STM32MP_SCMI_NS_SHM_BASE STM32MP_NS_SYSRAM_BASE
#define STM32MP_SCMI_NS_SHM_SIZE STM32MP_NS_SYSRAM_SIZE
#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE
#define STM32MP_SEC_SYSRAM_SIZE (STM32MP_SYSRAM_SIZE - \
STM32MP_NS_SYSRAM_SIZE)
/* DDR configuration */
#define STM32MP_DDR_BASE U(0xC0000000)
#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
/* DDR power initializations */
#ifndef __ASSEMBLER__
enum ddr_type {
STM32MP_DDR3,
STM32MP_LPDDR2,
STM32MP_LPDDR3
};
#endif
/* Section used inside TF binaries */
#if STM32MP13
/* 512 Octets reserved for header */
#define STM32MP_HEADER_RESERVED_SIZE U(0x200)
#define STM32MP_BINARY_BASE STM32MP_SEC_SYSRAM_BASE
#define STM32MP_BINARY_SIZE STM32MP_SEC_SYSRAM_SIZE
#endif
#if STM32MP15
#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */
/* 256 Octets reserved for header */
#define STM32MP_HEADER_SIZE U(0x00000100)
/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */
#define STM32MP_HEADER_RESERVED_SIZE U(0x3000)
#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \
STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE)
#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \
(STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE))
#endif
/* BL2 and BL32/sp_min require finer granularity tables */
#if defined(IMAGE_BL2)
#define MAX_XLAT_TABLES U(2) /* 8 KB for mapping */
#endif
#if defined(IMAGE_BL32)
#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */
#endif
/*
* MAX_MMAP_REGIONS is usually:
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
*/
#if defined(IMAGE_BL2)
#if STM32MP_USB_PROGRAMMER
#define MAX_MMAP_REGIONS 8
#else
#define MAX_MMAP_REGIONS 7
#endif
#endif
#if STM32MP13
#define STM32MP_BL33_BASE STM32MP_DDR_BASE
#endif
#if STM32MP15
#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000))
#endif
#define STM32MP_BL33_MAX_SIZE U(0x400000)
/* Define maximum page size for NAND devices */
#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000)
/* Define location for the MTD scratch buffer */
#if STM32MP13
#define STM32MP_MTD_BUFFER (SRAM1_BASE + \
SRAM1_SIZE - \
PLATFORM_MTD_MAX_PAGE_SIZE)
#endif
/*******************************************************************************
* STM32MP1 device/io map related constants (used for MMU)
******************************************************************************/
#define STM32MP1_DEVICE1_BASE U(0x40000000)
#define STM32MP1_DEVICE1_SIZE U(0x40000000)
#define STM32MP1_DEVICE2_BASE U(0x80000000)
#define STM32MP1_DEVICE2_SIZE U(0x40000000)
/*******************************************************************************
* STM32MP1 RCC
******************************************************************************/
#define RCC_BASE U(0x50000000)
/*******************************************************************************
* STM32MP1 PWR
******************************************************************************/
#define PWR_BASE U(0x50001000)
/*******************************************************************************
* STM32MP1 GPIO
******************************************************************************/
#define GPIOA_BASE U(0x50002000)
#define GPIOB_BASE U(0x50003000)
#define GPIOC_BASE U(0x50004000)
#define GPIOD_BASE U(0x50005000)
#define GPIOE_BASE U(0x50006000)
#define GPIOF_BASE U(0x50007000)
#define GPIOG_BASE U(0x50008000)
#define GPIOH_BASE U(0x50009000)
#define GPIOI_BASE U(0x5000A000)
#if STM32MP15
#define GPIOJ_BASE U(0x5000B000)
#define GPIOK_BASE U(0x5000C000)
#define GPIOZ_BASE U(0x54004000)
#endif
#define GPIO_BANK_OFFSET U(0x1000)
/* Bank IDs used in GPIO driver API */
#define GPIO_BANK_A U(0)
#define GPIO_BANK_B U(1)
#define GPIO_BANK_C U(2)
#define GPIO_BANK_D U(3)
#define GPIO_BANK_E U(4)
#define GPIO_BANK_F U(5)
#define GPIO_BANK_G U(6)
#define GPIO_BANK_H U(7)
#define GPIO_BANK_I U(8)
#if STM32MP15
#define GPIO_BANK_J U(9)
#define GPIO_BANK_K U(10)
#define GPIO_BANK_Z U(25)
#define STM32MP_GPIOZ_PIN_MAX_COUNT 8
#endif
/*******************************************************************************
* STM32MP1 UART
******************************************************************************/
#if STM32MP13
#define USART1_BASE U(0x4C000000)
#define USART2_BASE U(0x4C001000)
#endif
#if STM32MP15
#define USART1_BASE U(0x5C000000)
#define USART2_BASE U(0x4000E000)
#endif
#define USART3_BASE U(0x4000F000)
#define UART4_BASE U(0x40010000)
#define UART5_BASE U(0x40011000)
#define USART6_BASE U(0x44003000)
#define UART7_BASE U(0x40018000)
#define UART8_BASE U(0x40019000)
/* For UART crash console */
#define STM32MP_DEBUG_USART_BASE UART4_BASE
#if STM32MP13
/* UART4 on HSI@64MHz, TX on GPIOF12 Alternate 8 (Disco board) */
#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOD_BASE
#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_S_AHB4ENSETR
#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_S_AHB4ENSETR_GPIODEN
#define DEBUG_UART_TX_GPIO_PORT 6
#define DEBUG_UART_TX_GPIO_ALTERNATE 8
#define DEBUG_UART_TX_CLKSRC_REG RCC_UART4CKSELR
#define DEBUG_UART_TX_CLKSRC RCC_UART4CKSELR_HSI
#endif /* STM32MP13 */
#if STM32MP15
/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */
#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE
#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR
#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN
#define DEBUG_UART_TX_GPIO_PORT 11
#define DEBUG_UART_TX_GPIO_ALTERNATE 6
#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR
#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI
#endif /* STM32MP15 */
#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR
#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN
#define DEBUG_UART_RST_REG RCC_APB1RSTSETR
#define DEBUG_UART_RST_BIT RCC_APB1RSTSETR_UART4RST
/*******************************************************************************
* STM32MP1 ETZPC
******************************************************************************/
#define STM32MP1_ETZPC_BASE U(0x5C007000)
/* ETZPC TZMA IDs */
#define STM32MP1_ETZPC_TZMA_ROM U(0)
#define STM32MP1_ETZPC_TZMA_SYSRAM U(1)
#define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0)
/* ETZPC DECPROT IDs */
#define STM32MP1_ETZPC_STGENC_ID 0
#define STM32MP1_ETZPC_BKPSRAM_ID 1
#define STM32MP1_ETZPC_IWDG1_ID 2
#define STM32MP1_ETZPC_USART1_ID 3
#define STM32MP1_ETZPC_SPI6_ID 4
#define STM32MP1_ETZPC_I2C4_ID 5
#define STM32MP1_ETZPC_RNG1_ID 7
#define STM32MP1_ETZPC_HASH1_ID 8
#define STM32MP1_ETZPC_CRYP1_ID 9
#define STM32MP1_ETZPC_DDRCTRL_ID 10
#define STM32MP1_ETZPC_DDRPHYC_ID 11
#define STM32MP1_ETZPC_I2C6_ID 12
#define STM32MP1_ETZPC_SEC_ID_LIMIT 13
#define STM32MP1_ETZPC_TIM2_ID 16
#define STM32MP1_ETZPC_TIM3_ID 17
#define STM32MP1_ETZPC_TIM4_ID 18
#define STM32MP1_ETZPC_TIM5_ID 19
#define STM32MP1_ETZPC_TIM6_ID 20
#define STM32MP1_ETZPC_TIM7_ID 21
#define STM32MP1_ETZPC_TIM12_ID 22
#define STM32MP1_ETZPC_TIM13_ID 23
#define STM32MP1_ETZPC_TIM14_ID 24
#define STM32MP1_ETZPC_LPTIM1_ID 25
#define STM32MP1_ETZPC_WWDG1_ID 26
#define STM32MP1_ETZPC_SPI2_ID 27
#define STM32MP1_ETZPC_SPI3_ID 28
#define STM32MP1_ETZPC_SPDIFRX_ID 29
#define STM32MP1_ETZPC_USART2_ID 30
#define STM32MP1_ETZPC_USART3_ID 31
#define STM32MP1_ETZPC_UART4_ID 32
#define STM32MP1_ETZPC_UART5_ID 33
#define STM32MP1_ETZPC_I2C1_ID 34
#define STM32MP1_ETZPC_I2C2_ID 35
#define STM32MP1_ETZPC_I2C3_ID 36
#define STM32MP1_ETZPC_I2C5_ID 37
#define STM32MP1_ETZPC_CEC_ID 38
#define STM32MP1_ETZPC_DAC_ID 39
#define STM32MP1_ETZPC_UART7_ID 40
#define STM32MP1_ETZPC_UART8_ID 41
#define STM32MP1_ETZPC_MDIOS_ID 44
#define STM32MP1_ETZPC_TIM1_ID 48
#define STM32MP1_ETZPC_TIM8_ID 49
#define STM32MP1_ETZPC_USART6_ID 51
#define STM32MP1_ETZPC_SPI1_ID 52
#define STM32MP1_ETZPC_SPI4_ID 53
#define STM32MP1_ETZPC_TIM15_ID 54
#define STM32MP1_ETZPC_TIM16_ID 55
#define STM32MP1_ETZPC_TIM17_ID 56
#define STM32MP1_ETZPC_SPI5_ID 57
#define STM32MP1_ETZPC_SAI1_ID 58
#define STM32MP1_ETZPC_SAI2_ID 59
#define STM32MP1_ETZPC_SAI3_ID 60
#define STM32MP1_ETZPC_DFSDM_ID 61
#define STM32MP1_ETZPC_TT_FDCAN_ID 62
#define STM32MP1_ETZPC_LPTIM2_ID 64
#define STM32MP1_ETZPC_LPTIM3_ID 65
#define STM32MP1_ETZPC_LPTIM4_ID 66
#define STM32MP1_ETZPC_LPTIM5_ID 67
#define STM32MP1_ETZPC_SAI4_ID 68
#define STM32MP1_ETZPC_VREFBUF_ID 69
#define STM32MP1_ETZPC_DCMI_ID 70
#define STM32MP1_ETZPC_CRC2_ID 71
#define STM32MP1_ETZPC_ADC_ID 72
#define STM32MP1_ETZPC_HASH2_ID 73
#define STM32MP1_ETZPC_RNG2_ID 74
#define STM32MP1_ETZPC_CRYP2_ID 75
#define STM32MP1_ETZPC_SRAM1_ID 80
#define STM32MP1_ETZPC_SRAM2_ID 81
#define STM32MP1_ETZPC_SRAM3_ID 82
#define STM32MP1_ETZPC_SRAM4_ID 83
#define STM32MP1_ETZPC_RETRAM_ID 84
#define STM32MP1_ETZPC_OTG_ID 85
#define STM32MP1_ETZPC_SDMMC3_ID 86
#define STM32MP1_ETZPC_DLYBSD3_ID 87
#define STM32MP1_ETZPC_DMA1_ID 88
#define STM32MP1_ETZPC_DMA2_ID 89
#define STM32MP1_ETZPC_DMAMUX_ID 90
#define STM32MP1_ETZPC_FMC_ID 91
#define STM32MP1_ETZPC_QSPI_ID 92
#define STM32MP1_ETZPC_DLYBQ_ID 93
#define STM32MP1_ETZPC_ETH_ID 94
#define STM32MP1_ETZPC_RSV_ID 95
#define STM32MP_ETZPC_MAX_ID 96
/*******************************************************************************
* STM32MP1 TZC (TZ400)
******************************************************************************/
#define STM32MP1_TZC_BASE U(0x5C006000)
#if STM32MP13
#define STM32MP1_FILTER_BIT_ALL TZC_400_REGION_ATTR_FILTER_BIT(0)
#endif
#if STM32MP15
#define STM32MP1_FILTER_BIT_ALL (TZC_400_REGION_ATTR_FILTER_BIT(0) | \
TZC_400_REGION_ATTR_FILTER_BIT(1))
#endif
/*******************************************************************************
* STM32MP1 SDMMC
******************************************************************************/
#define STM32MP_SDMMC1_BASE U(0x58005000)
#define STM32MP_SDMMC2_BASE U(0x58007000)
#define STM32MP_SDMMC3_BASE U(0x48004000)
#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/
#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/
#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/
#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/
#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/
/*******************************************************************************
* STM32MP1 BSEC / OTP
******************************************************************************/
#define STM32MP1_OTP_MAX_ID 0x5FU
#define STM32MP1_UPPER_OTP_START 0x20U
#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U)
/* OTP labels */
#define CFG0_OTP "cfg0_otp"
#define PART_NUMBER_OTP "part_number_otp"
#if STM32MP15
#define PACKAGE_OTP "package_otp"
#endif
#define HW2_OTP "hw2_otp"
#if STM32MP13
#define NAND_OTP "cfg9_otp"
#define NAND2_OTP "cfg10_otp"
#endif
#if STM32MP15
#define NAND_OTP "nand_otp"
#endif
#define MONOTONIC_OTP "monotonic_otp"
#define UID_OTP "uid_otp"
#define PKH_OTP "pkh_otp"
#define ENCKEY_OTP "enckey_otp"
#define BOARD_ID_OTP "board_id"
/* OTP mask */
/* CFG0 */
#if STM32MP13
#define CFG0_OTP_MODE_MASK GENMASK_32(9, 0)
#define CFG0_OTP_MODE_SHIFT 0
#define CFG0_OPEN_DEVICE 0x17U
#define CFG0_CLOSED_DEVICE 0x3FU
#define CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN 0x17FU
#define CFG0_CLOSED_DEVICE_NO_JTAG 0x3FFU
#endif
#if STM32MP15
#define CFG0_CLOSED_DEVICE BIT(6)
#endif
/* PART NUMBER */
#if STM32MP13
#define PART_NUMBER_OTP_PART_MASK GENMASK_32(11, 0)
#endif
#if STM32MP15
#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0)
#endif
#define PART_NUMBER_OTP_PART_SHIFT 0
/* PACKAGE */
#if STM32MP15
#define PACKAGE_OTP_PKG_MASK GENMASK_32(29, 27)
#define PACKAGE_OTP_PKG_SHIFT 27
#endif
/* IWDG OTP */
#define HW2_OTP_IWDG_HW_POS U(3)
#define HW2_OTP_IWDG_FZ_STOP_POS U(5)
#define HW2_OTP_IWDG_FZ_STANDBY_POS U(7)
/* HW2 OTP */
#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13)
/* NAND OTP */
/* NAND parameter storage flag */
#define NAND_PARAM_STORED_IN_OTP BIT(31)
/* NAND page size in bytes */
#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29)
#define NAND_PAGE_SIZE_SHIFT 29
#define NAND_PAGE_SIZE_2K U(0)
#define NAND_PAGE_SIZE_4K U(1)
#define NAND_PAGE_SIZE_8K U(2)
/* NAND block size in pages */
#define NAND_BLOCK_SIZE_MASK GENMASK_32(28, 27)
#define NAND_BLOCK_SIZE_SHIFT 27
#define NAND_BLOCK_SIZE_64_PAGES U(0)
#define NAND_BLOCK_SIZE_128_PAGES U(1)
#define NAND_BLOCK_SIZE_256_PAGES U(2)
/* NAND number of block (in unit of 256 blocks) */
#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19)
#define NAND_BLOCK_NB_SHIFT 19
#define NAND_BLOCK_NB_UNIT U(256)
/* NAND bus width in bits */
#define NAND_WIDTH_MASK BIT(18)
#define NAND_WIDTH_SHIFT 18
/* NAND number of ECC bits per 512 bytes */
#define NAND_ECC_BIT_NB_MASK GENMASK_32(17, 15)
#define NAND_ECC_BIT_NB_SHIFT 15
#define NAND_ECC_BIT_NB_UNSET U(0)
#define NAND_ECC_BIT_NB_1_BITS U(1)
#define NAND_ECC_BIT_NB_4_BITS U(2)
#define NAND_ECC_BIT_NB_8_BITS U(3)
#define NAND_ECC_ON_DIE U(4)
/* NAND number of planes */
#define NAND_PLANE_BIT_NB_MASK BIT(14)
/* NAND2 OTP */
#define NAND2_PAGE_SIZE_SHIFT 16
/* NAND2 config distribution */
#define NAND2_CONFIG_DISTRIB BIT(0)
#define NAND2_PNAND_NAND2_SNAND_NAND1 U(0)
#define NAND2_PNAND_NAND1_SNAND_NAND2 U(1)
/* MONOTONIC OTP */
#define MAX_MONOTONIC_VALUE 32
/* UID OTP */
#define UID_WORD_NB U(3)
/* FWU configuration (max supported value is 15) */
#define FWU_MAX_TRIAL_REBOOT U(3)
/*******************************************************************************
* STM32MP1 TAMP
******************************************************************************/
#define TAMP_BASE U(0x5C00A000)
#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
#define TAMP_COUNTR U(0x40)
#if !(defined(__LINKER__) || defined(__ASSEMBLER__))
static inline uintptr_t tamp_bkpr(uint32_t idx)
{
return TAMP_BKP_REGISTER_BASE + (idx << 2);
}
#endif
/*******************************************************************************
* STM32MP1 USB
******************************************************************************/
#define USB_OTG_BASE U(0x49000000)
/*******************************************************************************
* STM32MP1 DDRCTRL
******************************************************************************/
#define DDRCTRL_BASE U(0x5A003000)
/*******************************************************************************
* STM32MP1 DDRPHYC
******************************************************************************/
#define DDRPHYC_BASE U(0x5A004000)
/*******************************************************************************
* STM32MP1 IWDG
******************************************************************************/
#define IWDG_MAX_INSTANCE U(2)
#define IWDG1_INST U(0)
#define IWDG2_INST U(1)
#define IWDG1_BASE U(0x5C003000)
#define IWDG2_BASE U(0x5A002000)
/*******************************************************************************
* Miscellaneous STM32MP1 peripherals base address
******************************************************************************/
#define BSEC_BASE U(0x5C005000)
#if STM32MP13
#define CRYP_BASE U(0x54002000)
#endif
#if STM32MP15
#define CRYP1_BASE U(0x54001000)
#endif
#define DBGMCU_BASE U(0x50081000)
#if STM32MP13
#define HASH_BASE U(0x54003000)
#endif
#if STM32MP15
#define HASH1_BASE U(0x54002000)
#endif
#if STM32MP13
#define I2C3_BASE U(0x4C004000)
#define I2C4_BASE U(0x4C005000)
#define I2C5_BASE U(0x4C006000)
#endif
#if STM32MP15
#define I2C4_BASE U(0x5C002000)
#define I2C6_BASE U(0x5c009000)
#endif
#if STM32MP13
#define RNG_BASE U(0x54004000)
#endif
#if STM32MP15
#define RNG1_BASE U(0x54003000)
#endif
#define RTC_BASE U(0x5c004000)
#if STM32MP13
#define SPI4_BASE U(0x4C002000)
#define SPI5_BASE U(0x4C003000)
#endif
#if STM32MP15
#define SPI6_BASE U(0x5c001000)
#endif
#define STGEN_BASE U(0x5c008000)
#define SYSCFG_BASE U(0x50020000)
/*******************************************************************************
* STM32MP13 SAES
******************************************************************************/
#define SAES_BASE U(0x54005000)
/*******************************************************************************
* STM32MP13 PKA
******************************************************************************/
#define PKA_BASE U(0x54006000)
/*******************************************************************************
* REGULATORS
******************************************************************************/
/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */
#define PLAT_NB_RDEVS U(19)
/* 2 FIXED */
#define PLAT_NB_FIXED_REGS U(2)
/*******************************************************************************
* Device Tree defines
******************************************************************************/
#define DT_BSEC_COMPAT "st,stm32mp15-bsec"
#if STM32MP13
#define DT_DDR_COMPAT "st,stm32mp13-ddr"
#endif
#if STM32MP15
#define DT_DDR_COMPAT "st,stm32mp1-ddr"
#endif
#define DT_IWDG_COMPAT "st,stm32mp1-iwdg"
#define DT_PWR_COMPAT "st,stm32mp1,pwr-reg"
#if STM32MP13
#define DT_RCC_CLK_COMPAT "st,stm32mp13-rcc"
#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp13-rcc-secure"
#endif
#if STM32MP15
#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp1-rcc-secure"
#endif
#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
#define DT_UART_COMPAT "st,stm32h7-uart"
#endif /* STM32MP1_DEF_H */
@@ -0,0 +1,128 @@
/*
* Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <drivers/arm/tzc400.h>
#include <drivers/clk.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <lib/fconf/fconf.h>
#include <lib/object_pool.h>
#include <libfdt.h>
#include <tools_share/firmware_image_package.h>
#include <platform_def.h>
#include <stm32mp_fconf_getter.h>
#define STM32MP_REGION_PARAMS 4
#define STM32MP_MAX_REGIONS 8
#define FORCE_SEC_REGION BIT(31)
static uint32_t nb_regions;
struct dt_id_attr {
fdt32_t id_attr[STM32MP_MAX_REGIONS];
};
void stm32mp1_arch_security_setup(void)
{
#if STM32MP13
clk_enable(TZC);
#endif
#if STM32MP15
clk_enable(TZC1);
clk_enable(TZC2);
#endif
tzc400_init(STM32MP1_TZC_BASE);
tzc400_disable_filters();
/*
* Region 0 set to cover all DRAM at 0xC000_0000
* Only secure access is granted in read/write.
*/
tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
tzc400_set_action(TZC_ACTION_ERR);
tzc400_enable_filters();
}
void stm32mp1_security_setup(void)
{
uint8_t i;
assert(nb_regions > 0U);
tzc400_init(STM32MP1_TZC_BASE);
tzc400_disable_filters();
/*
* Region 0 set to cover all DRAM at 0xC000_0000
* No access is allowed.
*/
tzc400_configure_region0(TZC_REGION_S_NONE, 0);
for (i = 1U; i <= nb_regions; i++) {
tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL);
}
tzc400_set_action(TZC_ACTION_INT);
tzc400_enable_filters();
}
static int fconf_populate_stm32mp1_firewall(uintptr_t config)
{
int node, len;
unsigned int i;
const struct dt_id_attr *conf_list;
const void *dtb = (const void *)config;
/* Assert the node offset point to "st,mem-firewall" compatible property */
const char *compatible_str = "st,mem-firewall";
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
if (node < 0) {
ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
return node;
}
conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len);
if (conf_list == NULL) {
WARN("FCONF: Read cell failed for %s\n", "memory-ranges");
return -1;
}
/* Locate the memory cells and read all values */
for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) {
uint32_t base;
uint32_t size;
uint32_t sec_attr;
uint32_t nsaid;
base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]);
size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]);
sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]);
nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]);
VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
base, size, sec_attr, nsaid);
nb_regions++;
/* Configure region but keep disabled for secure access for BL2 load */
tzc400_configure_region(0U, nb_regions, (unsigned long long)base,
(unsigned long long)base + size - 1ULL, sec_attr, nsaid);
}
/* Force flush as the value will be used cache off */
flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t));
return 0;
}
FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall);
@@ -0,0 +1,138 @@
/*
* Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef STM32MP1_FIP_DEF_H
#define STM32MP1_FIP_DEF_H
#if STM32MP15_OPTEE_RSV_SHM
#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */
#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */
#else
#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */
#define STM32MP_DDR_SHMEM_SIZE U(0) /* empty */
#endif
#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP
#if STM32MP15
#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */
#define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */
#endif /* STM32MP15 */
#else /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
#if STM32MP13
#if BL2_IN_XIP_MEM
#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */
#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */
#else
/* STM32MP_BL2_RO_SIZE not used if !BL2_IN_XIP_MEM */
#define STM32MP_BL2_SIZE U(0x0001B000) /* 108KB for BL2 */
/* with 20KB for DTB, SYSRAM is full */
#endif
#endif /* STM32MP13 */
#if STM32MP15
#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */
#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */
#endif /* STM32MP15 */
#endif /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
#if STM32MP13
#if TRUSTED_BOARD_BOOT
#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
#else /* TRUSTED_BOARD_BOOT */
#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */
#endif /* TRUSTED_BOARD_BOOT */
#endif /* STM32MP13 */
#if STM32MP15
#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */
#endif /* STM32MP15 */
#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */
#define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE /* 4 KB for FCONF DTB */
#define STM32MP_HW_CONFIG_MAX_SIZE U(0x40000) /* 256 KB for HW config DTB */
#if STM32MP13
#define STM32MP_BL2_BASE (STM32MP_BL2_DTB_BASE + \
STM32MP_BL2_DTB_SIZE)
#endif /* STM32MP13 */
#if STM32MP15
#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \
STM32MP_SEC_SYSRAM_SIZE - \
STM32MP_BL2_SIZE)
#endif /* STM32MP15 */
#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE
#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \
STM32MP_BL2_RO_SIZE)
#if STM32MP13
#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \
STM32MP_SYSRAM_SIZE - \
STM32MP_BL2_RW_BASE)
#define STM32MP_BL2_DTB_BASE STM32MP_SEC_SYSRAM_BASE
#endif /* STM32MP13 */
#if STM32MP15
#define STM32MP_BL2_RW_SIZE (STM32MP_SEC_SYSRAM_BASE + \
STM32MP_SEC_SYSRAM_SIZE - \
STM32MP_BL2_RW_BASE)
#define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \
STM32MP_BL2_DTB_SIZE)
#endif /* STM32MP15 */
#define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE
#define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \
STM32MP_BL32_DTB_SIZE)
#if defined(IMAGE_BL2)
#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE
#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE
#endif
#if defined(IMAGE_BL32)
#define STM32MP_DTB_SIZE STM32MP_BL32_DTB_SIZE
#define STM32MP_DTB_BASE STM32MP_BL32_DTB_BASE
#endif
#ifdef AARCH32_SP_OPTEE
#define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE
#define STM32MP_OPTEE_SIZE (STM32MP_BL2_DTB_BASE - \
STM32MP_OPTEE_BASE)
#endif
#if STM32MP13
#define STM32MP_FW_CONFIG_BASE SRAM3_BASE
#endif /* STM32MP13 */
#if STM32MP15
#define STM32MP_FW_CONFIG_BASE (STM32MP_SYSRAM_BASE + \
STM32MP_SYSRAM_SIZE - \
PAGE_SIZE)
#endif /* STM32MP15 */
#define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \
STM32MP_BL33_MAX_SIZE)
/*
* MAX_MMAP_REGIONS is usually:
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
*/
#if defined(IMAGE_BL32)
#define MAX_MMAP_REGIONS 10
#endif
/*******************************************************************************
* STM32MP1 RAW partition offset for devices without GPT
******************************************************************************/
#define STM32MP_EMMC_BOOT_FIP_OFFSET U(0x00040000)
#ifndef STM32MP_NOR_FIP_OFFSET
#define STM32MP_NOR_FIP_OFFSET U(0x00080000)
#endif
#ifndef STM32MP_NAND_FIP_OFFSET
#define STM32MP_NAND_FIP_OFFSET U(0x00200000)
#endif
#endif /* STM32MP1_FIP_DEF_H */
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <libfdt.h>
#include <platform_def.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/arm/gicv2.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
struct stm32_gic_instance {
uint32_t cells;
uint32_t phandle_node;
};
/******************************************************************************
* On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
* interrupts.
*****************************************************************************/
static const interrupt_prop_t stm32mp1_interrupt_props[] = {
PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
};
/* Fix target_mask_array as secondary core is not able to initialize it */
static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2};
static gicv2_driver_data_t platform_gic_data = {
.interrupt_props = stm32mp1_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props),
.target_masks = target_mask_array,
.target_masks_num = ARRAY_SIZE(target_mask_array),
};
static struct stm32_gic_instance stm32_gic;
void stm32mp1_gic_init(void)
{
int node;
void *fdt;
const fdt32_t *cuint;
struct dt_node_info dt_gic;
if (fdt_get_address(&fdt) == 0) {
panic();
}
node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic");
if (node < 0) {
panic();
}
platform_gic_data.gicd_base = dt_gic.base;
cuint = fdt_getprop(fdt, node, "reg", NULL);
if (cuint == NULL) {
panic();
}
platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2));
cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL);
if (cuint == NULL) {
panic();
}
stm32_gic.cells = fdt32_to_cpu(*cuint);
stm32_gic.phandle_node = fdt_get_phandle(fdt, node);
if (stm32_gic.phandle_node == 0U) {
panic();
}
gicv2_driver_init(&platform_gic_data);
gicv2_distif_init();
stm32mp1_gic_pcpu_init();
}
void stm32mp1_gic_pcpu_init(void)
{
gicv2_pcpu_distif_init();
gicv2_set_pe_target_mask(plat_my_core_pos());
gicv2_cpuif_enable();
}
@@ -0,0 +1,336 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
#include <drivers/st/stm32_gpio.h>
#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1)
.globl platform_mem_init
.globl plat_report_exception
.globl plat_report_prefetch_abort
.globl plat_report_data_abort
.globl plat_get_my_entrypoint
.globl plat_secondary_cold_boot_setup
.globl plat_reset_handler
.globl plat_is_my_cpu_primary
.globl plat_my_core_pos
.globl plat_crash_console_init
.globl plat_crash_console_flush
.globl plat_crash_console_putc
.globl plat_panic_handler
func platform_mem_init
/* Nothing to do, don't need to init SYSRAM */
bx lr
endfunc platform_mem_init
#if DEBUG
func plat_report_exception
mov r8, lr
/*
* Test if an abort occurred
* In this case the error message has already been displayed
* by dedicated functions
*/
cmp r0, #MODE32_abt
beq 1f
/* Test for an undefined instruction */
cmp r0, #MODE32_und
bne other_exception_lbl
ldr r4, =undefined_str
bl asm_print_str
mrs r4, lr_und
b print_exception_info
other_exception_lbl:
/* Other exceptions */
mov r9, r0
ldr r4, =exception_start_str
bl asm_print_str
mov r4, r9
bl asm_print_hex
ldr r4, =exception_end_str
bl asm_print_str
mov r4, r6
print_exception_info:
bl asm_print_hex
ldr r4, =end_error_str
bl asm_print_str
1:
bx r8
endfunc plat_report_exception
func plat_report_prefetch_abort
mov r8, lr
mov r9, r0
ldr r4, =prefetch_abort_str
bl asm_print_str
mov r4, r9
sub r4, r4, #4
bl asm_print_hex
ldr r4, =ifsr_str
bl asm_print_str
ldcopr r4, IFSR
bl asm_print_hex
ldr r4, =ifar_str
bl asm_print_str
ldcopr r4, IFAR
bl asm_print_hex
ldr r4, =end_error_str
bl asm_print_str
bx r8
endfunc plat_report_prefetch_abort
func plat_report_data_abort
mov r8, lr
mov r9, r0
ldr r4, =data_abort_str
bl asm_print_str
mov r4, r9
sub r4, r4, #8
bl asm_print_hex
ldr r4, =dfsr_str
bl asm_print_str
ldcopr r4, DFSR
bl asm_print_hex
ldr r4, =dfar_str
bl asm_print_str
ldcopr r4, DFAR
bl asm_print_hex
ldr r4, =end_error_str
bl asm_print_str
bx r8
endfunc plat_report_data_abort
#endif /* DEBUG */
func plat_reset_handler
bx lr
endfunc plat_reset_handler
/* ------------------------------------------------------------------
* unsigned long plat_get_my_entrypoint (void);
*
* Main job of this routine is to distinguish between a cold and warm
* boot.
*
* Currently supports only cold boot
* ------------------------------------------------------------------
*/
func plat_get_my_entrypoint
mov r0, #0
bx lr
endfunc plat_get_my_entrypoint
/* ---------------------------------------------
* void plat_secondary_cold_boot_setup (void);
*
* Cold-booting secondary CPUs is not supported.
* ---------------------------------------------
*/
func plat_secondary_cold_boot_setup
b .
endfunc plat_secondary_cold_boot_setup
/* -----------------------------------------------------
* unsigned int plat_is_my_cpu_primary (void);
*
* Find out whether the current cpu is the primary cpu.
* -----------------------------------------------------
*/
func plat_is_my_cpu_primary
ldcopr r0, MPIDR
ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
and r0, r1
cmp r0, #STM32MP_PRIMARY_CPU
moveq r0, #1
movne r0, #0
bx lr
endfunc plat_is_my_cpu_primary
/* -------------------------------------------
* int plat_stm32mp1_get_core_pos(int mpidr);
*
* Return CorePos = (ClusterId * 4) + CoreId
* -------------------------------------------
*/
func plat_stm32mp1_get_core_pos
and r1, r0, #MPIDR_CPU_MASK
and r0, r0, #MPIDR_CLUSTER_MASK
add r0, r1, r0, LSR #6
bx lr
endfunc plat_stm32mp1_get_core_pos
/* ------------------------------------
* unsigned int plat_my_core_pos(void)
* ------------------------------------
*/
func plat_my_core_pos
ldcopr r0, MPIDR
b plat_stm32mp1_get_core_pos
endfunc plat_my_core_pos
/* ---------------------------------------------
* int plat_crash_console_init(void)
*
* Initialize the crash console without a C Runtime stack.
* ---------------------------------------------
*/
func plat_crash_console_init
/* Reset UART peripheral */
ldr r1, =(RCC_BASE + DEBUG_UART_RST_REG)
ldr r2, =DEBUG_UART_RST_BIT
str r2, [r1]
1:
ldr r0, [r1]
ands r2, r0, r2
beq 1b
str r2, [r1, #4] /* RSTCLR register */
2:
ldr r0, [r1]
ands r2, r0, r2
bne 2b
/* Enable GPIOs for UART TX */
ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
ldr r2, [r1]
/* Configure GPIO */
orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
str r2, [r1]
ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS
/* Set GPIO mode alternate */
ldr r2, [r1, #GPIO_MODE_OFFSET]
bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
orr r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT)
str r2, [r1, #GPIO_MODE_OFFSET]
/* Set GPIO speed low */
ldr r2, [r1, #GPIO_SPEED_OFFSET]
bic r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT)
str r2, [r1, #GPIO_SPEED_OFFSET]
/* Set no-pull */
ldr r2, [r1, #GPIO_PUPD_OFFSET]
bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
str r2, [r1, #GPIO_PUPD_OFFSET]
/* Set alternate */
#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT
ldr r2, [r1, #GPIO_AFRH_OFFSET]
bic r2, r2, #(GPIO_ALTERNATE_MASK << \
((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \
((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
str r2, [r1, #GPIO_AFRH_OFFSET]
#else
ldr r2, [r1, #GPIO_AFRL_OFFSET]
bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
str r2, [r1, #GPIO_AFRL_OFFSET]
#endif
/* Enable UART clock, with its source */
ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
mov r2, #DEBUG_UART_TX_CLKSRC
str r2, [r1]
ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG)
ldr r2, [r1]
orr r2, r2, #DEBUG_UART_TX_EN
str r2, [r1]
ldr r0, =STM32MP_DEBUG_USART_BASE
ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ
ldr r2, =STM32MP_UART_BAUDRATE
b console_stm32_core_init
endfunc plat_crash_console_init
/* ---------------------------------------------
* void plat_crash_console_flush(void)
*
* Flush the crash console without a C Runtime stack.
* ---------------------------------------------
*/
func plat_crash_console_flush
ldr r0, =STM32MP_DEBUG_USART_BASE
b console_stm32_core_flush
endfunc plat_crash_console_flush
/* ---------------------------------------------
* int plat_crash_console_putc(int c)
*
* Print a character on the crash console without a C Runtime stack.
* Clobber list : r1 - r3
*
* In case of bootloading through uart, we keep console crash as this.
* Characters could be sent to the programmer, but will be ignored.
* No specific code in that case.
* ---------------------------------------------
*/
func plat_crash_console_putc
ldr r1, =STM32MP_DEBUG_USART_BASE
b console_stm32_core_putc
endfunc plat_crash_console_putc
/* ----------------------------------------------------------
* void plat_panic_handler(void) __dead2;
* Report exception + endless loop.
*
* r6 holds the address where the fault occurred.
* Filling lr with this value allows debuggers to reconstruct
* the backtrace.
* ----------------------------------------------------------
*/
func plat_panic_handler
mrs r0, cpsr
and r0, #MODE32_MASK
bl plat_report_exception
mov lr, r6
b .
endfunc plat_panic_handler
#if DEBUG
.section .rodata.rev_err_str, "aS"
prefetch_abort_str:
.asciz "\nPrefetch Abort at: 0x"
data_abort_str:
.asciz "\nData Abort at: 0x"
undefined_str:
.asciz "\nUndefined instruction at: 0x"
exception_start_str:
.asciz "\nException mode=0x"
exception_end_str:
.asciz " at: 0x"
dfsr_str:
.asciz " DFSR = 0x"
dfar_str:
.asciz " DFAR = 0x"
ifsr_str:
.asciz " IFSR = 0x"
ifar_str:
.asciz " IFAR = 0x"
end_error_str:
.asciz "\n\r"
#endif
@@ -0,0 +1,243 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <arch_helpers.h>
#include <bl32/sp_min/platform_sp_min.h>
#include <common/debug.h>
#include <drivers/arm/gic_common.h>
#include <drivers/arm/gicv2.h>
#include <drivers/clk.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
#include <plat/common/platform.h>
#include <platform_def.h>
static uintptr_t stm32_sec_entrypoint;
static uint32_t cntfrq_core0;
/*******************************************************************************
* STM32MP1 handler called when a CPU is about to enter standby.
* call by core 1 to enter in wfi
******************************************************************************/
static void stm32_cpu_standby(plat_local_state_t cpu_state)
{
uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
assert(cpu_state == ARM_LOCAL_STATE_RET);
/*
* Enter standby state
* dsb is good practice before using wfi to enter low power states
*/
isb();
dsb();
while (interrupt == GIC_SPURIOUS_INTERRUPT) {
wfi();
/* Acknoledge IT */
interrupt = gicv2_acknowledge_interrupt();
/* If Interrupt == 1022 it will be acknowledged by non secure */
if ((interrupt != PENDING_G1_INTID) &&
(interrupt != GIC_SPURIOUS_INTERRUPT)) {
gicv2_end_of_interrupt(interrupt);
}
}
}
/*******************************************************************************
* STM32MP1 handler called when a power domain is about to be turned on. The
* mpidr determines the CPU to be turned on.
* call by core 0 to activate core 1
******************************************************************************/
static int stm32_pwr_domain_on(u_register_t mpidr)
{
unsigned long current_cpu_mpidr = read_mpidr_el1();
uintptr_t bkpr_core1_addr =
tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
uintptr_t bkpr_core1_magic =
tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
if (mpidr == current_cpu_mpidr) {
return PSCI_E_INVALID_PARAMS;
}
/* Only one valid entry point */
if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) {
return PSCI_E_INVALID_ADDRESS;
}
clk_enable(RTCAPB);
cntfrq_core0 = read_cntfrq_el0();
/* Write entrypoint in backup RAM register */
mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint);
/* Write magic number in backup register */
mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER);
clk_disable(RTCAPB);
/* Generate an IT to core 1 */
gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, false, STM32MP_SECONDARY_CPU);
return PSCI_E_SUCCESS;
}
/*******************************************************************************
* STM32MP1 handler called when a power domain is about to be turned off. The
* target_state encodes the power state that each level should transition to.
******************************************************************************/
static void stm32_pwr_domain_off(const psci_power_state_t *target_state)
{
/* Nothing to do */
}
/*******************************************************************************
* STM32MP1 handler called when a power domain is about to be suspended. The
* target_state encodes the power state that each level should transition to.
******************************************************************************/
static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state)
{
/* Nothing to do, power domain is not disabled */
}
/*******************************************************************************
* STM32MP1 handler called when a power domain has just been powered on after
* being turned off earlier. The target_state encodes the low power state that
* each level has woken up from.
* call by core 1 just after wake up
******************************************************************************/
static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
stm32mp1_gic_pcpu_init();
write_cntfrq_el0(cntfrq_core0);
}
/*******************************************************************************
* STM32MP1 handler called when a power domain has just been powered on after
* having been suspended earlier. The target_state encodes the low power state
* that each level has woken up from.
******************************************************************************/
static void stm32_pwr_domain_suspend_finish(const psci_power_state_t
*target_state)
{
/* Nothing to do, power domain is not disabled */
}
static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
*target_state)
{
ERROR("stm32mpu1 Power Down WFI: operation not handled.\n");
panic();
}
static void __dead2 stm32_system_off(void)
{
ERROR("stm32mpu1 System Off: operation not handled.\n");
panic();
}
static void __dead2 stm32_system_reset(void)
{
mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
RCC_MP_GRSTCSETR_MPSYSRST);
/* Loop in case system reset is not immediately caught */
for ( ; ; ) {
;
}
}
static int stm32_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
int pstate = psci_get_pstate_type(power_state);
if (pstate != 0) {
return PSCI_E_INVALID_PARAMS;
}
if (psci_get_pstate_pwrlvl(power_state)) {
return PSCI_E_INVALID_PARAMS;
}
if (psci_get_pstate_id(power_state)) {
return PSCI_E_INVALID_PARAMS;
}
req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET;
req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN;
return PSCI_E_SUCCESS;
}
static int stm32_validate_ns_entrypoint(uintptr_t entrypoint)
{
/* The non-secure entry point must be in DDR */
if (entrypoint < STM32MP_DDR_BASE) {
return PSCI_E_INVALID_ADDRESS;
}
return PSCI_E_SUCCESS;
}
static int stm32_node_hw_state(u_register_t target_cpu,
unsigned int power_level)
{
/*
* The format of 'power_level' is implementation-defined, but 0 must
* mean a CPU. Only allow level 0.
*/
if (power_level != MPIDR_AFFLVL0) {
return PSCI_E_INVALID_PARAMS;
}
/*
* From psci view the CPU 0 is always ON,
* CPU 1 can be SUSPEND or RUNNING.
* Therefore do not manage POWER OFF state and always return HW_ON.
*/
return (int)HW_ON;
}
/*******************************************************************************
* Export the platform handlers. The ARM Standard platform layer will take care
* of registering the handlers with PSCI.
******************************************************************************/
static const plat_psci_ops_t stm32_psci_ops = {
.cpu_standby = stm32_cpu_standby,
.pwr_domain_on = stm32_pwr_domain_on,
.pwr_domain_off = stm32_pwr_domain_off,
.pwr_domain_suspend = stm32_pwr_domain_suspend,
.pwr_domain_on_finish = stm32_pwr_domain_on_finish,
.pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish,
.pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi,
.system_off = stm32_system_off,
.system_reset = stm32_system_reset,
.validate_power_state = stm32_validate_power_state,
.validate_ns_entrypoint = stm32_validate_ns_entrypoint,
.get_node_hw_state = stm32_node_hw_state
};
/*******************************************************************************
* Export the platform specific power ops.
******************************************************************************/
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
stm32_sec_entrypoint = sec_entrypoint;
*psci_ops = &stm32_psci_ops;
return 0;
}
@@ -0,0 +1,788 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <drivers/clk.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_iwdg.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <libfdt.h>
#include <plat/common/platform.h>
#include <platform_def.h>
/* Internal layout of the 32bit OTP word board_id */
#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16)
#define BOARD_ID_BOARD_NB_SHIFT 16
#define BOARD_ID_VARCPN_MASK GENMASK(15, 12)
#define BOARD_ID_VARCPN_SHIFT 12
#define BOARD_ID_REVISION_MASK GENMASK(11, 8)
#define BOARD_ID_REVISION_SHIFT 8
#define BOARD_ID_VARFG_MASK GENMASK(7, 4)
#define BOARD_ID_VARFG_SHIFT 4
#define BOARD_ID_BOM_MASK GENMASK(3, 0)
#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \
BOARD_ID_BOARD_NB_SHIFT)
#define BOARD_ID2VARCPN(_id) (((_id) & BOARD_ID_VARCPN_MASK) >> \
BOARD_ID_VARCPN_SHIFT)
#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \
BOARD_ID_REVISION_SHIFT)
#define BOARD_ID2VARFG(_id) (((_id) & BOARD_ID_VARFG_MASK) >> \
BOARD_ID_VARFG_SHIFT)
#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK)
#if STM32MP13
#define TAMP_BOOT_MODE_BACKUP_REG_ID U(30)
#endif
#if STM32MP15
#define TAMP_BOOT_MODE_BACKUP_REG_ID U(20)
#endif
#define TAMP_BOOT_MODE_ITF_MASK GENMASK(15, 8)
#define TAMP_BOOT_MODE_ITF_SHIFT 8
#define TAMP_BOOT_MODE_AUTH_MASK GENMASK(23, 16)
#define TAMP_BOOT_MODE_AUTH_SHIFT 16
/*
* Backup register to store fwu update information.
* It should be writeable only by secure world, but also readable by non secure
* (so it should be in Zone 2).
*/
#define TAMP_BOOT_FWU_INFO_REG_ID U(10)
#define TAMP_BOOT_FWU_INFO_IDX_MSK GENMASK(3, 0)
#define TAMP_BOOT_FWU_INFO_IDX_OFF U(0)
#define TAMP_BOOT_FWU_INFO_CNT_MSK GENMASK(7, 4)
#define TAMP_BOOT_FWU_INFO_CNT_OFF U(4)
#if defined(IMAGE_BL2)
#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
STM32MP_SYSRAM_SIZE, \
MT_MEMORY | \
MT_RW | \
MT_SECURE | \
MT_EXECUTE_NEVER)
#elif defined(IMAGE_BL32)
#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \
STM32MP_SEC_SYSRAM_SIZE, \
MT_MEMORY | \
MT_RW | \
MT_SECURE | \
MT_EXECUTE_NEVER)
/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */
#define MAP_NS_SYSRAM MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \
STM32MP_NS_SYSRAM_SIZE, \
MT_DEVICE | \
MT_RW | \
MT_NS | \
MT_EXECUTE_NEVER)
#endif
#if STM32MP13
#define MAP_SRAM_ALL MAP_REGION_FLAT(SRAMS_BASE, \
SRAMS_SIZE_2MB_ALIGNED, \
MT_MEMORY | \
MT_RW | \
MT_SECURE | \
MT_EXECUTE_NEVER)
#endif
#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
STM32MP1_DEVICE1_SIZE, \
MT_DEVICE | \
MT_RW | \
MT_SECURE | \
MT_EXECUTE_NEVER)
#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \
STM32MP1_DEVICE2_SIZE, \
MT_DEVICE | \
MT_RW | \
MT_SECURE | \
MT_EXECUTE_NEVER)
#if defined(IMAGE_BL2)
static const mmap_region_t stm32mp1_mmap[] = {
MAP_SEC_SYSRAM,
#if STM32MP13
MAP_SRAM_ALL,
#endif
MAP_DEVICE1,
#if STM32MP_RAW_NAND
MAP_DEVICE2,
#endif
{0}
};
#endif
#if defined(IMAGE_BL32)
static const mmap_region_t stm32mp1_mmap[] = {
MAP_SEC_SYSRAM,
MAP_NS_SYSRAM,
MAP_DEVICE1,
MAP_DEVICE2,
{0}
};
#endif
void configure_mmu(void)
{
mmap_add(stm32mp1_mmap);
init_xlat_tables();
enable_mmu_svc_mon(0);
}
uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
{
#if STM32MP13
assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
#endif
#if STM32MP15
if (bank == GPIO_BANK_Z) {
return GPIOZ_BASE;
}
assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
#endif
return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
}
uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
{
#if STM32MP13
assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
#endif
#if STM32MP15
if (bank == GPIO_BANK_Z) {
return 0;
}
assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
#endif
return bank * GPIO_BANK_OFFSET;
}
bool stm32_gpio_is_secure_at_reset(unsigned int bank)
{
#if STM32MP13
return true;
#endif
#if STM32MP15
if (bank == GPIO_BANK_Z) {
return true;
}
return false;
#endif
}
unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
{
#if STM32MP13
assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
#endif
#if STM32MP15
if (bank == GPIO_BANK_Z) {
return GPIOZ;
}
assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
#endif
return GPIOA + (bank - GPIO_BANK_A);
}
int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank)
{
const char *node_compatible = NULL;
switch (bank) {
case GPIO_BANK_A:
case GPIO_BANK_B:
case GPIO_BANK_C:
case GPIO_BANK_D:
case GPIO_BANK_E:
case GPIO_BANK_F:
case GPIO_BANK_G:
case GPIO_BANK_H:
case GPIO_BANK_I:
#if STM32MP13
node_compatible = "st,stm32mp135-pinctrl";
break;
#endif
#if STM32MP15
case GPIO_BANK_J:
case GPIO_BANK_K:
node_compatible = "st,stm32mp157-pinctrl";
break;
case GPIO_BANK_Z:
node_compatible = "st,stm32mp157-z-pinctrl";
break;
#endif
default:
panic();
}
return fdt_node_offset_by_compatible(fdt, -1, node_compatible);
}
#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
/*
* UART Management
*/
static const uintptr_t stm32mp1_uart_addresses[8] = {
USART1_BASE,
USART2_BASE,
USART3_BASE,
UART4_BASE,
UART5_BASE,
USART6_BASE,
UART7_BASE,
UART8_BASE,
};
uintptr_t get_uart_address(uint32_t instance_nb)
{
if ((instance_nb == 0U) ||
(instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) {
return 0U;
}
return stm32mp1_uart_addresses[instance_nb - 1U];
}
#endif
#if STM32MP_USB_PROGRAMMER
struct gpio_bank_pin_list {
uint32_t bank;
uint32_t pin;
};
static const struct gpio_bank_pin_list gpio_list[] = {
{ /* USART2_RX: GPIOA3 */
.bank = 0U,
.pin = 3U,
},
{ /* USART3_RX: GPIOB12 */
.bank = 1U,
.pin = 12U,
},
{ /* UART4_RX: GPIOB2 */
.bank = 1U,
.pin = 2U,
},
{ /* UART5_RX: GPIOB4 */
.bank = 1U,
.pin = 5U,
},
{ /* USART6_RX: GPIOC7 */
.bank = 2U,
.pin = 7U,
},
{ /* UART7_RX: GPIOF6 */
.bank = 5U,
.pin = 6U,
},
{ /* UART8_RX: GPIOE0 */
.bank = 4U,
.pin = 0U,
},
};
void stm32mp1_deconfigure_uart_pins(void)
{
size_t i;
for (i = 0U; i < ARRAY_SIZE(gpio_list); i++) {
set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin);
}
}
#endif
uint32_t stm32mp_get_chip_version(void)
{
#if STM32MP13
return stm32mp1_syscfg_get_chip_version();
#endif
#if STM32MP15
uint32_t version = 0U;
if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) {
INFO("Cannot get CPU version, debug disabled\n");
return 0U;
}
return version;
#endif
}
uint32_t stm32mp_get_chip_dev_id(void)
{
#if STM32MP13
return stm32mp1_syscfg_get_chip_dev_id();
#endif
#if STM32MP15
uint32_t dev_id;
if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) {
INFO("Use default chip ID, debug disabled\n");
dev_id = STM32MP1_CHIP_ID;
}
return dev_id;
#endif
}
static uint32_t get_part_number(void)
{
static uint32_t part_number;
if (part_number != 0U) {
return part_number;
}
if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) {
panic();
}
part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >>
PART_NUMBER_OTP_PART_SHIFT;
part_number |= stm32mp_get_chip_dev_id() << 16;
return part_number;
}
#if STM32MP15
static uint32_t get_cpu_package(void)
{
uint32_t package;
if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) {
panic();
}
package = (package & PACKAGE_OTP_PKG_MASK) >>
PACKAGE_OTP_PKG_SHIFT;
return package;
}
#endif
void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE])
{
char *cpu_s, *cpu_r, *pkg;
/* MPUs Part Numbers */
switch (get_part_number()) {
#if STM32MP13
case STM32MP135F_PART_NB:
cpu_s = "135F";
break;
case STM32MP135D_PART_NB:
cpu_s = "135D";
break;
case STM32MP135C_PART_NB:
cpu_s = "135C";
break;
case STM32MP135A_PART_NB:
cpu_s = "135A";
break;
case STM32MP133F_PART_NB:
cpu_s = "133F";
break;
case STM32MP133D_PART_NB:
cpu_s = "133D";
break;
case STM32MP133C_PART_NB:
cpu_s = "133C";
break;
case STM32MP133A_PART_NB:
cpu_s = "133A";
break;
case STM32MP131F_PART_NB:
cpu_s = "131F";
break;
case STM32MP131D_PART_NB:
cpu_s = "131D";
break;
case STM32MP131C_PART_NB:
cpu_s = "131C";
break;
case STM32MP131A_PART_NB:
cpu_s = "131A";
break;
#endif
#if STM32MP15
case STM32MP157C_PART_NB:
cpu_s = "157C";
break;
case STM32MP157A_PART_NB:
cpu_s = "157A";
break;
case STM32MP153C_PART_NB:
cpu_s = "153C";
break;
case STM32MP153A_PART_NB:
cpu_s = "153A";
break;
case STM32MP151C_PART_NB:
cpu_s = "151C";
break;
case STM32MP151A_PART_NB:
cpu_s = "151A";
break;
case STM32MP157F_PART_NB:
cpu_s = "157F";
break;
case STM32MP157D_PART_NB:
cpu_s = "157D";
break;
case STM32MP153F_PART_NB:
cpu_s = "153F";
break;
case STM32MP153D_PART_NB:
cpu_s = "153D";
break;
case STM32MP151F_PART_NB:
cpu_s = "151F";
break;
case STM32MP151D_PART_NB:
cpu_s = "151D";
break;
#endif
default:
cpu_s = "????";
break;
}
/* Package */
#if STM32MP13
/* On STM32MP13, package is not present in OTP */
pkg = "";
#endif
#if STM32MP15
switch (get_cpu_package()) {
case PKG_AA_LFBGA448:
pkg = "AA";
break;
case PKG_AB_LFBGA354:
pkg = "AB";
break;
case PKG_AC_TFBGA361:
pkg = "AC";
break;
case PKG_AD_TFBGA257:
pkg = "AD";
break;
default:
pkg = "??";
break;
}
#endif
/* REVISION */
switch (stm32mp_get_chip_version()) {
case STM32MP1_REV_B:
cpu_r = "B";
break;
#if STM32MP13
case STM32MP1_REV_Y:
cpu_r = "Y";
break;
#endif
case STM32MP1_REV_Z:
cpu_r = "Z";
break;
default:
cpu_r = "?";
break;
}
snprintf(name, STM32_SOC_NAME_SIZE,
"STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r);
}
void stm32mp_print_cpuinfo(void)
{
char name[STM32_SOC_NAME_SIZE];
stm32mp_get_soc_name(name);
NOTICE("CPU: %s\n", name);
}
void stm32mp_print_boardinfo(void)
{
uint32_t board_id = 0;
if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) {
return;
}
if (board_id != 0U) {
char rev[2];
rev[0] = BOARD_ID2REV(board_id) - 1 + 'A';
rev[1] = '\0';
NOTICE("Board: MB%04x Var%u.%u Rev.%s-%02u\n",
BOARD_ID2NB(board_id),
BOARD_ID2VARCPN(board_id),
BOARD_ID2VARFG(board_id),
rev,
BOARD_ID2BOM(board_id));
}
}
/* Return true when SoC provides a single Cortex-A7 core, and false otherwise */
bool stm32mp_is_single_core(void)
{
#if STM32MP13
return true;
#endif
#if STM32MP15
bool single_core = false;
switch (get_part_number()) {
case STM32MP151A_PART_NB:
case STM32MP151C_PART_NB:
case STM32MP151D_PART_NB:
case STM32MP151F_PART_NB:
single_core = true;
break;
default:
break;
}
return single_core;
#endif
}
/* Return true when device is in closed state */
bool stm32mp_is_closed_device(void)
{
uint32_t value;
if (stm32_get_otp_value(CFG0_OTP, &value) != 0) {
return true;
}
#if STM32MP13
value = (value & CFG0_OTP_MODE_MASK) >> CFG0_OTP_MODE_SHIFT;
switch (value) {
case CFG0_OPEN_DEVICE:
return false;
case CFG0_CLOSED_DEVICE:
case CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN:
case CFG0_CLOSED_DEVICE_NO_JTAG:
return true;
default:
panic();
}
#endif
#if STM32MP15
return (value & CFG0_CLOSED_DEVICE) == CFG0_CLOSED_DEVICE;
#endif
}
/* Return true when device supports secure boot */
bool stm32mp_is_auth_supported(void)
{
bool supported = false;
switch (get_part_number()) {
#if STM32MP13
case STM32MP131C_PART_NB:
case STM32MP131F_PART_NB:
case STM32MP133C_PART_NB:
case STM32MP133F_PART_NB:
case STM32MP135C_PART_NB:
case STM32MP135F_PART_NB:
#endif
#if STM32MP15
case STM32MP151C_PART_NB:
case STM32MP151F_PART_NB:
case STM32MP153C_PART_NB:
case STM32MP153F_PART_NB:
case STM32MP157C_PART_NB:
case STM32MP157F_PART_NB:
#endif
supported = true;
break;
default:
break;
}
return supported;
}
uint32_t stm32_iwdg_get_instance(uintptr_t base)
{
switch (base) {
case IWDG1_BASE:
return IWDG1_INST;
case IWDG2_BASE:
return IWDG2_INST;
default:
panic();
}
}
uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst)
{
uint32_t iwdg_cfg = 0U;
uint32_t otp_value;
if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
panic();
}
if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_HW_POS)) != 0U) {
iwdg_cfg |= IWDG_HW_ENABLED;
}
if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS)) != 0U) {
iwdg_cfg |= IWDG_DISABLE_ON_STOP;
}
if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS)) != 0U) {
iwdg_cfg |= IWDG_DISABLE_ON_STANDBY;
}
return iwdg_cfg;
}
#if defined(IMAGE_BL2)
uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags)
{
uint32_t otp_value;
uint32_t otp;
uint32_t result;
if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) {
panic();
}
if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
panic();
}
if ((flags & IWDG_DISABLE_ON_STOP) != 0) {
otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS);
}
if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) {
otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS);
}
result = bsec_write_otp(otp_value, otp);
if (result != BSEC_OK) {
return result;
}
/* Sticky lock OTP_IWDG (read and write) */
if ((bsec_set_sr_lock(otp) != BSEC_OK) ||
(bsec_set_sw_lock(otp) != BSEC_OK)) {
return BSEC_LOCK_FAIL;
}
return BSEC_OK;
}
#endif
void stm32_save_boot_interface(uint32_t interface, uint32_t instance)
{
uintptr_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
clk_enable(RTCAPB);
mmio_clrsetbits_32(bkpr_itf_idx,
TAMP_BOOT_MODE_ITF_MASK,
((interface << 4) | (instance & 0xFU)) <<
TAMP_BOOT_MODE_ITF_SHIFT);
clk_disable(RTCAPB);
}
void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
{
static uint32_t itf;
if (itf == 0U) {
uintptr_t bkpr = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
clk_enable(RTCAPB);
itf = (mmio_read_32(bkpr) & TAMP_BOOT_MODE_ITF_MASK) >>
TAMP_BOOT_MODE_ITF_SHIFT;
clk_disable(RTCAPB);
}
*interface = itf >> 4;
*instance = itf & 0xFU;
}
void stm32_save_boot_auth(uint32_t auth_status, uint32_t boot_partition)
{
uint32_t boot_status = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
clk_enable(RTCAPB);
mmio_clrsetbits_32(boot_status,
TAMP_BOOT_MODE_AUTH_MASK,
((auth_status << 4) | (boot_partition & 0xFU)) <<
TAMP_BOOT_MODE_AUTH_SHIFT);
clk_disable(RTCAPB);
}
#if PSA_FWU_SUPPORT
void stm32mp1_fwu_set_boot_idx(void)
{
clk_enable(RTCAPB);
mmio_clrsetbits_32(tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID),
TAMP_BOOT_FWU_INFO_IDX_MSK,
(plat_fwu_get_boot_idx() << TAMP_BOOT_FWU_INFO_IDX_OFF) &
TAMP_BOOT_FWU_INFO_IDX_MSK);
clk_disable(RTCAPB);
}
uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void)
{
uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID);
uint32_t try_cnt;
clk_enable(RTCAPB);
try_cnt = (mmio_read_32(bkpr_fwu_cnt) & TAMP_BOOT_FWU_INFO_CNT_MSK) >>
TAMP_BOOT_FWU_INFO_CNT_OFF;
assert(try_cnt <= FWU_MAX_TRIAL_REBOOT);
if (try_cnt != 0U) {
mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK,
(try_cnt - 1U) << TAMP_BOOT_FWU_INFO_CNT_OFF);
}
clk_disable(RTCAPB);
return try_cnt;
}
void stm32_set_max_fwu_trial_boot_cnt(void)
{
uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID);
clk_enable(RTCAPB);
mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK,
(FWU_MAX_TRIAL_REBOOT << TAMP_BOOT_FWU_INFO_CNT_OFF) &
TAMP_BOOT_FWU_INFO_CNT_MSK);
clk_disable(RTCAPB);
}
#endif /* PSA_FWU_SUPPORT */
@@ -0,0 +1,479 @@
/*
* Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <platform_def.h>
#include <drivers/clk.h>
#include <drivers/scmi-msg.h>
#include <drivers/scmi.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp_reset.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
#define TIMEOUT_US_1MS 1000U
#define SCMI_CLOCK_NAME_SIZE 16U
#define SCMI_RSTD_NAME_SIZE 16U
/*
* struct stm32_scmi_clk - Data for the exposed clock
* @clock_id: Clock identifier in RCC clock driver
* @name: Clock string ID exposed to agent
* @enabled: State of the SCMI clock
*/
struct stm32_scmi_clk {
unsigned long clock_id;
const char *name;
bool enabled;
};
/*
* struct stm32_scmi_rstd - Data for the exposed reset controller
* @reset_id: Reset identifier in RCC reset driver
* @name: Reset string ID exposed to agent
*/
struct stm32_scmi_rstd {
unsigned long reset_id;
const char *name;
};
/* Locate all non-secure SMT message buffers in last page of SYSRAM */
#define SMT_BUFFER_BASE STM32MP_SCMI_NS_SHM_BASE
#define SMT_BUFFER0_BASE SMT_BUFFER_BASE
#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200)
CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >=
(SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE),
assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size);
static struct scmi_msg_channel scmi_channel[] = {
[0] = {
.shm_addr = SMT_BUFFER0_BASE,
.shm_size = SMT_BUF_SLOT_SIZE,
},
[1] = {
.shm_addr = SMT_BUFFER1_BASE,
.shm_size = SMT_BUF_SLOT_SIZE,
},
};
struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
{
assert(agent_id < ARRAY_SIZE(scmi_channel));
return &scmi_channel[agent_id];
}
#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
[_scmi_id] = { \
.clock_id = _id, \
.name = _name, \
.enabled = _init_enabled, \
}
static struct stm32_scmi_clk stm32_scmi0_clock[] = {
CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
};
static struct stm32_scmi_clk stm32_scmi1_clock[] = {
CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
};
#define RESET_CELL(_scmi_id, _id, _name) \
[_scmi_id] = { \
.reset_id = _id, \
.name = _name, \
}
static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
};
struct scmi_agent_resources {
struct stm32_scmi_clk *clock;
size_t clock_count;
struct stm32_scmi_rstd *rstd;
size_t rstd_count;
};
static const struct scmi_agent_resources agent_resources[] = {
[0] = {
.clock = stm32_scmi0_clock,
.clock_count = ARRAY_SIZE(stm32_scmi0_clock),
.rstd = stm32_scmi0_reset_domain,
.rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
},
[1] = {
.clock = stm32_scmi1_clock,
.clock_count = ARRAY_SIZE(stm32_scmi1_clock),
},
};
static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
{
assert(agent_id < ARRAY_SIZE(agent_resources));
return &agent_resources[agent_id];
}
#if ENABLE_ASSERTIONS
static size_t plat_scmi_protocol_count_paranoid(void)
{
unsigned int n = 0U;
unsigned int count = 0U;
for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
if (agent_resources[n].clock_count) {
count++;
break;
}
}
for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
if (agent_resources[n].rstd_count) {
count++;
break;
}
}
return count;
}
#endif
static const char vendor[] = "ST";
static const char sub_vendor[] = "";
const char *plat_scmi_vendor_name(void)
{
return vendor;
}
const char *plat_scmi_sub_vendor_name(void)
{
return sub_vendor;
}
/* Currently supporting Clocks and Reset Domains */
static const uint8_t plat_protocol_list[] = {
SCMI_PROTOCOL_ID_CLOCK,
SCMI_PROTOCOL_ID_RESET_DOMAIN,
0U /* Null termination */
};
size_t plat_scmi_protocol_count(void)
{
const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
assert(count == plat_scmi_protocol_count_paranoid());
return count;
}
const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
{
assert(plat_scmi_protocol_count_paranoid() ==
(ARRAY_SIZE(plat_protocol_list) - 1U));
return plat_protocol_list;
}
/*
* Platform SCMI clocks
*/
static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
unsigned int scmi_id)
{
const struct scmi_agent_resources *resource = find_resource(agent_id);
size_t n = 0U;
if (resource != NULL) {
for (n = 0U; n < resource->clock_count; n++) {
if (n == scmi_id) {
return &resource->clock[n];
}
}
}
return NULL;
}
size_t plat_scmi_clock_count(unsigned int agent_id)
{
const struct scmi_agent_resources *resource = find_resource(agent_id);
if (resource == NULL) {
return 0U;
}
return resource->clock_count;
}
const char *plat_scmi_clock_get_name(unsigned int agent_id,
unsigned int scmi_id)
{
struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
if ((clock == NULL) ||
!stm32mp_nsec_can_access_clock(clock->clock_id)) {
return NULL;
}
return clock->name;
}
int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
unsigned long *array, size_t *nb_elts)
{
struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
if (clock == NULL) {
return SCMI_NOT_FOUND;
}
if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
return SCMI_DENIED;
}
if (array == NULL) {
*nb_elts = 1U;
} else if (*nb_elts == 1U) {
*array = clk_get_rate(clock->clock_id);
} else {
return SCMI_GENERIC_ERROR;
}
return SCMI_SUCCESS;
}
unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
unsigned int scmi_id)
{
struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
if ((clock == NULL) ||
!stm32mp_nsec_can_access_clock(clock->clock_id)) {
return 0U;
}
return clk_get_rate(clock->clock_id);
}
int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
{
struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
if ((clock == NULL) ||
!stm32mp_nsec_can_access_clock(clock->clock_id)) {
return 0U;
}
return (int32_t)clock->enabled;
}
int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
bool enable_not_disable)
{
struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
if (clock == NULL) {
return SCMI_NOT_FOUND;
}
if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
return SCMI_DENIED;
}
if (enable_not_disable) {
if (!clock->enabled) {
VERBOSE("SCMI clock %u enable\n", scmi_id);
clk_enable(clock->clock_id);
clock->enabled = true;
}
} else {
if (clock->enabled) {
VERBOSE("SCMI clock %u disable\n", scmi_id);
clk_disable(clock->clock_id);
clock->enabled = false;
}
}
return SCMI_SUCCESS;
}
/*
* Platform SCMI reset domains
*/
static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
unsigned int scmi_id)
{
const struct scmi_agent_resources *resource = find_resource(agent_id);
size_t n;
if (resource != NULL) {
for (n = 0U; n < resource->rstd_count; n++) {
if (n == scmi_id) {
return &resource->rstd[n];
}
}
}
return NULL;
}
const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
{
const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
if (rstd == NULL) {
return NULL;
}
return rstd->name;
}
size_t plat_scmi_rstd_count(unsigned int agent_id)
{
const struct scmi_agent_resources *resource = find_resource(agent_id);
if (resource == NULL) {
return 0U;
}
return resource->rstd_count;
}
int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
uint32_t state)
{
const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
if (rstd == NULL) {
return SCMI_NOT_FOUND;
}
if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
return SCMI_DENIED;
}
/* Supports only reset with context loss */
if (state != 0U) {
return SCMI_NOT_SUPPORTED;
}
VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
return SCMI_HARDWARE_ERROR;
}
if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
return SCMI_HARDWARE_ERROR;
}
return SCMI_SUCCESS;
}
int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
bool assert_not_deassert)
{
const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
if (rstd == NULL) {
return SCMI_NOT_FOUND;
}
if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
return SCMI_DENIED;
}
if (assert_not_deassert) {
VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
stm32mp_reset_set(rstd->reset_id);
} else {
VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
stm32mp_reset_release(rstd->reset_id);
}
return SCMI_SUCCESS;
}
/*
* Initialize platform SCMI resources
*/
void stm32mp1_init_scmi_server(void)
{
size_t i;
for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
scmi_smt_init_agent_channel(&scmi_channel[i]);
}
for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
const struct scmi_agent_resources *res = &agent_resources[i];
size_t j;
for (j = 0U; j < res->clock_count; j++) {
struct stm32_scmi_clk *clk = &res->clock[j];
if ((clk->name == NULL) ||
(strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
ERROR("Invalid SCMI clock name\n");
panic();
}
/* Sync SCMI clocks with their targeted initial state */
if (clk->enabled &&
stm32mp_nsec_can_access_clock(clk->clock_id)) {
clk_enable(clk->clock_id);
}
}
for (j = 0U; j < res->rstd_count; j++) {
struct stm32_scmi_rstd *rstd = &res->rstd[j];
if ((rstd->name == NULL) ||
(strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
ERROR("Invalid SCMI reset domain name\n");
panic();
}
}
}
}
@@ -0,0 +1,596 @@
/*
* Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <common/debug.h>
#include <drivers/st/etzpc.h>
#include <drivers/st/stm32_gpio.h>
#include <platform_def.h>
#include <stm32mp_shared_resources.h>
/*
* Once one starts to get the resource registering state, one cannot register
* new resources. This ensures resource state cannot change.
*/
static bool registering_locked;
/*
* Shared peripherals and resources registration
*
* Each resource assignation is stored in a table. The state defaults
* to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
*
* Resource driver that as not embedded (a.k.a their related CFG_xxx build
* directive is disabled) are assigned to the non-secure world.
*
* Each pin of the GPIOZ bank can be secure or non-secure.
*
* It is the platform responsibility the ensure resource assignation
* matches the access permission firewalls configuration.
*/
enum shres_state {
SHRES_UNREGISTERED = 0,
SHRES_SECURE,
SHRES_NON_SECURE,
};
/* Force uint8_t array for array of enum shres_state for size considerations */
static uint8_t shres_state[STM32MP1_SHRES_COUNT];
static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
[STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
[STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
[STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
[STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
[STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
[STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
[STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
[STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
[STM32MP1_SHRES_IWDG1] = "IWDG1",
[STM32MP1_SHRES_USART1] = "USART1",
[STM32MP1_SHRES_SPI6] = "SPI6",
[STM32MP1_SHRES_I2C4] = "I2C4",
[STM32MP1_SHRES_RNG1] = "RNG1",
[STM32MP1_SHRES_HASH1] = "HASH1",
[STM32MP1_SHRES_CRYP1] = "CRYP1",
[STM32MP1_SHRES_I2C6] = "I2C6",
[STM32MP1_SHRES_RTC] = "RTC",
[STM32MP1_SHRES_MCU] = "MCU",
[STM32MP1_SHRES_MDMA] = "MDMA",
[STM32MP1_SHRES_PLL3] = "PLL3",
};
static const char __unused *shres2str_id(enum stm32mp_shres id)
{
assert(id < ARRAY_SIZE(shres2str_id_tbl));
return shres2str_id_tbl[id];
}
static const char __unused *shres2str_state_tbl[] = {
[SHRES_UNREGISTERED] = "unregistered",
[SHRES_NON_SECURE] = "non-secure",
[SHRES_SECURE] = "secure",
};
static const char __unused *shres2str_state(unsigned int state)
{
assert(state < ARRAY_SIZE(shres2str_state_tbl));
return shres2str_state_tbl[state];
}
/* Get resource state: these accesses lock the registering support */
static void lock_registering(void)
{
registering_locked = true;
}
static bool periph_is_non_secure(enum stm32mp_shres id)
{
lock_registering();
return (shres_state[id] == SHRES_NON_SECURE) ||
(shres_state[id] == SHRES_UNREGISTERED);
}
static bool periph_is_secure(enum stm32mp_shres id)
{
return !periph_is_non_secure(id);
}
/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
static int8_t gpioz_nbpin = -1;
static unsigned int get_gpio_nbpin(unsigned int bank)
{
if (bank != GPIO_BANK_Z) {
int count = fdt_get_gpio_bank_pin_count(bank);
assert((count >= 0) && ((unsigned int)count <= (GPIO_PIN_MAX + 1)));
return (unsigned int)count;
}
if (gpioz_nbpin < 0) {
int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
gpioz_nbpin = count;
}
return (unsigned int)gpioz_nbpin;
}
static unsigned int get_gpioz_nbpin(void)
{
return get_gpio_nbpin(GPIO_BANK_Z);
}
static void register_periph(enum stm32mp_shres id, unsigned int state)
{
assert((id < STM32MP1_SHRES_COUNT) &&
((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
if (registering_locked) {
if (shres_state[id] == state) {
return;
}
panic();
}
if ((shres_state[id] != SHRES_UNREGISTERED) &&
(shres_state[id] != state)) {
VERBOSE("Cannot change %s from %s to %s\n",
shres2str_id(id),
shres2str_state(shres_state[id]),
shres2str_state(state));
panic();
}
if (shres_state[id] == SHRES_UNREGISTERED) {
VERBOSE("Register %s as %s\n",
shres2str_id(id), shres2str_state(state));
}
if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
(id <= STM32MP1_SHRES_GPIOZ(7)) &&
((unsigned int)(id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
ERROR("Invalid GPIO pin %d, %u pin(s) available\n",
(int)(id - STM32MP1_SHRES_GPIOZ(0)), get_gpioz_nbpin());
panic();
}
shres_state[id] = (uint8_t)state;
/* Explore clock tree to lock dependencies */
if (state == SHRES_SECURE) {
enum stm32mp_shres clock_res_id;
switch (id) {
case STM32MP1_SHRES_GPIOZ(0):
case STM32MP1_SHRES_GPIOZ(1):
case STM32MP1_SHRES_GPIOZ(2):
case STM32MP1_SHRES_GPIOZ(3):
case STM32MP1_SHRES_GPIOZ(4):
case STM32MP1_SHRES_GPIOZ(5):
case STM32MP1_SHRES_GPIOZ(6):
case STM32MP1_SHRES_GPIOZ(7):
clock_res_id = GPIOZ;
break;
case STM32MP1_SHRES_IWDG1:
clock_res_id = IWDG1;
break;
case STM32MP1_SHRES_USART1:
clock_res_id = USART1_K;
break;
case STM32MP1_SHRES_SPI6:
clock_res_id = SPI6_K;
break;
case STM32MP1_SHRES_I2C4:
clock_res_id = I2C4_K;
break;
case STM32MP1_SHRES_RNG1:
clock_res_id = RNG1_K;
break;
case STM32MP1_SHRES_HASH1:
clock_res_id = HASH1;
break;
case STM32MP1_SHRES_CRYP1:
clock_res_id = CRYP1;
break;
case STM32MP1_SHRES_I2C6:
clock_res_id = I2C6_K;
break;
case STM32MP1_SHRES_RTC:
clock_res_id = RTC;
break;
default:
/* No clock resource dependency */
return;
}
stm32mp1_register_clock_parents_secure(clock_res_id);
}
}
/* Register resource by ID */
void stm32mp_register_secure_periph(enum stm32mp_shres id)
{
register_periph(id, SHRES_SECURE);
}
void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
{
register_periph(id, SHRES_NON_SECURE);
}
static void register_periph_iomem(uintptr_t base, unsigned int state)
{
enum stm32mp_shres id;
switch (base) {
case CRYP1_BASE:
id = STM32MP1_SHRES_CRYP1;
break;
case HASH1_BASE:
id = STM32MP1_SHRES_HASH1;
break;
case I2C4_BASE:
id = STM32MP1_SHRES_I2C4;
break;
case I2C6_BASE:
id = STM32MP1_SHRES_I2C6;
break;
case IWDG1_BASE:
id = STM32MP1_SHRES_IWDG1;
break;
case RNG1_BASE:
id = STM32MP1_SHRES_RNG1;
break;
case RTC_BASE:
id = STM32MP1_SHRES_RTC;
break;
case SPI6_BASE:
id = STM32MP1_SHRES_SPI6;
break;
case USART1_BASE:
id = STM32MP1_SHRES_USART1;
break;
case GPIOA_BASE:
case GPIOB_BASE:
case GPIOC_BASE:
case GPIOD_BASE:
case GPIOE_BASE:
case GPIOF_BASE:
case GPIOG_BASE:
case GPIOH_BASE:
case GPIOI_BASE:
case GPIOJ_BASE:
case GPIOK_BASE:
case USART2_BASE:
case USART3_BASE:
case UART4_BASE:
case UART5_BASE:
case USART6_BASE:
case UART7_BASE:
case UART8_BASE:
case IWDG2_BASE:
/* Allow drivers to register some non-secure resources */
VERBOSE("IO for non-secure resource 0x%x\n",
(unsigned int)base);
if (state != SHRES_NON_SECURE) {
panic();
}
return;
default:
panic();
}
register_periph(id, state);
}
void stm32mp_register_secure_periph_iomem(uintptr_t base)
{
register_periph_iomem(base, SHRES_SECURE);
}
void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
{
register_periph_iomem(base, SHRES_NON_SECURE);
}
void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
{
switch (bank) {
case GPIO_BANK_Z:
register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
break;
default:
ERROR("GPIO bank %u cannot be secured\n", bank);
panic();
}
}
void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
{
switch (bank) {
case GPIO_BANK_Z:
register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
break;
default:
break;
}
}
static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
{
unsigned int non_secure = 0U;
unsigned int i;
lock_registering();
if (bank != GPIO_BANK_Z) {
return true;
}
for (i = 0U; i < get_gpioz_nbpin(); i++) {
if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
non_secure++;
}
}
return non_secure == get_gpioz_nbpin();
}
static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
{
unsigned int secure = 0U;
unsigned int i;
lock_registering();
if (bank != GPIO_BANK_Z) {
return false;
}
for (i = 0U; i < get_gpioz_nbpin(); i++) {
if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
secure++;
}
}
return secure == get_gpioz_nbpin();
}
bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
{
enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
switch (clock_id) {
case CK_CSI:
case CK_HSE:
case CK_HSE_DIV2:
case CK_HSI:
case CK_LSE:
case CK_LSI:
case PLL1_P:
case PLL1_Q:
case PLL1_R:
case PLL2_P:
case PLL2_Q:
case PLL2_R:
case PLL3_P:
case PLL3_Q:
case PLL3_R:
case RTCAPB:
return true;
case GPIOZ:
/* Allow clock access if at least one pin is non-secure */
return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
case CRYP1:
shres_id = STM32MP1_SHRES_CRYP1;
break;
case HASH1:
shres_id = STM32MP1_SHRES_HASH1;
break;
case I2C4_K:
shres_id = STM32MP1_SHRES_I2C4;
break;
case I2C6_K:
shres_id = STM32MP1_SHRES_I2C6;
break;
case IWDG1:
shres_id = STM32MP1_SHRES_IWDG1;
break;
case RNG1_K:
shres_id = STM32MP1_SHRES_RNG1;
break;
case RTC:
shres_id = STM32MP1_SHRES_RTC;
break;
case SPI6_K:
shres_id = STM32MP1_SHRES_SPI6;
break;
case USART1_K:
shres_id = STM32MP1_SHRES_USART1;
break;
default:
return false;
}
return periph_is_non_secure(shres_id);
}
bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
{
enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
switch (reset_id) {
case CRYP1_R:
shres_id = STM32MP1_SHRES_CRYP1;
break;
case GPIOZ_R:
/* GPIOZ reset mandates all pins are non-secure */
return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
case HASH1_R:
shres_id = STM32MP1_SHRES_HASH1;
break;
case I2C4_R:
shres_id = STM32MP1_SHRES_I2C4;
break;
case I2C6_R:
shres_id = STM32MP1_SHRES_I2C6;
break;
case MCU_R:
shres_id = STM32MP1_SHRES_MCU;
break;
case MDMA_R:
shres_id = STM32MP1_SHRES_MDMA;
break;
case RNG1_R:
shres_id = STM32MP1_SHRES_RNG1;
break;
case SPI6_R:
shres_id = STM32MP1_SHRES_SPI6;
break;
case USART1_R:
shres_id = STM32MP1_SHRES_USART1;
break;
default:
return false;
}
return periph_is_non_secure(shres_id);
}
static bool mckprot_protects_periph(enum stm32mp_shres id)
{
switch (id) {
case STM32MP1_SHRES_MCU:
case STM32MP1_SHRES_PLL3:
return true;
default:
return false;
}
}
/* ETZPC configuration at drivers initialization completion */
static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
{
assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
(id > STM32MP1_SHRES_GPIOZ(7)));
if (periph_is_non_secure(id)) {
return ETZPC_DECPROT_NS_RW;
}
return ETZPC_DECPROT_S_RW;
}
static void set_etzpc_secure_configuration(void)
{
/* Some system peripherals shall be secure */
etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
ETZPC_DECPROT_NS_R_S_W);
etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
ETZPC_DECPROT_NS_R_S_W);
/* Configure ETZPC with peripheral registering */
etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
shres2decprot_attr(STM32MP1_SHRES_CRYP1));
etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
shres2decprot_attr(STM32MP1_SHRES_HASH1));
etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
shres2decprot_attr(STM32MP1_SHRES_I2C4));
etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
shres2decprot_attr(STM32MP1_SHRES_I2C6));
etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
shres2decprot_attr(STM32MP1_SHRES_IWDG1));
etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
shres2decprot_attr(STM32MP1_SHRES_RNG1));
etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
shres2decprot_attr(STM32MP1_SHRES_USART1));
etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
shres2decprot_attr(STM32MP1_SHRES_SPI6));
}
static void check_rcc_secure_configuration(void)
{
uint32_t n;
uint32_t error = 0U;
bool mckprot = stm32mp1_rcc_is_mckprot();
bool secure = stm32mp1_rcc_is_secure();
for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
if (shres_state[n] != SHRES_SECURE) {
continue;
}
if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
ERROR("RCC %s MCKPROT %s and %s secure\n",
secure ? "secure" : "non-secure",
mckprot ? "set" : "not set",
shres2str_id(n));
error++;
}
}
if (error != 0U) {
panic();
}
}
static void set_gpio_secure_configuration(void)
{
uint32_t pin;
for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
}
}
static void print_shared_resources_state(void)
{
unsigned int id;
for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
switch (shres_state[id]) {
case SHRES_SECURE:
INFO("stm32mp1 %s is secure\n", shres2str_id(id));
break;
case SHRES_NON_SECURE:
case SHRES_UNREGISTERED:
VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
break;
default:
VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
panic();
}
}
}
void stm32mp_lock_periph_registering(void)
{
registering_locked = true;
print_shared_resources_state();
check_rcc_secure_configuration();
set_etzpc_secure_configuration();
set_gpio_secure_configuration();
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <arch_helpers.h>
#include <plat/common/platform.h>
#define RANDOM_CANARY_VALUE 2144346116U
u_register_t plat_get_stack_protector_canary(void)
{
/*
* Ideally, a random number should be returned instead of the
* combination of a timer's value and a compile-time constant.
*/
return RANDOM_CANARY_VALUE ^ (u_register_t)read_cntpct_el0();
}
@@ -0,0 +1,411 @@
/*
* Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <common/debug.h>
#include <drivers/clk.h>
#include <drivers/delay_timer.h>
#include <drivers/st/stpmic1.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <libfdt.h>
#include <platform_def.h>
#include <stm32mp_common.h>
#include <stm32mp_dt.h>
#include <stm32mp1_private.h>
/*
* SYSCFG REGISTER OFFSET (base relative)
*/
#define SYSCFG_BOOTR 0x00U
#define SYSCFG_BOOTCR 0x0CU
#if STM32MP15
#define SYSCFG_IOCTRLSETR 0x18U
#define SYSCFG_ICNR 0x1CU
#endif
#define SYSCFG_CMPCR 0x20U
#define SYSCFG_CMPENSETR 0x24U
#define SYSCFG_CMPENCLRR 0x28U
#if STM32MP13
#define SYSCFG_CMPSD1CR 0x30U
#define SYSCFG_CMPSD1ENSETR 0x34U
#define SYSCFG_CMPSD1ENCLRR 0x38U
#define SYSCFG_CMPSD2CR 0x40U
#define SYSCFG_CMPSD2ENSETR 0x44U
#define SYSCFG_CMPSD2ENCLRR 0x48U
#define SYSCFG_HSLVEN0R 0x50U
#endif
#define SYSCFG_IDC 0x380U
#define CMPCR_CMPENSETR_OFFSET 0x4U
#define CMPCR_CMPENCLRR_OFFSET 0x8U
/*
* SYSCFG_BOOTR Register
*/
#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
#if STM32MP15
#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
#endif
/*
* SYSCFG_BOOTCR Register
*/
#define SYSCFG_BOOTCR_BMEN BIT(0)
/*
* SYSCFG_IOCTRLSETR Register
*/
#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
/*
* SYSCFG_ICNR Register
*/
#define SYSCFG_ICNR_AXI_M9 BIT(9)
/*
* SYSCFG_CMPCR Register
*/
#define SYSCFG_CMPCR_SW_CTRL BIT(1)
#define SYSCFG_CMPCR_READY BIT(8)
#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
#define SYSCFG_CMPCR_RANSRC_SHIFT 16
#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
#define SYSCFG_CMPCR_ANSRC_SHIFT 24
#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
/*
* SYSCFG_CMPENSETR Register
*/
#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
/*
* HSLV definitions
*/
#define HSLV_IDX_TPIU 0U
#define HSLV_IDX_QSPI 1U
#define HSLV_IDX_ETH1 2U
#define HSLV_IDX_ETH2 3U
#define HSLV_IDX_SDMMC1 4U
#define HSLV_IDX_SDMMC2 5U
#define HSLV_IDX_SPI1 6U
#define HSLV_IDX_SPI2 7U
#define HSLV_IDX_SPI3 8U
#define HSLV_IDX_SPI4 9U
#define HSLV_IDX_SPI5 10U
#define HSLV_IDX_LTDC 11U
#define HSLV_NB_IDX 12U
#define HSLV_KEY 0x1018U
/*
* SYSCFG_IDC Register
*/
#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
#define SYSCFG_IDC_REV_ID_SHIFT 16
static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
{
uint64_t start;
start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
if (timeout_elapsed(start)) {
/* Failure on IO compensation enable is not a issue: warn only. */
WARN("IO compensation cell not ready\n");
break;
}
}
mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
}
static void disable_io_comp_cell(uintptr_t cmpcr_off)
{
uint32_t value;
if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
return;
}
value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
}
#if STM32MP13
static int get_regu_max_voltage(void *fdt, int sdmmc_node,
const char *regu_name, uint32_t *regu_val)
{
int node;
const fdt32_t *cuint;
cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL);
if (cuint == NULL) {
return -ENODEV;
}
node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
if (node < 0) {
return -ENODEV;
}
cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
if (cuint == NULL) {
return -ENODEV;
}
*regu_val = fdt32_to_cpu(*cuint);
return 0;
}
static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base)
{
int ret;
int node;
void *fdt = NULL;
uint32_t regu_max_val;
if (fdt_get_address(&fdt) == 0) {
return false;
}
if (fdt == NULL) {
return false;
}
node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base);
if (node < 0) {
/* No SD or eMMC device on this instance, enable HSLV */
return true;
}
ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", &regu_max_val);
if ((ret < 0) || (regu_max_val > 1800000U)) {
/*
* The vqmmc-supply property should always be present for eMMC.
* For SD-card, if it is not, then the card only supports 3.3V.
*/
return false;
}
return true;
}
static void enable_hslv_by_index(uint32_t index)
{
bool apply_hslv;
assert(index < HSLV_NB_IDX);
switch (index) {
case HSLV_IDX_SDMMC1:
apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE);
break;
case HSLV_IDX_SDMMC2:
apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE);
break;
default:
apply_hslv = true;
break;
}
if (apply_hslv) {
mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + index * sizeof(uint32_t), HSLV_KEY);
}
}
#endif
static void enable_high_speed_mode_low_voltage(void)
{
#if STM32MP13
uint32_t idx;
for (idx = 0U; idx < HSLV_NB_IDX; idx++) {
enable_hslv_by_index(idx);
}
#endif
#if STM32MP15
mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
SYSCFG_IOCTRLSETR_HSLVEN_ETH |
SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
SYSCFG_IOCTRLSETR_HSLVEN_SPI);
#endif
}
static void stm32mp1_syscfg_set_hslv(void)
{
uint32_t otp_value;
uint32_t vdd_voltage;
bool product_below_2v5;
/*
* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
* It could be disabled for low frequencies or if AFMUX is selected
* but the function is not used, typically for TRACE.
* If high speed low voltage pad mode is node enable, platform will
* over consume.
*
* WARNING:
* Enabling High Speed mode while VDD > 2.7V
* with the OTP product_below_2v5 (OTP 18, BIT 13)
* erroneously set to 1 can damage the SoC!
* => TF-A enables the low power mode only if VDD < 2.7V (in DT)
* but this value needs to be consistent with board design.
*/
if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
panic();
}
product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
/* Get VDD supply */
vdd_voltage = dt_get_pwr_vdd_voltage();
/* Check if VDD is Low Voltage */
if (vdd_voltage == 0U) {
WARN("VDD unknown\n");
} else if (vdd_voltage < 2700000U) {
enable_high_speed_mode_low_voltage();
if (!product_below_2v5) {
INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
}
} else {
if (product_below_2v5) {
ERROR("Product_below_2v5=1:\n");
ERROR("\tHSLVEN update is destructive,\n");
ERROR("\tno update as VDD > 2.7V\n");
panic();
}
}
}
void stm32mp1_syscfg_init(void)
{
#if STM32MP15
uint32_t bootr;
/*
* Interconnect update : select master using the port 1.
* LTDC = AXI_M9.
*/
mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
/* Disable Pull-Down for boot pin connected to VDD */
bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
SYSCFG_BOOTR_BOOT_MASK;
mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
#endif
stm32mp1_syscfg_set_hslv();
stm32mp1_syscfg_enable_io_compensation_start();
}
void stm32mp1_syscfg_enable_io_compensation_start(void)
{
/*
* Activate automatic I/O compensation.
* Warning: need to ensure CSI enabled and ready in clock driver.
* Enable non-secure clock, we assume non-secure is suspended.
*/
clk_enable(SYSCFG);
mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
SYSCFG_CMPENSETR_MPU_EN);
#if STM32MP13
mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR,
SYSCFG_CMPENSETR_MPU_EN);
mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR,
SYSCFG_CMPENSETR_MPU_EN);
#endif
}
void stm32mp1_syscfg_enable_io_compensation_finish(void)
{
enable_io_comp_cell_finish(SYSCFG_CMPCR);
#if STM32MP13
enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
#endif
}
void stm32mp1_syscfg_disable_io_compensation(void)
{
clk_enable(SYSCFG);
/*
* Deactivate automatic I/O compensation.
* Warning: CSI is disabled automatically in STOP if not
* requested for other usages and always OFF in STANDBY.
* Disable non-secure SYSCFG clock, we assume non-secure is suspended.
*/
disable_io_comp_cell(SYSCFG_CMPCR);
#if STM32MP13
disable_io_comp_cell(SYSCFG_CMPSD1CR);
disable_io_comp_cell(SYSCFG_CMPSD2CR);
#endif
clk_disable(SYSCFG);
}
/*
* @brief Get silicon revision from SYSCFG registers.
* @retval chip version (REV_ID).
*/
uint32_t stm32mp1_syscfg_get_chip_version(void)
{
return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
}
/*
* @brief Get device ID from SYSCFG registers.
* @retval device ID (DEV_ID).
*/
uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
{
return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
}
#if STM32MP13
void stm32mp1_syscfg_boot_mode_enable(void)
{
mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
}
void stm32mp1_syscfg_boot_mode_disable(void)
{
mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
}
#endif
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "tbbr/tbb_ext.h"
#include "tbbr/tbb_key.h"
#include "tbbr/stm32mp1_tbb_cert.h"
/*
* Certificates used in the chain of trust
*
* The order of the certificates must follow the enumeration specified in
* stm32mp1_tbb_cert.h. All certificates are self-signed, so the issuer certificate
* field points to itself.
*/
static cert_t stm32mp1_tbb_certs[] = {
[0] = {
.id = STM32MP_CONFIG_CERT,
.opt = "stm32mp-cfg-cert",
.help_msg = "STM32MP Config Certificate (output file)",
.fn = NULL,
.cn = "STM32MP config FW Certificate",
.key = ROT_KEY,
.issuer = STM32MP_CONFIG_CERT,
.ext = {
TRUSTED_FW_NVCOUNTER_EXT,
HW_CONFIG_HASH_EXT,
FW_CONFIG_HASH_EXT
},
.num_ext = 3
},
};
PLAT_REGISTER_COT(stm32mp1_tbb_certs);
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <lib/psci/psci.h>
#include <plat/common/platform.h>
/* 1 cluster, all cores into */
static const unsigned char stm32mp1_power_domain_tree_desc[] = {
PLATFORM_CLUSTER_COUNT,
PLATFORM_CORE_COUNT,
};
/* This function returns the platform topology */
const unsigned char *plat_get_power_domain_tree_desc(void)
{
return stm32mp1_power_domain_tree_desc;
}
/*******************************************************************************
* This function implements a part of the critical interface between the psci
* generic layer and the platform that allows the former to query the platform
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
* in case the MPIDR is invalid.
******************************************************************************/
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
unsigned int cluster_id, cpu_id;
u_register_t mpidr_copy = mpidr;
mpidr_copy &= MPIDR_AFFINITY_MASK;
if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) {
return -1;
}
cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
cpu_id = (mpidr_copy >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
return -1;
}
/*
* Validate cpu_id by checking whether it represents a CPU in one
* of the two clusters present on the platform.
*/
if (cpu_id >= PLATFORM_CORE_COUNT) {
return -1;
}
return (int)cpu_id;
}
@@ -0,0 +1,423 @@
/*
* Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <limits.h>
#include <string.h>
#include <common/debug.h>
#include <drivers/st/bsec.h>
#include <drivers/st/stm32mp1_usb.h>
#include <drivers/usb_device.h>
#include <platform_def.h>
#include <stm32cubeprogrammer.h>
#include <stm32mp_common.h>
#include <usb_dfu.h>
/* String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */
#define SIZ_STRING_SERIAL U(24)
#define USB_SIZ_STRING_SERIAL (1U + 1U + (SIZ_STRING_SERIAL * 2U))
#define USBD_MAX_STR_DESC_SIZ 0x100
#define USBD_VID 0x0483
#define USBD_PID 0xDF11
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "STMicroelectronics"
#define USBD_CONFIGURATION_STRING "DFU Config"
#define USBD_INTERFACE_STRING "DFU Interface"
#if STM32MP13
#define USB_DFU_ITF_NUM 2
#endif
#if STM32MP15
#define USB_DFU_ITF_NUM 6
#endif
#define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM)
/* DFU devices */
static struct usb_dfu_handle usb_dfu_handle;
/* USB Standard Device Descriptor */
static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = {
USB_LEN_DEV_DESC, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType */
0x00, /* bcdUSB */
0x02, /* version */
0x00, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
USB_MAX_EP0_SIZE, /* bMaxPacketSize */
LOBYTE(USBD_VID), /* idVendor */
HIBYTE(USBD_VID), /* idVendor */
LOBYTE(USBD_PID), /* idVendor */
HIBYTE(USBD_PID), /* idVendor */
0x00, /* bcdDevice rel. 2.00 */
0x02,
USBD_IDX_MFC_STR, /* Index of manufacturer string */
USBD_IDX_PRODUCT_STR, /* Index of product string */
USBD_IDX_SERIAL_STR, /* Index of serial number string */
USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
}; /* USB_DeviceDescriptor */
/* USB Standard String Descriptor */
static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
USB_LEN_LANGID_STR_DESC,
USB_DESC_TYPE_STRING,
LOBYTE(USBD_LANGID_STRING),
HIBYTE(USBD_LANGID_STRING),
};
/* USB Standard Device Descriptor */
static const uint8_t
usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
/* USB serial number: build dynamically */
static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1];
/* USB DFU device Configuration Descriptor */
static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x02, /* iConfiguration: Index of string descriptor for configuration */
0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
/* Descriptor of DFU interface 0 Alternate setting 0..N */
USBD_DFU_IF_DESC(0),
USBD_DFU_IF_DESC(1),
#if USB_DFU_ITF_NUM > 2
USBD_DFU_IF_DESC(2),
#endif
#if USB_DFU_ITF_NUM > 3
USBD_DFU_IF_DESC(3),
#endif
#if USB_DFU_ITF_NUM > 4
USBD_DFU_IF_DESC(4),
#endif
#if USB_DFU_ITF_NUM > 5
USBD_DFU_IF_DESC(5),
#endif
/* DFU Functional Descriptor */
0x09, /* blength = 9 Bytes */
DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */
DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */
0xFF, /* DetachTimeOut = 255 ms */
0x00,
TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */
((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */
((USB_DFU_VERSION >> 8) & 0xFF)
};
/* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */
#if STM32MP13
const char *const if_desc_string[USB_DFU_ITF_NUM] = {
"@SSBL /0x03/1*16Me",
"@virtual /0xF1/1*512Ba"
};
#endif
#if STM32MP15
const char *const if_desc_string[USB_DFU_ITF_NUM] = {
"@Partition0 /0x00/1*256Ke",
"@FSBL /0x01/1*1Me",
"@Partition2 /0x02/1*1Me",
"@Partition3 /0x03/1*16Me",
"@Partition4 /0x04/1*16Me",
"@virtual /0xF1/1*512Ba"
};
#endif
/* Buffer to build the unicode string provided to USB device stack */
static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ];
/*
* Convert Ascii string into unicode one
* desc : descriptor buffer
* unicode : Formatted string buffer (unicode)
* len : descriptor length
*/
static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *len)
{
uint8_t idx = 0U;
if (desc == NULL) {
return;
}
*len = strlen(desc) * 2U + 2U;
unicode[idx++] = *len;
unicode[idx++] = USB_DESC_TYPE_STRING;
while (*desc != '\0') {
unicode[idx++] = *desc++;
unicode[idx++] = 0x00U;
}
}
/*
* Create the serial number string descriptor
*/
static void update_serial_num_string(void)
{
uint8_t i;
char serial_string[SIZ_STRING_SERIAL + 2U];
/* serial number is set to 0 */
uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U};
uint32_t otp;
uint32_t len;
uint16_t length;
if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) {
ERROR("BSEC: Get UID_OTP number Error\n");
return;
}
if ((len / __WORD_BIT) != UID_WORD_NB) {
ERROR("BSEC: Get UID_OTP length Error\n");
return;
}
for (i = 0; i < UID_WORD_NB; i++) {
if (bsec_shadow_read_otp(&deviceserial[i], i + otp) !=
BSEC_OK) {
ERROR("BSEC: UID%d Error\n", i);
return;
}
}
/* build serial number with OTP value as in ROM code */
snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X",
deviceserial[0], deviceserial[1], deviceserial[2]);
length = USB_SIZ_STRING_SERIAL;
stm32mp1_get_string(serial_string, usb_stm32mp1_serial, &length);
}
/*
* Return Device Qualifier descriptor
* length : pointer data length
* return : pointer to descriptor buffer
*/
static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length)
{
*length = sizeof(usbd_stm32mp1_qualifier_desc);
return (uint8_t *)usbd_stm32mp1_qualifier_desc;
}
/*
* Return configuration descriptor
* length : pointer data length
* return : pointer to descriptor buffer
*/
static uint8_t *stm32mp1_get_config_desc(uint16_t *length)
{
*length = sizeof(usb_stm32mp1_config_desc);
return (uint8_t *)usb_stm32mp1_config_desc;
}
/*
* Returns the device descriptor.
* length: Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_device_desc(uint16_t *length)
{
*length = sizeof(usb_stm32mp1_desc);
return (uint8_t *)usb_stm32mp1_desc;
}
/*
* Returns the LangID string descriptor.
* length: Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_lang_id_desc(uint16_t *length)
{
*length = sizeof(usb_stm32mp1_lang_id_desc);
return (uint8_t *)usb_stm32mp1_lang_id_desc;
}
/*
* Returns the product string descriptor.
* length: Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_product_desc(uint16_t *length)
{
char name[STM32_SOC_NAME_SIZE];
char product[128];
uint32_t chip_id;
uint32_t chip_version;
stm32mp_get_soc_name(name);
chip_id = stm32mp_get_chip_dev_id();
chip_version = stm32mp_get_chip_version();
snprintf(product, sizeof(product),
"DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,",
chip_id, chip_version, name);
stm32mp1_get_string(product, usb_str_dec, length);
return usb_str_dec;
}
/*
* Returns the manufacturer string descriptor.
* length: Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length)
{
stm32mp1_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length);
return usb_str_dec;
}
/*
* Returns the serial number string descriptor.
* length: Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_serial_desc(uint16_t *length)
{
*length = USB_SIZ_STRING_SERIAL;
return (uint8_t *)usb_stm32mp1_serial;
}
/*
* Returns the configuration string descriptor.
* length: Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_config_desc(uint16_t *length)
{
stm32mp1_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length);
return usb_str_dec;
}
/*
* Returns the interface string descriptor.
* length : Pointer to data length variable
* return : Pointer to descriptor buffer
*/
static uint8_t *stm32mp1_interface_desc(uint16_t *length)
{
stm32mp1_get_string(USBD_INTERFACE_STRING, usb_str_dec, length);
return usb_str_dec;
}
/*
* Manages the transfer of memory interfaces string descriptors.
* index: descriptor index
* length : pointer data length
* return : pointer to the descriptor table or NULL if the descriptor
* is not supported.
*/
static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length)
{
if (index >= ARRAY_SIZE(if_desc_string)) {
return NULL;
}
stm32mp1_get_string(if_desc_string[index], usb_str_dec, length);
return usb_str_dec;
}
static const struct usb_desc dfu_desc = {
.get_device_desc = stm32mp1_device_desc,
.get_lang_id_desc = stm32mp1_lang_id_desc,
.get_manufacturer_desc = stm32mp1_manufacturer_desc,
.get_product_desc = stm32mp1_product_desc,
.get_configuration_desc = stm32mp1_config_desc,
.get_serial_desc = stm32mp1_serial_desc,
.get_interface_desc = stm32mp1_interface_desc,
.get_usr_desc = stm32mp1_get_usr_desc,
.get_config_desc = stm32mp1_get_config_desc,
.get_device_qualifier_desc = stm32mp1_get_qualifier_desc,
/* only HS is supported, as ROM code */
.get_other_speed_config_desc = NULL,
};
static struct usb_handle usb_core_handle;
static struct pcd_handle pcd_handle;
struct usb_handle *usb_dfu_plat_init(void)
{
/* Prepare USB Driver */
pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE;
pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE;
stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle,
(uint32_t *)USB_OTG_BASE);
#if STM32MP15
/* STM32MP15 = keep the configuration from ROM code */
usb_core_handle.ep0_state = USBD_EP0_DATA_IN;
usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
#endif
/* Update the serial number string descriptor from the unique ID */
update_serial_num_string();
/* Prepare USB DFU stack */
usb_dfu_register(&usb_core_handle, &usb_dfu_handle);
/* Register DFU descriptor in USB stack */
register_platform(&usb_core_handle, &dfu_desc);
return &usb_core_handle;
}
/* Link between USB alternate and STM32CubeProgramer phase */
uint8_t usb_dfu_get_phase(uint8_t alt)
{
uint8_t ret;
switch (alt) {
#if STM32MP13
case 0:
ret = PHASE_SSBL;
break;
case 1:
ret = PHASE_CMD;
break;
#endif
#if STM32MP15
case 3:
ret = PHASE_SSBL;
break;
case 5:
ret = PHASE_CMD;
break;
#endif
default:
ret = PHASE_RESET;
break;
}
return ret;
}