diff options
Diffstat (limited to 'plat/brcm/board/common')
-rw-r--r-- | plat/brcm/board/common/bcm_console.c | 65 | ||||
-rw-r--r-- | plat/brcm/board/common/bcm_elog.c | 268 | ||||
-rw-r--r-- | plat/brcm/board/common/bcm_elog_ddr.c | 133 | ||||
-rw-r--r-- | plat/brcm/board/common/bcm_elog_ddr.h | 107 | ||||
-rw-r--r-- | plat/brcm/board/common/board_arm_trusted_boot.c | 625 | ||||
-rw-r--r-- | plat/brcm/board/common/board_common.c | 74 | ||||
-rw-r--r-- | plat/brcm/board/common/board_common.mk | 294 | ||||
-rw-r--r-- | plat/brcm/board/common/brcm_mbedtls.c | 12 | ||||
-rw-r--r-- | plat/brcm/board/common/chip_id.h | 37 | ||||
-rw-r--r-- | plat/brcm/board/common/cmn_plat_def.h | 82 | ||||
-rw-r--r-- | plat/brcm/board/common/cmn_plat_util.h | 43 | ||||
-rw-r--r-- | plat/brcm/board/common/cmn_sec.c | 49 | ||||
-rw-r--r-- | plat/brcm/board/common/cmn_sec.h | 19 | ||||
-rw-r--r-- | plat/brcm/board/common/err.c | 37 | ||||
-rw-r--r-- | plat/brcm/board/common/plat_setup.c | 27 | ||||
-rw-r--r-- | plat/brcm/board/common/platform_common.c | 94 | ||||
-rw-r--r-- | plat/brcm/board/common/sbl_util.c | 40 | ||||
-rw-r--r-- | plat/brcm/board/common/sbl_util.h | 19 | ||||
-rw-r--r-- | plat/brcm/board/common/timer_sync.c | 71 |
19 files changed, 2096 insertions, 0 deletions
diff --git a/plat/brcm/board/common/bcm_console.c b/plat/brcm/board/common/bcm_console.c new file mode 100644 index 0000000..5f20094 --- /dev/null +++ b/plat/brcm/board/common/bcm_console.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <drivers/console.h> +#include <drivers/ti/uart/uart_16550.h> + +#include <platform_def.h> + +/******************************************************************************* + * Functions that set up the console + ******************************************************************************/ +static console_t bcm_boot_console; +static console_t bcm_runtime_console; + +/* Initialize the console to provide early debug support */ +void bcm_console_boot_init(void) +{ + int rc = console_16550_register(PLAT_BRCM_BOOT_UART_BASE, + PLAT_BRCM_BOOT_UART_CLK_IN_HZ, + BRCM_CONSOLE_BAUDRATE, + &bcm_boot_console); + if (rc == 0) { + /* + * The crash console doesn't use the multi console API, it uses + * the core console functions directly. It is safe to call panic + * and let it print debug information. + */ + panic(); + } + + console_set_scope(&bcm_boot_console, CONSOLE_FLAG_BOOT); +} + +void bcm_console_boot_end(void) +{ + console_flush(); + + (void)console_unregister(&bcm_boot_console); +} + +/* Initialize the runtime console */ +void bcm_console_runtime_init(void) +{ + int rc = console_16550_register(PLAT_BRCM_BL31_RUN_UART_BASE, + PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ, + BRCM_CONSOLE_BAUDRATE, + &bcm_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&bcm_runtime_console, CONSOLE_FLAG_RUNTIME); +} + +void bcm_console_runtime_end(void) +{ + console_flush(); + + (void)console_unregister(&bcm_runtime_console); +} diff --git a/plat/brcm/board/common/bcm_elog.c b/plat/brcm/board/common/bcm_elog.c new file mode 100644 index 0000000..093157e --- /dev/null +++ b/plat/brcm/board/common/bcm_elog.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2018 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdarg.h> +#include <stdint.h> +#include <string.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <plat/common/platform.h> + +#include <bcm_elog.h> + +/* error logging signature */ +#define BCM_ELOG_SIG_OFFSET 0x0000 +#define BCM_ELOG_SIG_VAL 0x75767971 + +/* current logging offset that points to where new logs should be added */ +#define BCM_ELOG_OFF_OFFSET 0x0004 + +/* current logging length (excluding header) */ +#define BCM_ELOG_LEN_OFFSET 0x0008 + +#define BCM_ELOG_HEADER_LEN 12 + +/* + * @base: base address of memory where log is saved + * @max_size: max size of memory reserved for logging + * @is_active: indicates logging is currently active + * @level: current logging level + */ +struct bcm_elog { + uintptr_t base; + uint32_t max_size; + unsigned int is_active; + unsigned int level; +}; + +static struct bcm_elog global_elog; + +extern void memcpy16(void *dst, const void *src, unsigned int len); + +/* + * Log one character + */ +static void elog_putchar(struct bcm_elog *elog, unsigned char c) +{ + uint32_t offset, len; + + offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET); + len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET); + mmio_write_8(elog->base + offset, c); + offset++; + + /* log buffer is now full and need to wrap around */ + if (offset >= elog->max_size) + offset = BCM_ELOG_HEADER_LEN; + + /* only increment length when log buffer is not full */ + if (len < elog->max_size - BCM_ELOG_HEADER_LEN) + len++; + + mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset); + mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len); +} + +static void elog_unsigned_num(struct bcm_elog *elog, unsigned long unum, + unsigned int radix) +{ + /* Just need enough space to store 64 bit decimal integer */ + unsigned char num_buf[20]; + int i = 0, rem; + + do { + rem = unum % radix; + if (rem < 0xa) + num_buf[i++] = '0' + rem; + else + num_buf[i++] = 'a' + (rem - 0xa); + } while (unum /= radix); + + while (--i >= 0) + elog_putchar(elog, num_buf[i]); +} + +static void elog_string(struct bcm_elog *elog, const char *str) +{ + while (*str) + elog_putchar(elog, *str++); +} + +/* + * Routine to initialize error logging + */ +int bcm_elog_init(void *base, uint32_t size, unsigned int level) +{ + struct bcm_elog *elog = &global_elog; + uint32_t val; + + elog->base = (uintptr_t)base; + elog->max_size = size; + elog->is_active = 1; + elog->level = level / 10; + + /* + * If a valid signature can be found, it means logs have been copied + * into designated memory by another software. In this case, we should + * not re-initialize the entry header in the designated memory + */ + val = mmio_read_32(elog->base + BCM_ELOG_SIG_OFFSET); + if (val != BCM_ELOG_SIG_VAL) { + mmio_write_32(elog->base + BCM_ELOG_SIG_OFFSET, + BCM_ELOG_SIG_VAL); + mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, + BCM_ELOG_HEADER_LEN); + mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, 0); + } + + return 0; +} + +/* + * Routine to disable error logging + */ +void bcm_elog_exit(void) +{ + struct bcm_elog *elog = &global_elog; + + if (!elog->is_active) + return; + + elog->is_active = 0; + + flush_dcache_range(elog->base, elog->max_size); +} + +/* + * Routine to copy error logs from current memory to 'dst' memory and continue + * logging from the new 'dst' memory. + * dst and base addresses must be 16-bytes aligned. + */ +int bcm_elog_copy_log(void *dst, uint32_t max_size) +{ + struct bcm_elog *elog = &global_elog; + uint32_t offset, len; + + if (!elog->is_active || ((uintptr_t)dst == elog->base)) + return -1; + + /* flush cache before copying logs */ + flush_dcache_range(elog->base, max_size); + + /* + * If current offset exceeds the new max size, then that is considered + * as a buffer overflow situation. In this case, we reset the offset + * back to the beginning + */ + offset = mmio_read_32(elog->base + BCM_ELOG_OFF_OFFSET); + if (offset >= max_size) { + offset = BCM_ELOG_HEADER_LEN; + mmio_write_32(elog->base + BCM_ELOG_OFF_OFFSET, offset); + } + + /* note payload length does not include header */ + len = mmio_read_32(elog->base + BCM_ELOG_LEN_OFFSET); + if (len > max_size - BCM_ELOG_HEADER_LEN) { + len = max_size - BCM_ELOG_HEADER_LEN; + mmio_write_32(elog->base + BCM_ELOG_LEN_OFFSET, len); + } + + /* Need to copy everything including the header. */ + memcpy16(dst, (const void *)elog->base, len + BCM_ELOG_HEADER_LEN); + elog->base = (uintptr_t)dst; + elog->max_size = max_size; + + return 0; +} + +/* + * Main routine to save logs into memory + */ +void bcm_elog(const char *fmt, ...) +{ + va_list args; + const char *prefix_str; + int bit64; + int64_t num; + uint64_t unum; + char *str; + struct bcm_elog *elog = &global_elog; + + /* We expect the LOG_MARKER_* macro as the first character */ + unsigned int level = fmt[0]; + + if (!elog->is_active || level > elog->level) + return; + + prefix_str = plat_log_get_prefix(level); + + while (*prefix_str != '\0') { + elog_putchar(elog, *prefix_str); + prefix_str++; + } + + va_start(args, fmt); + fmt++; + while (*fmt) { + bit64 = 0; + + if (*fmt == '%') { + fmt++; + /* Check the format specifier */ +loop: + switch (*fmt) { + case 'i': /* Fall through to next one */ + case 'd': + if (bit64) + num = va_arg(args, int64_t); + else + num = va_arg(args, int32_t); + + if (num < 0) { + elog_putchar(elog, '-'); + unum = (unsigned long)-num; + } else + unum = (unsigned long)num; + + elog_unsigned_num(elog, unum, 10); + break; + case 's': + str = va_arg(args, char *); + elog_string(elog, str); + break; + case 'x': + if (bit64) + unum = va_arg(args, uint64_t); + else + unum = va_arg(args, uint32_t); + + elog_unsigned_num(elog, unum, 16); + break; + case 'l': + bit64 = 1; + fmt++; + goto loop; + case 'u': + if (bit64) + unum = va_arg(args, uint64_t); + else + unum = va_arg(args, uint32_t); + + elog_unsigned_num(elog, unum, 10); + break; + default: + /* Exit on any other format specifier */ + goto exit; + } + fmt++; + continue; + } + elog_putchar(elog, *fmt++); + } +exit: + va_end(args); +} diff --git a/plat/brcm/board/common/bcm_elog_ddr.c b/plat/brcm/board/common/bcm_elog_ddr.c new file mode 100644 index 0000000..89e7bff --- /dev/null +++ b/plat/brcm/board/common/bcm_elog_ddr.c @@ -0,0 +1,133 @@ +/* + * Copyright 2019-2020 Broadcom. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> + +#include <ddr_init.h> +#include <scp_cmd.h> +#include <scp_utils.h> +#include <platform_def.h> + +#include "bcm_elog_ddr.h" +#include "m0_cfg.h" +#include "m0_ipc.h" + +void elog_init_ddr_log(void) +{ + struct elog_setup setup = {0}; + struct elog_global_header global; + struct elog_meta_record rec; + unsigned int rec_idx = 0; + uint32_t log_offset; + uintptr_t metadata; + char *rec_desc[ELOG_SUPPORTED_REC_CNT] = {"SYSRESET", "THERMAL", + "DDR_ECC", "APBOOTLG", + "IDM"}; + + /* + * If this is warm boot, return immediately. + * We expect metadata to be initialized already + */ + if (is_warmboot()) { + WARN("Warmboot detected, skip ELOG metadata initialization\n"); + return; + } + + memset(&global, 0, sizeof(global)); + + global.sector_size = ELOG_SECTOR_SIZE; + global.signature = ELOG_GLOBAL_META_HDR_SIG; + global.rec_count = ELOG_SUPPORTED_REC_CNT; + + /* Start of logging area in DDR memory */ + log_offset = ELOG_STORE_OFFSET; + + /* Shift to the first RECORD header */ + log_offset += 2 * global.sector_size; + + /* Temporary place to hold metadata */ + metadata = TMP_ELOG_METADATA_BASE; + + memcpy((void *)metadata, &global, sizeof(global)); + metadata += sizeof(global); + + while (rec_idx < global.rec_count) { + memset(&rec, 0, sizeof(rec)); + + rec.type = rec_idx; + if (rec_idx == ELOG_REC_UART_LOG) { + rec.format = ELOG_REC_FMT_ASCII; + rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR; + rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_FS4_SCRATCH; + rec.src_mem_addr = BCM_ELOG_BL31_BASE; + rec.alt_src_mem_addr = BCM_ELOG_BL2_BASE; + rec.rec_size = ELOG_APBOOTLG_REC_SIZE; + } else if (rec_idx == ELOG_REC_IDM_LOG) { + rec.type = IDM_ELOG_REC_TYPE; + rec.format = ELOG_REC_FMT_CUSTOM; + rec.src_mem_type = ELOG_SRC_MEM_TYPE_DDR; + rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH; + rec.src_mem_addr = ELOG_IDM_SRC_MEM_ADDR; + rec.alt_src_mem_addr = 0x0; + rec.rec_size = ELOG_DEFAULT_REC_SIZE; + } else { + rec.format = ELOG_REC_FMT_CUSTOM; + rec.src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH; + rec.alt_src_mem_type = ELOG_SRC_MEM_TYPE_CRMU_SCRATCH; + rec.src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR; + rec.alt_src_mem_addr = ELOG_USE_DEFAULT_MEM_ADDR; + rec.rec_size = ELOG_DEFAULT_REC_SIZE; + } + + rec.nvm_type = LOG_MEDIA_DDR; + rec.sector_size = ELOG_SECTOR_SIZE; + + rec.rec_addr = (uint64_t)log_offset; + log_offset += rec.rec_size; + + /* Sanity checks */ + if (rec.type > ELOG_MAX_REC_COUNT || + rec.format > ELOG_MAX_REC_FORMAT || + (rec.nvm_type > ELOG_MAX_NVM_TYPE && + rec.nvm_type != ELOG_NVM_DEFAULT) || + !rec.rec_size || + !rec.sector_size || + rec_idx >= ELOG_SUPPORTED_REC_CNT) { + ERROR("Invalid ELOG record(%u) detected\n", rec_idx); + return; + } + + memset(rec.rec_desc, ' ', sizeof(rec.rec_desc)); + + memcpy(rec.rec_desc, rec_desc[rec_idx], + strlen(rec_desc[rec_idx])); + + memcpy((void *)metadata, &rec, sizeof(rec)); + metadata += sizeof(rec); + + rec_idx++; + } + + setup.params[0] = TMP_ELOG_METADATA_BASE; + setup.params[1] = (sizeof(global) + global.rec_count * sizeof(rec)); + setup.cmd = ELOG_SETUP_CMD_WRITE_META; + + flush_dcache_range((uintptr_t)&setup, sizeof(struct elog_setup)); + flush_dcache_range((uintptr_t)setup.params[0], setup.params[1]); + + /* initialize DDR Logging METADATA if this is NOT warmboot */ + if (!is_warmboot()) { + if (scp_send_cmd(MCU_IPC_MCU_CMD_ELOG_SETUP, + (uint32_t)(uintptr_t)(&setup), + SCP_CMD_DEFAULT_TIMEOUT_US)) { + ERROR("scp_send_cmd: timeout/error for elog setup\n"); + return; + } + } + + NOTICE("MCU Error logging initialized\n"); +} diff --git a/plat/brcm/board/common/bcm_elog_ddr.h b/plat/brcm/board/common/bcm_elog_ddr.h new file mode 100644 index 0000000..6f21a68 --- /dev/null +++ b/plat/brcm/board/common/bcm_elog_ddr.h @@ -0,0 +1,107 @@ +/* + * Copyright 2019-2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BCM_ELOG_DDR_H +#define BCM_ELOG_DDR_H + +#define ELOG_GLOBAL_META_HDR_SIG 0x45524c47 +#define ELOG_MAX_REC_COUNT 13 +#define ELOG_MAX_REC_FORMAT 1 +#define ELOG_MAX_NVM_TYPE 4 +/* Use a default NVM, set by m0 configuration */ +#define ELOG_NVM_DEFAULT 0xff + +/* Max. number of cmd parameters per elog spec */ +#define ELOG_PARAM_COUNT 3 +/* + * Number of supported RECORD Types- + * SYSRESET, THERMAL, DDR_ECC, APBOOTLG, IDM + */ +#define ELOG_SUPPORTED_REC_CNT 5 + +#define ELOG_REC_DESC_LENGTH 8 + +#define ELOG_SECTOR_SIZE 0x1000 + +/* Default Record size for all record types except APBOOTLOG */ +#define ELOG_DEFAULT_REC_SIZE 0x10000 + +/* Default record size for APBOOTLOG record */ +#define ELOG_APBOOTLG_REC_SIZE 0x60000 + +/* Use default CRMU provided mem address */ +#define ELOG_USE_DEFAULT_MEM_ADDR 0x0 + +/* Temporary place to hold metadata */ +#define TMP_ELOG_METADATA_BASE (ELOG_AP_UART_LOG_BASE + \ + BCM_ELOG_BL2_SIZE) +/* IDM ELOG source memory address */ +#define ELOG_IDM_SRC_MEM_ADDR 0x8f213000 + +#define IDM_ELOG_REC_TYPE 5 + +enum elog_record_type { + ELOG_REC_SYS_RESET_EVT = 0, + ELOG_REC_THERMAL_EVT, + ELOG_REC_DDR_ECC, + ELOG_REC_UART_LOG, + ELOG_REC_IDM_LOG, + ELOG_REC_MAX +}; + +enum elog_record_format { + ELOG_REC_FMT_ASCII = 0, + ELOG_REC_FMT_CUSTOM +}; + +enum elog_src_memory_type { + ELOG_SRC_MEM_TYPE_CRMU_SCRATCH = 0, + ELOG_SRC_MEM_TYPE_FS4_SCRATCH, + ELOG_SRC_MEM_TYPE_DDR, + ELOG_SRC_MEM_TYPE_CHIMP_SCRATCH +}; + +enum elog_setup_cmd { + ELOG_SETUP_CMD_VALIDATE_META, + ELOG_SETUP_CMD_WRITE_META, + ELOG_SETUP_CMD_ERASE, + ELOG_SETUP_CMD_READ, + ELOG_SETUP_CMD_CHECK +}; + +struct elog_setup { + uint32_t cmd; + uint32_t params[ELOG_PARAM_COUNT]; + uint32_t result; + uint32_t ret_code; +}; + +struct elog_meta_record { + uint8_t type; + uint8_t format; + uint8_t src_mem_type; + uint8_t alt_src_mem_type; + uint8_t nvm_type; + char rec_desc[ELOG_REC_DESC_LENGTH]; + uint64_t src_mem_addr; + uint64_t alt_src_mem_addr; + uint64_t rec_addr; + uint32_t rec_size; + uint32_t sector_size; + uint8_t padding[3]; +} __packed; + +struct elog_global_header { + uint32_t signature; + uint32_t sector_size; + uint8_t revision; + uint8_t rec_count; + uint16_t padding; +} __packed; + +void elog_init_ddr_log(void); + +#endif /* BCM_ELOG_DDR_H */ diff --git a/plat/brcm/board/common/board_arm_trusted_boot.c b/plat/brcm/board/common/board_arm_trusted_boot.c new file mode 100644 index 0000000..da18c31 --- /dev/null +++ b/plat/brcm/board/common/board_arm_trusted_boot.c @@ -0,0 +1,625 @@ +/* + * Copyright 2015 - 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <inttypes.h> +#include <stdint.h> +#include <string.h> + +#include <common/debug.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> +#include <tools_share/tbbr_oid.h> + +#include <sbl_util.h> +#include <sotp.h> + +/* Weak definition may be overridden in specific platform */ +#pragma weak plat_match_rotpk +#pragma weak plat_get_nv_ctr +#pragma weak plat_set_nv_ctr + +/* SHA256 algorithm */ +#define SHA256_BYTES 32 + +/* ROTPK locations */ +#define ARM_ROTPK_REGS_ID 1 +#define ARM_ROTPK_DEVEL_RSA_ID 2 +#define BRCM_ROTPK_SOTP_RSA_ID 3 + +#if !ARM_ROTPK_LOCATION_ID + #error "ARM_ROTPK_LOCATION_ID not defined" +#endif + +static const unsigned char rotpk_hash_hdr[] = + "\x30\x31\x30\x0D\x06\x09\x60\x86\x48" + "\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"; +static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1; +static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) +static const unsigned char arm_devel_rotpk_hash[] = + "\xB0\xF3\x82\x09\x12\x97\xD8\x3A" + "\x37\x7A\x72\x47\x1B\xEC\x32\x73" + "\xE9\x92\x32\xE2\x49\x59\xF6\x5E" + "\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA"; +#endif + +#pragma weak plat_rotpk_hash +const unsigned char plat_rotpk_hash[] = + "\xdb\x06\x67\x95\x4f\x88\x2b\x88" + "\x49\xbf\x70\x3f\xde\x50\x4a\x96" + "\xd8\x17\x69\xd4\xa0\x6c\xba\xee" + "\x66\x3e\x71\x82\x2d\x95\x69\xe4"; + +#pragma weak rom_slice +const unsigned char rom_slice[] = + "\x77\x06\xbc\x98\x40\xbe\xfd\xab" + "\x60\x4b\x74\x3c\x9a\xb3\x80\x75" + "\x39\xb6\xda\x27\x07\x2e\x5b\xbf" + "\x5c\x47\x91\xc9\x95\x26\x26\x0c"; + +#if (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID) +static int plat_is_trusted_boot(void) +{ + uint64_t section3_row0_data; + + section3_row0_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); + + if ((section3_row0_data & SOTP_DEVICE_SECURE_CFG0_AB_MASK) == 0) { + INFO("NOT AB\n"); + return 0; + } + + INFO("AB\n"); + return TRUSTED_BOARD_BOOT; +} + +/* + * FAST AUTH is enabled if all following conditions are met: + * - AB part + * - SOTP.DEV != 0 + * - SOTP.CID != 0 + * - SOTP.ENC_DEV_TYPE = ENC_AB_DEV + * - Manuf_debug strap set high + */ +static int plat_fast_auth_enabled(void) +{ + uint32_t chip_state; + uint64_t section3_row0_data; + uint64_t section3_row1_data; + + section3_row0_data = + sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); + section3_row1_data = + sotp_mem_read(SOTP_DEVICE_SECURE_CFG1_ROW, 0); + + chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES); + + if (plat_is_trusted_boot() && + (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_DEV_MASK) && + (section3_row0_data & SOTP_DEVICE_SECURE_CFG0_CID_MASK) && + ((section3_row1_data & SOTP_ENC_DEV_TYPE_MASK) == + SOTP_ENC_DEV_TYPE_AB_DEV) && + (chip_state & SOTP_CHIP_STATES_MANU_DEBUG_MASK)) + return 1; + + return 0; +} +#endif + +/* + * Return the ROTPK hash in the following ASN.1 structure in DER format: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags) +{ + uint8_t *dst; + + assert(key_ptr != NULL); + assert(key_len != NULL); + assert(flags != NULL); + + *flags = 0; + + /* Copy the DER header */ + memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len); + dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len]; + +#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) + memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES); +#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) + uint32_t *src, tmp; + unsigned int words, i; + + /* + * Append the hash from Trusted Root-Key Storage registers. The hash has + * not been written linearly into the registers, so we have to do a bit + * of byte swapping: + * + * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C + * +---------------------------------------------------------------+ + * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | + * +---------------------------------------------------------------+ + * | ... ... | | ... ... | + * | +--------------------+ | +-------+ + * | | | | + * +----------------------------+ +----------------------------+ + * | | | | + * +-------+ | +--------------------+ | + * | | | | + * v v v v + * +---------------------------------------------------------------+ + * | | | + * +---------------------------------------------------------------+ + * 0 15 16 31 + * + * Additionally, we have to access the registers in 32-bit words + */ + words = SHA256_BYTES >> 3; + + /* Swap bytes 0-15 (first four registers) */ + src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + /* Words are read in little endian */ + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } + + /* Swap bytes 16-31 (last four registers) */ + src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2); + for (i = 0 ; i < words ; i++) { + tmp = src[words - 1 - i]; + *dst++ = (uint8_t)((tmp >> 24) & 0xFF); + *dst++ = (uint8_t)((tmp >> 16) & 0xFF); + *dst++ = (uint8_t)((tmp >> 8) & 0xFF); + *dst++ = (uint8_t)(tmp & 0xFF); + } +#elif (ARM_ROTPK_LOCATION_ID == BRCM_ROTPK_SOTP_RSA_ID) +{ + int i; + int ret = -1; + + /* + * In non-AB mode, we do not read the key. + * In AB mode: + * - The Dauth is in BL11 if SBL is enabled + * - The Dauth is in SOTP if SBL is disabled. + */ + if (plat_is_trusted_boot() == 0) { + + INFO("NON-AB: Do not read DAUTH!\n"); + *flags = ROTPK_NOT_DEPLOYED; + ret = 0; + + } else if ((sbl_status() == SBL_ENABLED) && + (mmio_read_32(BL11_DAUTH_BASE) == BL11_DAUTH_ID)) { + + /* Read hash from BL11 */ + INFO("readKeys (DAUTH) from BL11\n"); + + memcpy(dst, + (void *)(BL11_DAUTH_BASE + sizeof(uint32_t)), + SHA256_BYTES); + + for (i = 0; i < SHA256_BYTES; i++) + if (dst[i] != 0) + break; + + if (i >= SHA256_BYTES) + ERROR("Hash not valid from BL11\n"); + else + ret = 0; + + } else if (sotp_key_erased()) { + + memcpy(dst, plat_rotpk_hash, SHA256_BYTES); + + INFO("SOTP erased, Use internal key hash.\n"); + ret = 0; + + } else if (plat_fast_auth_enabled()) { + + INFO("AB DEV: FAST AUTH!\n"); + *flags = ROTPK_NOT_DEPLOYED; + ret = 0; + + } else if (!(mmio_read_32(SOTP_STATUS_1) & SOTP_DAUTH_ECC_ERROR_MASK)) { + + /* Read hash from SOTP */ + ret = sotp_read_key(dst, + SHA256_BYTES, + SOTP_DAUTH_ROW, + SOTP_K_HMAC_ROW-1); + + INFO("sotp_read_key (DAUTH): %i\n", ret); + + } else { + + uint64_t row_data; + uint32_t k; + + for (k = 0; k < (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW); k++) { + row_data = sotp_mem_read(SOTP_DAUTH_ROW + k, + SOTP_ROW_NO_ECC); + + if (row_data != 0) + break; + } + + if (k == (SOTP_K_HMAC_ROW - SOTP_DAUTH_ROW)) { + INFO("SOTP NOT PROGRAMMED: Do not use DAUTH!\n"); + + if (sotp_mem_read(SOTP_ATF2_CFG_ROW_ID, + SOTP_ROW_NO_ECC) & SOTP_ROMKEY_MASK) { + memcpy(dst, plat_rotpk_hash, SHA256_BYTES); + + INFO("Use internal key hash.\n"); + ret = 0; + } else { + *flags = ROTPK_NOT_DEPLOYED; + ret = 0; + } + } else { + INFO("No hash found in SOTP\n"); + } + } + if (ret) + return ret; +} +#endif + + *key_ptr = (void *)rotpk_hash_der; + *key_len = (unsigned int)sizeof(rotpk_hash_der); + *flags |= ROTPK_IS_HASH; + + return 0; +} + +#define SOTP_NUM_BITS_PER_ROW 41 +#define SOTP_NVCTR_ROW_ALL_ONES 0x1ffffffffff +#define SOTP_NVCTR_TRUSTED_IN_USE \ + ((uint64_t)0x3 << (SOTP_NUM_BITS_PER_ROW-2)) +#define SOTP_NVCTR_NON_TRUSTED_IN_USE ((uint64_t)0x3) +#define SOTP_NVCTR_TRUSTED_NEAR_END SOTP_NVCTR_NON_TRUSTED_IN_USE +#define SOTP_NVCTR_NON_TRUSTED_NEAR_END SOTP_NVCTR_TRUSTED_IN_USE + +#define SOTP_NVCTR_ROW_START 64 +#define SOTP_NVCTR_ROW_END 75 + +/* + * SOTP NVCTR are stored in section 10 of SOTP (rows 64-75). + * Each row of SOTP is 41 bits. + * NVCTR's are stored in a bitstream format. + * We are tolerant to consecutive bit errors. + * Trusted NVCTR starts at the top of row 64 in bitstream format. + * Non Trusted NVCTR starts at the bottom of row 75 in reverse bitstream. + * Each row can only be used by 1 of the 2 counters. This is determined + * by 2 zeros remaining at the beginning or end of the last available row. + * If one counter has already starting using a row, the other will be + * prevent from writing to that row. + * + * Example counter values for SOTP programmed below: + * Trusted Counter (rows64-69) = 5 * 41 + 40 = 245 + * NonTrusted Counter (row75-71) = 3 * 41 + 4 = 127 + * 40 39 38 37 36 ..... 5 4 3 2 1 0 + * row 64 1 1 1 1 1 1 1 1 1 1 1 + * row 65 1 1 1 1 1 1 1 1 1 1 1 + * row 66 1 1 1 1 1 1 1 1 1 1 1 + * row 67 1 1 1 1 1 1 1 1 1 1 1 + * row 68 1 1 1 1 1 1 1 1 1 1 1 + * row 69 1 1 1 1 1 1 1 1 1 1 0 + * row 71 0 0 0 0 0 0 0 0 0 0 0 + * row 71 0 0 0 0 0 0 0 0 0 0 0 + * row 71 0 0 0 0 0 0 0 1 1 1 1 + * row 73 1 1 1 1 1 1 1 1 1 1 1 + * row 74 1 1 1 1 1 1 1 1 1 1 1 + * row 75 1 1 1 1 1 1 1 1 1 1 1 + * + */ + +#if (DEBUG == 1) +/* + * Dump sotp rows + */ +void sotp_dump_rows(uint32_t start_row, uint32_t end_row) +{ + int32_t rownum; + uint64_t rowdata; + + for (rownum = start_row; rownum <= end_row; rownum++) { + rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); + INFO("%d 0x%" PRIx64 "\n", rownum, rowdata); + } +} +#endif + +/* + * Get SOTP Trusted nvctr + */ +unsigned int sotp_get_trusted_nvctr(void) +{ + uint64_t rowdata; + uint64_t nextrowdata; + uint32_t rownum; + unsigned int nvctr; + + rownum = SOTP_NVCTR_ROW_START; + nvctr = SOTP_NUM_BITS_PER_ROW; + + /* + * Determine what row has last valid data for trusted ctr + */ + rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); + while ((rowdata & SOTP_NVCTR_TRUSTED_IN_USE) && + (rowdata & SOTP_NVCTR_TRUSTED_NEAR_END) && + (rownum < SOTP_NVCTR_ROW_END)) { + /* + * Current row in use and has data in last 2 bits as well. + * Check if next row also has data for this counter + */ + nextrowdata = sotp_mem_read(rownum+1, SOTP_ROW_NO_ECC); + if (nextrowdata & SOTP_NVCTR_TRUSTED_IN_USE) { + /* Next row also has data so increment rownum */ + rownum++; + nvctr += SOTP_NUM_BITS_PER_ROW; + rowdata = nextrowdata; + } else { + /* Next row does not have data */ + break; + } + } + + if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) { + while ((rowdata & 0x1) == 0) { + nvctr--; + rowdata >>= 1; + } + } else + nvctr -= SOTP_NUM_BITS_PER_ROW; + + INFO("CTR %i\n", nvctr); + return nvctr; +} + +/* + * Get SOTP NonTrusted nvctr + */ +unsigned int sotp_get_nontrusted_nvctr(void) +{ + uint64_t rowdata; + uint64_t nextrowdata; + uint32_t rownum; + unsigned int nvctr; + + nvctr = SOTP_NUM_BITS_PER_ROW; + rownum = SOTP_NVCTR_ROW_END; + + /* + * Determine what row has last valid data for nontrusted ctr + */ + rowdata = sotp_mem_read(rownum, SOTP_ROW_NO_ECC); + while ((rowdata & SOTP_NVCTR_NON_TRUSTED_NEAR_END) && + (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) && + (rownum > SOTP_NVCTR_ROW_START)) { + /* + * Current row in use and has data in last 2 bits as well. + * Check if next row also has data for this counter + */ + nextrowdata = sotp_mem_read(rownum-1, SOTP_ROW_NO_ECC); + if (nextrowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) { + /* Next row also has data so decrement rownum */ + rownum--; + nvctr += SOTP_NUM_BITS_PER_ROW; + rowdata = nextrowdata; + } else { + /* Next row does not have data */ + break; + } + } + + if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) { + while ((rowdata & ((uint64_t)0x1 << (SOTP_NUM_BITS_PER_ROW-1))) + == + 0) { + nvctr--; + rowdata <<= 1; + } + } else + nvctr -= SOTP_NUM_BITS_PER_ROW; + + INFO("NCTR %i\n", nvctr); + return nvctr; +} + +/* + * Set SOTP Trusted nvctr + */ +int sotp_set_trusted_nvctr(unsigned int nvctr) +{ + int numrows_available; + uint32_t nontrusted_rownum; + uint32_t trusted_rownum; + uint64_t rowdata; + unsigned int maxnvctr; + + /* + * Read SOTP to find out how many rows are used by the + * NON Trusted nvctr + */ + nontrusted_rownum = SOTP_NVCTR_ROW_END; + do { + rowdata = sotp_mem_read(nontrusted_rownum, SOTP_ROW_NO_ECC); + if (rowdata & SOTP_NVCTR_NON_TRUSTED_IN_USE) + nontrusted_rownum--; + else + break; + } while (nontrusted_rownum >= SOTP_NVCTR_ROW_START); + + /* + * Calculate maximum value we can have for nvctr based on + * number of available rows. + */ + numrows_available = nontrusted_rownum - SOTP_NVCTR_ROW_START + 1; + maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW; + if (maxnvctr) { + /* + * Last 2 bits of counter can't be written or it will + * overflow with nontrusted counter + */ + maxnvctr -= 2; + } + + if (nvctr > maxnvctr) { + /* Error - not enough room */ + WARN("tctr not set\n"); + return 1; + } + + /* + * It is safe to write the nvctr, fill all 1's up to the + * last row and then fill the last row with partial bitstream + */ + trusted_rownum = SOTP_NVCTR_ROW_START; + rowdata = SOTP_NVCTR_ROW_ALL_ONES; + + while (nvctr >= SOTP_NUM_BITS_PER_ROW) { + sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata); + nvctr -= SOTP_NUM_BITS_PER_ROW; + trusted_rownum++; + } + rowdata <<= (SOTP_NUM_BITS_PER_ROW - nvctr); + sotp_mem_write(trusted_rownum, SOTP_ROW_NO_ECC, rowdata); + return 0; +} + +/* + * Set SOTP NonTrusted nvctr + */ +int sotp_set_nontrusted_nvctr(unsigned int nvctr) +{ + int numrows_available; + uint32_t nontrusted_rownum; + uint32_t trusted_rownum; + uint64_t rowdata; + unsigned int maxnvctr; + + /* + * Read SOTP to find out how many rows are used by the + * Trusted nvctr + */ + trusted_rownum = SOTP_NVCTR_ROW_START; + do { + rowdata = sotp_mem_read(trusted_rownum, SOTP_ROW_NO_ECC); + if (rowdata & SOTP_NVCTR_TRUSTED_IN_USE) + trusted_rownum++; + else + break; + } while (trusted_rownum <= SOTP_NVCTR_ROW_END); + + /* + * Calculate maximum value we can have for nvctr based on + * number of available rows. + */ + numrows_available = SOTP_NVCTR_ROW_END - trusted_rownum + 1; + maxnvctr = numrows_available * SOTP_NUM_BITS_PER_ROW; + if (maxnvctr) { + /* + * Last 2 bits of counter can't be written or it will + * overflow with nontrusted counter + */ + maxnvctr -= 2; + } + + if (nvctr > maxnvctr) { + /* Error - not enough room */ + WARN("nctr not set\n"); + return 1; + } + + /* + * It is safe to write the nvctr, fill all 1's up to the + * last row and then fill the last row with partial bitstream + */ + nontrusted_rownum = SOTP_NVCTR_ROW_END; + rowdata = SOTP_NVCTR_ROW_ALL_ONES; + + while (nvctr >= SOTP_NUM_BITS_PER_ROW) { + sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata); + nvctr -= SOTP_NUM_BITS_PER_ROW; + nontrusted_rownum--; + } + rowdata >>= (SOTP_NUM_BITS_PER_ROW - nvctr); + sotp_mem_write(nontrusted_rownum, SOTP_ROW_NO_ECC, rowdata); + return 0; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * will contain the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + const char *oid; + + assert(cookie != NULL); + assert(nv_ctr != NULL); + + *nv_ctr = 0; + if ((sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & + SOTP_ATF_NVCOUNTER_ENABLE_MASK)) { + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) + *nv_ctr = sotp_get_trusted_nvctr(); + else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) + *nv_ctr = sotp_get_nontrusted_nvctr(); + else + return 1; + } + return 0; +} + +/* + * Store a new non-volatile counter value. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + const char *oid; + + if (sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) & + SOTP_ATF_NVCOUNTER_ENABLE_MASK) { + INFO("set CTR %i\n", nv_ctr); + oid = (const char *)cookie; + if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) + return sotp_set_trusted_nvctr(nv_ctr); + else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) + return sotp_set_nontrusted_nvctr(nv_ctr); + return 1; + } + return 0; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/plat/brcm/board/common/board_common.c b/plat/brcm/board/common/board_common.c new file mode 100644 index 0000000..2f764ab --- /dev/null +++ b/plat/brcm/board/common/board_common.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <brcm_def.h> +#include <plat_brcm.h> + +#if IMAGE_BL2 +const mmap_region_t plat_brcm_mmap[] = { + HSLS_REGION, + BRCM_MAP_SHARED_RAM, + BRCM_MAP_NAND_RO, + BRCM_MAP_QSPI_RO, +#ifdef PERIPH0_REGION + PERIPH0_REGION, +#endif +#ifdef PERIPH1_REGION + PERIPH1_REGION, +#endif +#ifdef USE_DDR + BRCM_MAP_NS_DRAM1, +#if BRCM_BL31_IN_DRAM + BRCM_MAP_BL31_SEC_DRAM, +#endif +#else +#ifdef BRCM_MAP_EXT_SRAM + BRCM_MAP_EXT_SRAM, +#endif +#endif +#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE) + CRMU_SRAM_REGION, +#endif + {0} +}; +#endif + +#if IMAGE_BL31 +const mmap_region_t plat_brcm_mmap[] = { + HSLS_REGION, +#ifdef PERIPH0_REGION + PERIPH0_REGION, +#endif +#ifdef PERIPH1_REGION + PERIPH1_REGION, +#endif +#ifdef PERIPH2_REGION + PERIPH2_REGION, +#endif +#ifdef USB_REGION + USB_REGION, +#endif +#ifdef USE_DDR + BRCM_MAP_NS_DRAM1, +#ifdef BRCM_MAP_NS_SHARED_DRAM + BRCM_MAP_NS_SHARED_DRAM, +#endif +#else +#ifdef BRCM_MAP_EXT_SRAM + BRCM_MAP_EXT_SRAM, +#endif +#endif +#if defined(USE_CRMU_SRAM) && defined(CRMU_SRAM_BASE) + CRMU_SRAM_REGION, +#endif + {0} +}; +#endif + +CASSERT((ARRAY_SIZE(plat_brcm_mmap) - 1) <= PLAT_BRCM_MMAP_ENTRIES, + assert_plat_brcm_mmap_mismatch); +CASSERT((PLAT_BRCM_MMAP_ENTRIES + BRCM_BL_REGIONS) <= MAX_MMAP_REGIONS, + assert_max_mmap_regions); diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk new file mode 100644 index 0000000..24a27ed --- /dev/null +++ b/plat/brcm/board/common/board_common.mk @@ -0,0 +1,294 @@ +# +# Copyright (c) 2015 - 2021, Broadcom +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_BL_COMMON_SOURCES += plat/brcm/board/common/board_common.c + +# If no board config makefile, do not include it +ifneq (${BOARD_CFG},) +BOARD_CFG_MAKE := $(shell find plat/brcm/board/${PLAT} -name '${BOARD_CFG}.mk') +$(eval $(call add_define,BOARD_CFG)) +ifneq (${BOARD_CFG_MAKE},) +$(info Including ${BOARD_CFG_MAKE}) +include ${BOARD_CFG_MAKE} +else +$(error Error: File ${BOARD_CFG}.mk not found in plat/brcm/board/${PLAT}) +endif +endif + +# To compile with highest log level (VERBOSE) set value to 50 +LOG_LEVEL := 40 + +# Use custom generic timer clock +ifneq (${GENTIMER_ACTUAL_CLOCK},) +$(info Using GENTIMER_ACTUAL_CLOCK=$(GENTIMER_ACTUAL_CLOCK)) +SYSCNT_FREQ := $(GENTIMER_ACTUAL_CLOCK) +$(eval $(call add_define,SYSCNT_FREQ)) +endif + +ifeq (${DRIVER_EMMC_ENABLE},) +DRIVER_EMMC_ENABLE :=1 +endif + +ifeq (${DRIVER_SPI_ENABLE},) +DRIVER_SPI_ENABLE := 0 +endif + +ifeq (${DRIVER_I2C_ENABLE},) +DRIVER_I2C_ENABLE := 0 +endif + +# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set +ifeq (${BRCM_DISABLE_TRUSTED_WDOG},) +BRCM_DISABLE_TRUSTED_WDOG := 0 +endif +ifeq (${SPIN_ON_BL1_EXIT}, 1) +BRCM_DISABLE_TRUSTED_WDOG := 1 +endif + +$(eval $(call assert_boolean,BRCM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,BRCM_DISABLE_TRUSTED_WDOG)) + +# Process ARM_BL31_IN_DRAM flag +ifeq (${ARM_BL31_IN_DRAM},) +ARM_BL31_IN_DRAM := 0 +endif +$(eval $(call assert_boolean,ARM_BL31_IN_DRAM)) +$(eval $(call add_define,ARM_BL31_IN_DRAM)) + +ifeq (${STANDALONE_BL2},yes) +BL2_LOG_LEVEL := 40 +$(eval $(call add_define,MMU_DISABLED)) +endif + +# BL2 XIP from QSPI +RUN_BL2_FROM_QSPI := 0 +ifeq (${RUN_BL2_FROM_QSPI},1) +$(eval $(call add_define,RUN_BL2_FROM_QSPI)) +endif + +# BL2 XIP from NAND +RUN_BL2_FROM_NAND := 0 +ifeq (${RUN_BL2_FROM_NAND},1) +$(eval $(call add_define,RUN_BL2_FROM_NAND)) +endif + +ifneq (${ELOG_AP_UART_LOG_BASE},) +$(eval $(call add_define,ELOG_AP_UART_LOG_BASE)) +endif + +ifeq (${ELOG_SUPPORT},1) +ifeq (${ELOG_STORE_MEDIA},DDR) +$(eval $(call add_define,ELOG_STORE_MEDIA_DDR)) +ifneq (${ELOG_STORE_OFFSET},) +$(eval $(call add_define,ELOG_STORE_OFFSET)) +endif +endif +endif + +ifneq (${BL2_LOG_LEVEL},) +$(eval $(call add_define,BL2_LOG_LEVEL)) +endif + +ifneq (${BL31_LOG_LEVEL},) +$(eval $(call add_define,BL31_LOG_LEVEL)) +endif + +# Use CRMU SRAM from iHOST +ifneq (${USE_CRMU_SRAM},) +$(eval $(call add_define,USE_CRMU_SRAM)) +endif + +# Use PIO mode if DDR is not used +ifeq (${USE_DDR},yes) +EMMC_USE_DMA := 1 +else +EMMC_USE_DMA := 0 +endif +$(eval $(call add_define,EMMC_USE_DMA)) + +# On BRCM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + +# Use generic OID definition (tbbr_oid.h) +USE_TBBR_DEFS := 1 + +PLAT_INCLUDES += -Iplat/brcm/board/common \ + -Iinclude/drivers/brcm \ + -Iinclude/drivers/brcm/emmc \ + -Iinclude/drivers/brcm/mdio + +PLAT_BL_COMMON_SOURCES += plat/brcm/common/brcm_common.c \ + plat/brcm/board/common/cmn_sec.c \ + plat/brcm/board/common/bcm_console.c \ + plat/brcm/board/common/brcm_mbedtls.c \ + plat/brcm/board/common/plat_setup.c \ + plat/brcm/board/common/platform_common.c \ + drivers/arm/sp804/sp804_delay_timer.c \ + drivers/brcm/sotp.c \ + drivers/delay_timer/delay_timer.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/brcm/common/brcm_io_storage.c \ + plat/brcm/board/common/err.c \ + plat/brcm/board/common/sbl_util.c \ + drivers/arm/sp805/sp805.c + +# Add RNG driver +DRIVER_RNG_ENABLE := 1 +ifeq (${DRIVER_RNG_ENABLE},1) +PLAT_BL_COMMON_SOURCES += drivers/brcm/rng.c +endif + +# Add eMMC driver +ifeq (${DRIVER_EMMC_ENABLE},1) +$(eval $(call add_define,DRIVER_EMMC_ENABLE)) + +EMMC_SOURCES += drivers/brcm/emmc/emmc_chal_sd.c \ + drivers/brcm/emmc/emmc_csl_sdcard.c \ + drivers/brcm/emmc/emmc_csl_sdcmd.c \ + drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c + +PLAT_BL_COMMON_SOURCES += ${EMMC_SOURCES} + +ifeq (${DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT},) +$(eval $(call add_define,DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT)) +endif +endif + +BL2_SOURCES += plat/brcm/common/brcm_bl2_mem_params_desc.c \ + plat/brcm/common/brcm_image_load.c \ + common/desc_image_load.c + +BL2_SOURCES += plat/brcm/common/brcm_bl2_setup.c + +BL31_SOURCES += plat/brcm/common/brcm_bl31_setup.c + +ifeq (${BCM_ELOG},yes) +ELOG_SOURCES += plat/brcm/board/common/bcm_elog.c +BL2_SOURCES += ${ELOG_SOURCES} +BL31_SOURCES += ${ELOG_SOURCES} +endif + +# Add spi driver +ifeq (${DRIVER_SPI_ENABLE},1) +PLAT_BL_COMMON_SOURCES += drivers/brcm/spi/iproc_spi.c \ + drivers/brcm/spi/iproc_qspi.c +endif + +# Add spi nor/flash driver +ifeq (${DRIVER_SPI_NOR_ENABLE},1) +PLAT_BL_COMMON_SOURCES += drivers/brcm/spi_sf.c \ + drivers/brcm/spi_flash.c +endif + +ifeq (${DRIVER_I2C_ENABLE},1) +$(eval $(call add_define,DRIVER_I2C_ENABLE)) +BL2_SOURCES += drivers/brcm/i2c/i2c.c +PLAT_INCLUDES += -Iinclude/drivers/brcm/i2c +endif + +ifeq (${DRIVER_OCOTP_ENABLE},1) +$(eval $(call add_define,DRIVER_OCOTP_ENABLE)) +BL2_SOURCES += drivers/brcm/ocotp.c +endif + +# Enable FRU table support +ifeq (${USE_FRU},yes) +$(eval $(call add_define,USE_FRU)) +BL2_SOURCES += drivers/brcm/fru.c +endif + +# Enable GPIO support +ifeq (${USE_GPIO},yes) +$(eval $(call add_define,USE_GPIO)) +BL2_SOURCES += drivers/gpio/gpio.c +BL2_SOURCES += drivers/brcm/iproc_gpio.c +ifeq (${GPIO_SUPPORT_FLOAT_DETECTION},yes) +$(eval $(call add_define,GPIO_SUPPORT_FLOAT_DETECTION)) +endif +endif + +# Include mbedtls if it can be located +MBEDTLS_DIR ?= mbedtls +MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '$(notdir ${MBEDTLS_DIR})') + +ifneq (${MBEDTLS_CHECK},) +$(info Found mbedTLS at ${MBEDTLS_DIR}) +PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls + +# By default, use RSA keys +KEY_ALG := rsa_1_5 + +# Include common TBB sources +AUTH_SOURCES += drivers/auth/auth_mod.c \ + drivers/auth/crypto_mod.c \ + drivers/auth/img_parser_mod.c \ + drivers/auth/tbbr/tbbr_cot_common.c \ + drivers/auth/tbbr/tbbr_cot_bl2.c + +BL2_SOURCES += ${AUTH_SOURCES} + +# Use ATF framework for MBEDTLS +TRUSTED_BOARD_BOOT := 1 +CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk +IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk +$(info Including ${CRYPTO_LIB_MK}) +include ${CRYPTO_LIB_MK} +$(info Including ${IMG_PARSER_LIB_MK}) +include ${IMG_PARSER_LIB_MK} + +# Use ATF secure boot functions +# Use Hardcoded hash for devel + +ARM_ROTPK_LOCATION=arm_rsa +ifeq (${ARM_ROTPK_LOCATION}, arm_rsa) +ARM_ROTPK_LOCATION_ID=ARM_ROTPK_DEVEL_RSA_ID +ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem +else ifeq (${ARM_ROTPK_LOCATION}, brcm_rsa) +ARM_ROTPK_LOCATION_ID=BRCM_ROTPK_SOTP_RSA_ID +ifeq (${ROT_KEY},) +ROT_KEY=plat/brcm/board/common/rotpk/rsa_dauth2048_key.pem +endif +KEY_FIND := $(shell m="${ROT_KEY}"; [ -f "$$m" ] && echo "$$m") +ifeq (${KEY_FIND},) +$(error Error: No ${ROT_KEY} located) +else +$(info Using ROT_KEY: ${ROT_KEY}) +endif +else +$(error "Unsupported ARM_ROTPK_LOCATION value") +endif + +$(eval $(call add_define,ARM_ROTPK_LOCATION_ID)) +PLAT_BL_COMMON_SOURCES+=plat/brcm/board/common/board_arm_trusted_boot.c +endif + +#M0 runtime firmware +ifdef SCP_BL2 +$(eval $(call add_define,NEED_SCP_BL2)) +SCP_CFG_DIR=$(dir ${SCP_BL2}) +PLAT_INCLUDES += -I${SCP_CFG_DIR} +endif + +ifneq (${NEED_BL33},yes) +# If there is no BL33, BL31 will jump to this address. +ifeq (${USE_DDR},yes) +PRELOADED_BL33_BASE := 0x80000000 +else +PRELOADED_BL33_BASE := 0x74000000 +endif +endif + +# Use translation tables library v1 by default +ARM_XLAT_TABLES_LIB_V1 := 1 +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c +endif diff --git a/plat/brcm/board/common/brcm_mbedtls.c b/plat/brcm/board/common/brcm_mbedtls.c new file mode 100644 index 0000000..af42b86 --- /dev/null +++ b/plat/brcm/board/common/brcm_mbedtls.c @@ -0,0 +1,12 @@ +/* + * Copyright 2015 - 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> + +void tls_exit(int code) +{ + INFO("%s: 0x%x\n", __func__, code); +} diff --git a/plat/brcm/board/common/chip_id.h b/plat/brcm/board/common/chip_id.h new file mode 100644 index 0000000..842ac1f --- /dev/null +++ b/plat/brcm/board/common/chip_id.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CHIP_ID_H +#define CHIP_ID_H + +#include <lib/mmio.h> + +#include <platform_def.h> + +#define CHIP_REV_MAJOR_MASK 0xF0 +#define CHIP_REV_MAJOR_AX 0x00 +#define CHIP_REV_MAJOR_BX 0x10 +#define CHIP_REV_MAJOR_CX 0x20 +#define CHIP_REV_MAJOR_DX 0x30 + +/* Get Chip ID (product number) of the chip */ +static inline unsigned int chip_get_product_id(void) +{ + return PLAT_CHIP_ID_GET; +} + +/* Get Revision ID (major and minor) number of the chip */ +static inline unsigned int chip_get_rev_id(void) +{ + return PLAT_CHIP_REV_GET; +} + +static inline unsigned int chip_get_rev_id_major(void) +{ + return (chip_get_rev_id() & CHIP_REV_MAJOR_MASK); +} + +#endif diff --git a/plat/brcm/board/common/cmn_plat_def.h b/plat/brcm/board/common/cmn_plat_def.h new file mode 100644 index 0000000..79d9a29 --- /dev/null +++ b/plat/brcm/board/common/cmn_plat_def.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_PLAT_DEF_H +#define CMN_PLAT_DEF_H + +#include <bcm_elog.h> +#include <platform_def.h> + +#ifndef GET_LOG_LEVEL +#define GET_LOG_LEVEL() LOG_LEVEL +#endif + +#ifndef SET_LOG_LEVEL +#define SET_LOG_LEVEL(x) ((void)(x)) +#endif + +#define PLAT_LOG_NOTICE(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_NOTICE) { \ + bcm_elog(LOG_MARKER_NOTICE __VA_ARGS__); \ + tf_log(LOG_MARKER_NOTICE __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_ERROR(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_ERROR) { \ + bcm_elog(LOG_MARKER_ERROR, __VA_ARGS__); \ + tf_log(LOG_MARKER_ERROR __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_WARN(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_WARNING) { \ + bcm_elog(LOG_MARKER_WARNING, __VA_ARGS__);\ + tf_log(LOG_MARKER_WARNING __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_INFO(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_INFO) { \ + bcm_elog(LOG_MARKER_INFO __VA_ARGS__); \ + tf_log(LOG_MARKER_INFO __VA_ARGS__); \ + } \ + } while (0) + +#define PLAT_LOG_VERBOSE(...) \ + do { \ + if (GET_LOG_LEVEL() >= LOG_LEVEL_VERBOSE) { \ + bcm_elog(LOG_MARKER_VERBOSE __VA_ARGS__);\ + tf_log(LOG_MARKER_VERBOSE __VA_ARGS__); \ + } \ + } while (0) + +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#if USE_COHERENT_MEM +#define CMN_BL_REGIONS 3 +#else +#define CMN_BL_REGIONS 2 +#endif + +/* + * FIP definitions + */ +#define PLAT_FIP_ATTEMPT_OFFSET 0x20000 +#define PLAT_FIP_NUM_ATTEMPTS 128 + +#define PLAT_BRCM_FIP_QSPI_BASE QSPI_BASE_ADDR +#define PLAT_BRCM_FIP_NAND_BASE NAND_BASE_ADDR +#define PLAT_BRCM_FIP_MAX_SIZE 0x01000000 + +#define PLAT_BRCM_FIP_BASE PLAT_BRCM_FIP_QSPI_BASE +#endif diff --git a/plat/brcm/board/common/cmn_plat_util.h b/plat/brcm/board/common/cmn_plat_util.h new file mode 100644 index 0000000..178c843 --- /dev/null +++ b/plat/brcm/board/common/cmn_plat_util.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_PLAT_UTIL_H +#define CMN_PLAT_UTIL_H + +#include <lib/mmio.h> + +/* BOOT source */ +#define BOOT_SOURCE_MASK 7 +#define BOOT_SOURCE_QSPI 0 +#define BOOT_SOURCE_NAND 1 +#define BOOT_SOURCE_SPI_NAND 2 +#define BOOT_SOURCE_UART 3 +#define BOOT_SOURCE_RES4 4 +#define BOOT_SOURCE_EMMC 5 +#define BOOT_SOURCE_ATE 6 +#define BOOT_SOURCE_USB 7 +#define BOOT_SOURCE_MAX 8 +#define BOOT_SOURCE_UNKNOWN (-1) + +#define KHMAC_SHA256_KEY_SIZE 32 + +#define SOFT_PWR_UP_RESET_L0 0 +#define SOFT_SYS_RESET_L1 1 +#define SOFT_RESET_L3 0x3 + +#define BOOT_SOURCE_SOFT_DATA_OFFSET 8 +#define BOOT_SOURCE_SOFT_ENABLE_OFFSET 14 +#define BOOT_SOURCE_SOFT_ENABLE_MASK BIT(BOOT_SOURCE_SOFT_ENABLE_OFFSET) + +typedef struct _key { + uint8_t hmac_sha256[KHMAC_SHA256_KEY_SIZE]; +} cmn_key_t; + +uint32_t boot_source_get(void); +void bl1_platform_wait_events(void); +void plat_soft_reset(uint32_t reset); + +#endif diff --git a/plat/brcm/board/common/cmn_sec.c b/plat/brcm/board/common/cmn_sec.c new file mode 100644 index 0000000..c80d5dd --- /dev/null +++ b/plat/brcm/board/common/cmn_sec.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <common/debug.h> +#include <lib/mmio.h> + +#include <cmn_sec.h> + +#pragma weak plat_tz_master_default_cfg +#pragma weak plat_tz_sdio_ns_master_set +#pragma weak plat_tz_usb_ns_master_set + +void plat_tz_master_default_cfg(void) +{ + /* This function should be implemented in the platform side. */ + ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__); +} + +void plat_tz_sdio_ns_master_set(uint32_t ns) +{ + /* This function should be implemented in the platform side. */ + ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__); +} + +void plat_tz_usb_ns_master_set(uint32_t ns) +{ + /* This function should be implemented in the platform side. */ + ERROR("%s: TZ CONFIGURATION NOT SET!!!\n", __func__); +} + +void tz_master_default_cfg(void) +{ + plat_tz_master_default_cfg(); +} + +void tz_sdio_ns_master_set(uint32_t ns) +{ + plat_tz_sdio_ns_master_set(ns); +} + +void tz_usb_ns_master_set(uint32_t ns) +{ + plat_tz_usb_ns_master_set(ns); +} diff --git a/plat/brcm/board/common/cmn_sec.h b/plat/brcm/board/common/cmn_sec.h new file mode 100644 index 0000000..f74863d --- /dev/null +++ b/plat/brcm/board/common/cmn_sec.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_SEC_H +#define CMN_SEC_H + +#include <stdint.h> + +#define SECURE_MASTER 0 +#define NS_MASTER 1 + +void tz_master_default_cfg(void); +void tz_usb_ns_master_set(uint32_t ns); +void tz_sdio_ns_master_set(uint32_t ns); + +#endif diff --git a/plat/brcm/board/common/err.c b/plat/brcm/board/common/err.c new file mode 100644 index 0000000..1fc73c4 --- /dev/null +++ b/plat/brcm/board/common/err.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/console.h> +#include <lib/mmio.h> + +#include <platform_def.h> + +#define L0_RESET 0x2 + +/* + * Brcm error handler + */ +void plat_error_handler(int err) +{ + INFO("L0 reset...\n"); + + /* Ensure the characters are flushed out */ + console_flush(); + + mmio_write_32(CRMU_SOFT_RESET_CTRL, L0_RESET); + + /* + * In case we get here: + * Loop until the watchdog resets the system + */ + while (1) { + wfi(); + } +} diff --git a/plat/brcm/board/common/plat_setup.c b/plat/brcm/board/common/plat_setup.c new file mode 100644 index 0000000..95e12ed --- /dev/null +++ b/plat/brcm/board/common/plat_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/common/platform.h> + +#include <platform_def.h> + +/* + * This function returns the fixed clock frequency at which private + * timers run. This value will be programmed into CNTFRQ_EL0. + */ +unsigned int plat_get_syscnt_freq2(void) +{ + return SYSCNT_FREQ; +} + +static const char * const plat_prefix_str[] = { + "E: ", "N: ", "W: ", "I: ", "V: " +}; + +const char *plat_log_get_prefix(unsigned int log_level) +{ + return plat_prefix_str[log_level - 1U]; +} diff --git a/plat/brcm/board/common/platform_common.c b/plat/brcm/board/common/platform_common.c new file mode 100644 index 0000000..f4c9a73 --- /dev/null +++ b/plat/brcm/board/common/platform_common.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/brcm/sotp.h> + +#include <cmn_plat_util.h> +#include <platform_def.h> + +uint32_t boot_source_get(void) +{ + uint32_t data; + +#ifdef FORCE_BOOTSOURCE + data = FORCE_BOOTSOURCE; +#else + /* Read primary boot strap from CRMU persistent registers */ + data = mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1); + if (data & BOOT_SOURCE_SOFT_ENABLE_MASK) { + data >>= BOOT_SOURCE_SOFT_DATA_OFFSET; + } else { + uint64_t sotp_atf_row; + + sotp_atf_row = + sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC); + + if (sotp_atf_row & SOTP_BOOT_SOURCE_ENABLE_MASK) { + /* Construct the boot source based on SOTP bits */ + data = 0; + if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS0) + data |= 0x1; + if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS1) + data |= 0x2; + if (sotp_atf_row & SOTP_BOOT_SOURCE_BITS2) + data |= 0x4; + } else { + + /* + * This path is for L0 reset with + * Primary Boot source disabled in SOTP. + * BOOT_SOURCE_FROM_PR_ON_L1 compile flag will allow + * to never come back here so that the + * external straps will not be read on L1 reset. + */ + + /* Use the external straps */ + data = mmio_read_32(ROM_S0_IDM_IO_STATUS); + +#ifdef BOOT_SOURCE_FROM_PR_ON_L1 + /* Enable boot source read from PR#1 */ + mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, + BOOT_SOURCE_SOFT_ENABLE_MASK); + + /* set boot source */ + data &= BOOT_SOURCE_MASK; + mmio_clrsetbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, + BOOT_SOURCE_MASK << BOOT_SOURCE_SOFT_DATA_OFFSET, + data << BOOT_SOURCE_SOFT_DATA_OFFSET); +#endif + } + } +#endif + return (data & BOOT_SOURCE_MASK); +} + +void __dead2 plat_soft_reset(uint32_t reset) +{ + if (reset == SOFT_RESET_L3) { + mmio_setbits_32(CRMU_IHOST_SW_PERSISTENT_REG1, reset); + mmio_write_32(CRMU_MAIL_BOX0, 0x0); + mmio_write_32(CRMU_MAIL_BOX1, 0xFFFFFFFF); + } + + if (reset != SOFT_SYS_RESET_L1) + reset = SOFT_PWR_UP_RESET_L0; + + if (reset == SOFT_PWR_UP_RESET_L0) + INFO("L0 RESET...\n"); + + if (reset == SOFT_SYS_RESET_L1) + INFO("L1 RESET...\n"); + + console_flush(); + + mmio_clrbits_32(CRMU_SOFT_RESET_CTRL, 1 << reset); + + while (1) { + ; + } +} diff --git a/plat/brcm/board/common/sbl_util.c b/plat/brcm/board/common/sbl_util.c new file mode 100644 index 0000000..06e5b33 --- /dev/null +++ b/plat/brcm/board/common/sbl_util.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdint.h> + +#include <common/debug.h> + +#include <platform_def.h> +#include <sbl_util.h> +#include <sotp.h> + +#pragma weak plat_sbl_status + +int plat_sbl_status(uint64_t sbl_status) +{ + return sbl_status ? 1:0; +} + +int sbl_status(void) +{ + uint64_t sbl_sotp = 0; + int ret = SBL_DISABLED; + + sbl_sotp = sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC); + + if (sbl_sotp != SOTP_ECC_ERR_DETECT) { + + sbl_sotp &= SOTP_SBL_MASK; + + if (plat_sbl_status(sbl_sotp)) + ret = SBL_ENABLED; + } + + VERBOSE("SBL status: %d\n", ret); + + return ret; +} diff --git a/plat/brcm/board/common/sbl_util.h b/plat/brcm/board/common/sbl_util.h new file mode 100644 index 0000000..0747389 --- /dev/null +++ b/plat/brcm/board/common/sbl_util.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBL_UTIL_H +#define SBL_UTIL_H + +#include <stdint.h> + +#include <sotp.h> + +#define SBL_DISABLED 0 +#define SBL_ENABLED 1 + +int sbl_status(void); + +#endif /* #ifdef SBL_UTIL_H */ diff --git a/plat/brcm/board/common/timer_sync.c b/plat/brcm/board/common/timer_sync.c new file mode 100644 index 0000000..7e33a94 --- /dev/null +++ b/plat/brcm/board/common/timer_sync.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> + +#include <platform_def.h> +#include <timer_sync.h> + +/******************************************************************************* + * Defines related to time sync and satelite timers + ******************************************************************************/ +#define TIME_SYNC_WR_ENA ((uint32_t)0xACCE55 << 8) +#define IHOST_STA_TMR_CTRL 0x1800 +#define IHOST_SAT_TMR_INC_L 0x1814 +#define IHOST_SAT_TMR_INC_H 0x1818 + +#define SAT_TMR_CYCLE_DELAY 2 +#define SAT_TMR_32BIT_WRAP_VAL (BIT_64(32) - SAT_TMR_CYCLE_DELAY) + +void ihost_enable_satellite_timer(unsigned int cluster_id) +{ + uintptr_t ihost_base; + uint32_t time_lx, time_h; + uintptr_t ihost_enable; + + VERBOSE("Program iHost%u satellite timer\n", cluster_id); + ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE; + + /* this read starts the satellite timer counting from 0 */ + ihost_enable = CENTRAL_TIMER_GET_IHOST_ENA_BASE + cluster_id * 4; + time_lx = mmio_read_32(ihost_enable); + + /* + * Increment the satellite timer by the central timer plus 2 + * to accommodate for a 1 cycle delay through NOC + * plus counter starting from 0. + */ + mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_L, + time_lx + SAT_TMR_CYCLE_DELAY); + + /* + * Read the latched upper data, if lx will wrap by adding 2 to it + * we need to handle the wrap + */ + time_h = mmio_read_32(CENTRAL_TIMER_GET_H); + if (time_lx >= SAT_TMR_32BIT_WRAP_VAL) + mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h + 1); + else + mmio_write_32(ihost_base + IHOST_SAT_TMR_INC_H, time_h); +} + +void brcm_timer_sync_init(void) +{ + unsigned int cluster_id; + + /* Get the Time Sync module out of reset */ + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, + BIT(CDRU_MISC_RESET_CONTROL_TS_RESET_N)); + + /* Deassert the Central Timer TIMER_EN signal for all module */ + mmio_write_32(CENTRAL_TIMER_SAT_TMR_ENA, TIME_SYNC_WR_ENA); + + /* enables/programs iHost0 satellite timer*/ + cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr()); + ihost_enable_satellite_timer(cluster_id); +} |