GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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 */
|
||||
+625
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
+294
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
+94
@@ -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) {
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <cpu_macros.S>
|
||||
#include <cortex_a72.h>
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_reset_handler
|
||||
.globl platform_get_entrypoint
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl platform_mem_init
|
||||
.globl platform_check_mpidr
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_crash_console_flush
|
||||
.globl plat_disable_acp
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_my_core_pos
|
||||
.globl platform_is_primary_cpu
|
||||
.globl plat_brcm_calc_core_pos
|
||||
.globl plat_get_my_entrypoint
|
||||
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* void plat_l2_init(void);
|
||||
*
|
||||
* BL1 and BL2 run with one core, one cluster
|
||||
* This is safe to disable cluster coherency
|
||||
* to make use of the data cache MMU WB attribute
|
||||
* for the SRAM.
|
||||
*
|
||||
* Set L2 Auxiliary Control Register
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_l2_init
|
||||
mrs x0, CORTEX_A72_L2ACTLR_EL1
|
||||
#if (IMAGE_BL1 || IMAGE_BL2) || defined(USE_SINGLE_CLUSTER)
|
||||
orr x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI
|
||||
#else
|
||||
bic x0, x0, #CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI
|
||||
#endif
|
||||
msr CORTEX_A72_L2ACTLR_EL1, x0
|
||||
|
||||
/* Set L2 Control Register */
|
||||
mrs x0, CORTEX_A72_L2CTLR_EL1
|
||||
mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_MASK << \
|
||||
CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
|
||||
(CORTEX_A72_L2_TAG_RAM_LATENCY_MASK << \
|
||||
CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT) | \
|
||||
(U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \
|
||||
(U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT))
|
||||
bic x0, x0, x1
|
||||
mov x1, #((CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES << \
|
||||
CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
|
||||
(U(0x1) << CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT) | \
|
||||
(U(0x1) << CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT))
|
||||
orr x0, x0, x1
|
||||
msr CORTEX_A72_L2CTLR_EL1, x0
|
||||
|
||||
isb
|
||||
ret
|
||||
endfunc plat_l2_init
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* void plat_reset_handler(void);
|
||||
*
|
||||
* Before adding code in this function, refer to the guidelines in
|
||||
* docs/firmware-design.md.
|
||||
*
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func plat_reset_handler
|
||||
mov x9, x30
|
||||
bl plat_l2_init
|
||||
mov x30, x9
|
||||
ret
|
||||
endfunc plat_reset_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void platform_get_entrypoint (unsigned int mpid);
|
||||
*
|
||||
* Main job of this routine is to distinguish between
|
||||
* a cold and warm boot.
|
||||
* On a cold boot the secondaries first wait for the
|
||||
* platform to be initialized after which they are
|
||||
* hotplugged in. The primary proceeds to perform the
|
||||
* platform initialization.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func platform_get_entrypoint
|
||||
/*TBD-STINGRAY*/
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc platform_get_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset e.g
|
||||
* mark the cpu's presence, mechanism to place it in a
|
||||
* holding pen etc.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
bl plat_my_core_pos
|
||||
mov_imm x1, SECONDARY_CPU_SPIN_BASE_ADDR
|
||||
add x0, x1, x0, LSL #3
|
||||
mov x1, #0
|
||||
str x1, [x0]
|
||||
|
||||
/* Wait until the entrypoint gets populated */
|
||||
poll_mailbox:
|
||||
ldr x1, [x0]
|
||||
cbz x1, 1f
|
||||
br x1
|
||||
1:
|
||||
wfe
|
||||
b poll_mailbox
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void platform_mem_init(void);
|
||||
*
|
||||
* We don't need to carry out any memory initialization
|
||||
* on CSS platforms. The Secure RAM is accessible straight away.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func platform_mem_init
|
||||
/*TBD-STINGRAY*/
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func platform_check_mpidr
|
||||
/*TBD-STINGRAY*/
|
||||
mov x0, xzr
|
||||
ret
|
||||
endfunc platform_check_mpidr
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_init(void)
|
||||
* Function to initialize the crash console
|
||||
* without a C Runtime to print crash report.
|
||||
* Clobber list : x0, x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, BRCM_CRASH_CONSOLE_BASE
|
||||
mov_imm x1, BRCM_CRASH_CONSOLE_REFCLK
|
||||
mov_imm x2, BRCM_CRASH_CONSOLE_BAUDRATE
|
||||
b console_16550_core_init
|
||||
ret
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_putc(void)
|
||||
* Function to print a character on the crash
|
||||
* console without a C Runtime.
|
||||
* Clobber list : x1, x2, x3
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, BRCM_CRASH_CONSOLE_BASE
|
||||
b console_16550_core_putc
|
||||
ret
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_crash_console_flush(void)
|
||||
* Function to flush crash console
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
mov_imm x0, BRCM_CRASH_CONSOLE_BASE
|
||||
b console_16550_core_flush
|
||||
ret
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Placeholder function which should be redefined by
|
||||
* each platform. This function is allowed to use
|
||||
* registers x0 - x17.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
func plat_disable_acp
|
||||
/*TBD-STINGRAY*/
|
||||
ret
|
||||
endfunc plat_disable_acp
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu (applicable only after a cold boot)
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
b platform_is_primary_cpu
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_my_core_pos(void)
|
||||
* This function uses the plat_brcm_calc_core_pos()
|
||||
* definition to get the index of the calling CPU.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
b plat_brcm_calc_core_pos
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int platform_is_primary_cpu (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu (applicable only after a cold boot)
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func platform_is_primary_cpu
|
||||
mov x9, x30
|
||||
bl plat_my_core_pos
|
||||
cmp x0, #PRIMARY_CPU
|
||||
cset x0, eq
|
||||
ret x9
|
||||
endfunc platform_is_primary_cpu
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_brcm_calc_core_pos(uint64_t mpidr)
|
||||
* Helper function to calculate the core position.
|
||||
* With this function: CorePos = (ClusterId * 4) +
|
||||
* CoreId
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_brcm_calc_core_pos
|
||||
and x1, x0, #MPIDR_CPU_MASK
|
||||
and x0, x0, #MPIDR_CLUSTER_MASK
|
||||
add x0, x1, x0, LSR #7
|
||||
ret
|
||||
endfunc plat_brcm_calc_core_pos
|
||||
|
||||
func plat_get_my_entrypoint
|
||||
mrs x0, mpidr_el1
|
||||
b platform_get_entrypoint
|
||||
endfunc plat_get_my_entrypoint
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2015 - 2020, Broadcom
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
#######################################################
|
||||
# Board config file for bcm958742t-ns3 Stingray SST100-NS3
|
||||
#######################################################
|
||||
|
||||
include plat/brcm/board/stingray/bcm958742t.mk
|
||||
|
||||
# Load BL33 at 0xFF00_0000 address
|
||||
ifneq (${BL33_OVERRIDE_LOAD_ADDR},)
|
||||
$(eval $(call add_define_val,BL33_OVERRIDE_LOAD_ADDR,0xFF000000))
|
||||
endif
|
||||
|
||||
# Nitro DDR secure memory
|
||||
# Nitro FW and config 0x8AE00000 - 0x8B000000
|
||||
# Nitro Crash dump 0x8B000000 - 0x8D000000
|
||||
DDR_NITRO_SECURE_REGION_START := 0x8AE00000
|
||||
DDR_NITRO_SECURE_REGION_END := 0x8D000000
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2015 - 2020, Broadcom
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
#######################################################
|
||||
# Board config file for bcm958742t Stingray SST100
|
||||
#######################################################
|
||||
BOARD_FAMILY := "<bcm958742t.h>"
|
||||
$(eval $(call add_define,BOARD_FAMILY))
|
||||
|
||||
# Board has internal programmable regulator
|
||||
IHOST_REG_TYPE := IHOST_REG_INTEGRATED
|
||||
$(eval $(call add_define,IHOST_REG_TYPE))
|
||||
|
||||
# Board has internal programmable regulator
|
||||
VDDC_REG_TYPE := VDDC_REG_INTEGRATED
|
||||
$(eval $(call add_define,VDDC_REG_TYPE))
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef BOARD_FAMILY_H
|
||||
#define BOARD_FAMILY_H
|
||||
|
||||
#if defined(DRIVER_SPD_ENABLE) && !defined(DRIVER_SPD_SPOOF)
|
||||
#include <spd.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPIO
|
||||
/* max number of supported GPIOs to construct the bitmap for board detection */
|
||||
#define MAX_NR_GPIOS 4
|
||||
|
||||
/* max GPIO bitmap value */
|
||||
#define MAX_GPIO_BITMAP_VAL (BIT(MAX_NR_GPIOS) - 1)
|
||||
#endif
|
||||
|
||||
struct mcb_ref_group {
|
||||
uint32_t mcb_ref;
|
||||
unsigned int *mcb_cfg;
|
||||
};
|
||||
|
||||
#define MCB_REF_GROUP(ref) \
|
||||
{ \
|
||||
.mcb_ref = 0x ## ref, \
|
||||
.mcb_cfg = mcb_ ## ref, \
|
||||
}
|
||||
|
||||
#endif
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
static void brcm_stingray_pnor_pinmux_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
INFO(" - pnor pinmux init start.\n");
|
||||
|
||||
/* Set PNOR_ADV_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2dc),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_BAA_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e0),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_BLS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e4),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_BLS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2e8),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_CRE_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2ec),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_CS_2_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f0),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_CS_1_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f4),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_CS_0_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2f8),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x2fc),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_OE_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x300),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_INTR_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x304),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set PNOR_DAT_x_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
for (i = 0; i < 0x40; i += 0x4) {
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x308 + i),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
}
|
||||
|
||||
/* Set NAND_CE1_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x348),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_CE0_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x34c),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_WE_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x350),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_WP_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x354),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_RE_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x358),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_RDY_BSY_N_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x35c),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_IOx_0_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
for (i = 0; i < 0x40; i += 0x4) {
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x360 + i),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
}
|
||||
|
||||
/* Set NAND_ALE_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a0),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
/* Set NAND_CLE_MODE_SEL_CONTROL.fsel = 0x2 */
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x3a4),
|
||||
MODE_SEL_CONTROL_FSEL_MASK,
|
||||
MODE_SEL_CONTROL_FSEL_MODE2);
|
||||
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x40), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x44), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x48), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x4c), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x50), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x54), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x58), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x5c), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x60), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x64), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x68), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x6c), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x70), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x74), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x78), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x7c), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x80), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x84), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x88), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x8c), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x90), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x94), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x98), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0x9c), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa0), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa4), (7 << 1), 0x8);
|
||||
mmio_clrsetbits_32((uintptr_t)(HSLS_IOPAD_BASE + 0xa8), (7 << 1), 0x8);
|
||||
|
||||
INFO(" - pnor pinmux init done.\n");
|
||||
}
|
||||
|
||||
#if BL2_TEST_EXT_SRAM
|
||||
#define SRAM_CHECKS_GRANUL 0x100000
|
||||
#define SRAM_CHECKS_CNT 8
|
||||
static unsigned int sram_checks[SRAM_CHECKS_CNT] = {
|
||||
/* offset, magic */
|
||||
0xd00dfeed,
|
||||
0xfadebabe,
|
||||
0xc001d00d,
|
||||
0xa5a5b5b5,
|
||||
0x5a5a5b5b,
|
||||
0xc5c5d5d5,
|
||||
0x5c5c5d5d,
|
||||
0xe5e5f5f5,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void brcm_stingray_pnor_sram_init(void)
|
||||
{
|
||||
unsigned int val, tmp;
|
||||
#if BL2_TEST_EXT_SRAM
|
||||
unsigned int off, i;
|
||||
#endif
|
||||
INFO(" - pnor sram init start.\n");
|
||||
|
||||
/* Enable PNOR Clock */
|
||||
INFO(" -- enable pnor clock\n");
|
||||
mmio_write_32((uintptr_t)(PNOR_IDM_IO_CONTROL_DIRECT), 0x1);
|
||||
udelay(500);
|
||||
|
||||
/* Reset PNOR */
|
||||
INFO(" -- reset pnor\n");
|
||||
mmio_setbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1);
|
||||
udelay(500);
|
||||
mmio_clrbits_32((uintptr_t)(PNOR_IDM_IO_RESET_CONTROL), 0x1);
|
||||
udelay(500);
|
||||
|
||||
/* Configure slave address to chip-select mapping */
|
||||
INFO(" -- configure pnor slave address to chip-select mapping\n");
|
||||
/* 0x74000000-0x75ffffff => CS0 (32MB) */
|
||||
val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT);
|
||||
val |= (0x74);
|
||||
mmio_write_32((uintptr_t)(PNOR_ICFG_CS_0), val);
|
||||
/* 0x76000000-0x77ffffff => CS1 (32MB) */
|
||||
val = (0xfe << PNOR_ICFG_CS_x_MASK0_SHIFT);
|
||||
val |= (0x76);
|
||||
mmio_write_32((uintptr_t)(PNOR_ICFG_CS_1), val);
|
||||
/* 0xffffffff-0xffffffff => CS2 (0MB) */
|
||||
val = (0x00 << PNOR_ICFG_CS_x_MASK0_SHIFT);
|
||||
val |= (0xff);
|
||||
mmio_write_32((uintptr_t)(PNOR_ICFG_CS_2), val);
|
||||
|
||||
/* Print PNOR ID */
|
||||
tmp = 0x0;
|
||||
val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID0));
|
||||
tmp |= (val & PNOR_REG_PERIPH_IDx_MASK);
|
||||
val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID1));
|
||||
tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 8);
|
||||
val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID2));
|
||||
tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 16);
|
||||
val = mmio_read_32((uintptr_t)(PNOR_REG_PERIPH_ID3));
|
||||
tmp |= ((val & PNOR_REG_PERIPH_IDx_MASK) << 24);
|
||||
INFO(" -- pnor primecell_id = 0x%x\n", tmp);
|
||||
|
||||
/* PNOR set_cycles */
|
||||
#ifdef EMULATION_SETUP
|
||||
val = 0x00129A44;
|
||||
#else
|
||||
val = 0x00125954; /* 0x00002DEF; */
|
||||
#endif
|
||||
mmio_write_32((uintptr_t)(PNOR_REG_SET_CYCLES), val);
|
||||
INFO(" -- pnor set_cycles = 0x%x\n", val);
|
||||
|
||||
/* PNOR set_opmode */
|
||||
val = 0x0;
|
||||
#ifdef EMULATION_SETUP
|
||||
/* TODO: Final values to be provided by DV folks */
|
||||
val &= ~(0x7 << 7); /* set_wr_bl */
|
||||
val &= ~(0x7 << 3); /* set_rd_bl */
|
||||
val &= ~(0x3);
|
||||
val |= (0x1); /* set_mw */
|
||||
#else
|
||||
/* TODO: Final values to be provided by DV folks */
|
||||
val &= ~(0x7 << 7); /* set_wr_bl */
|
||||
val &= ~(0x7 << 3); /* set_rd_bl */
|
||||
val &= ~(0x3);
|
||||
val |= (0x1); /* set_mw */
|
||||
#endif
|
||||
mmio_write_32((uintptr_t)(PNOR_REG_SET_OPMODE), val);
|
||||
INFO(" -- pnor set_opmode = 0x%x\n", val);
|
||||
|
||||
#ifndef EMULATION_SETUP
|
||||
/* Actual SRAM chip will require self-refresh */
|
||||
val = 0x1;
|
||||
mmio_write_32((uintptr_t)(PNOR_REG_REFRESH_0), val);
|
||||
INFO(" -- pnor refresh_0 = 0x%x\n", val);
|
||||
#endif
|
||||
|
||||
#if BL2_TEST_EXT_SRAM
|
||||
/* Check PNOR SRAM access */
|
||||
for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) {
|
||||
i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT;
|
||||
val = sram_checks[i];
|
||||
INFO(" -- pnor sram write addr=0x%lx value=0x%lx\n",
|
||||
(unsigned long)(NOR_BASE_ADDR + off),
|
||||
(unsigned long)val);
|
||||
mmio_write_32((uintptr_t)(NOR_BASE_ADDR + off), val);
|
||||
}
|
||||
tmp = 0;
|
||||
for (off = 0; off < NOR_SIZE; off += SRAM_CHECKS_GRANUL) {
|
||||
i = (off / SRAM_CHECKS_GRANUL) % SRAM_CHECKS_CNT;
|
||||
val = mmio_read_32((uintptr_t)(NOR_BASE_ADDR + off));
|
||||
INFO(" -- pnor sram read addr=0x%lx value=0x%lx\n",
|
||||
(unsigned long)(NOR_BASE_ADDR + off),
|
||||
(unsigned long)val);
|
||||
if (val == sram_checks[i])
|
||||
tmp++;
|
||||
}
|
||||
INFO(" -- pnor sram checks pass=%d total=%d\n",
|
||||
tmp, (NOR_SIZE / SRAM_CHECKS_GRANUL));
|
||||
|
||||
if (tmp != (NOR_SIZE / SRAM_CHECKS_GRANUL)) {
|
||||
INFO(" - pnor sram init failed.\n");
|
||||
while (1)
|
||||
;
|
||||
} else {
|
||||
INFO(" - pnor sram init done.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ext_sram_init(void)
|
||||
{
|
||||
INFO("%s start.\n", __func__);
|
||||
|
||||
brcm_stingray_pnor_pinmux_init();
|
||||
|
||||
brcm_stingray_pnor_sram_init();
|
||||
|
||||
INFO("%s done.\n", __func__);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef EXT_SRAM_INIT_H
|
||||
#define EXT_SRAM_INIT_H
|
||||
|
||||
void ext_sram_init(void);
|
||||
#endif
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <dmu.h>
|
||||
|
||||
#define IHOST0_CONFIG_ROOT 0x66000000
|
||||
#define IHOST1_CONFIG_ROOT 0x66002000
|
||||
#define IHOST2_CONFIG_ROOT 0x66004000
|
||||
#define IHOST3_CONFIG_ROOT 0x66006000
|
||||
#define A72_CRM_PLL_PWR_ON 0x00000070
|
||||
#define A72_CRM_PLL_PWR_ON__PLL0_RESETB_R 4
|
||||
#define A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R 5
|
||||
#define A72_CRM_PLL_CHNL_BYPS_EN 0x000000ac
|
||||
#define A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R 0
|
||||
#define A72_CRM_PLL_CHNL_BYPS_EN_DATAMASK 0x0000ec1f
|
||||
#define A72_CRM_PLL_CMD 0x00000080
|
||||
#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R 0
|
||||
#define A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R 1
|
||||
#define A72_CRM_PLL_STATUS 0x00000084
|
||||
#define A72_CRM_PLL_STATUS__PLL0_LOCK_R 9
|
||||
#define A72_CRM_PLL0_CTRL1 0x00000100
|
||||
#define A72_CRM_PLL0_CTRL2 0x00000104
|
||||
#define A72_CRM_PLL0_CTRL3 0x00000108
|
||||
#define A72_CRM_PLL0_CTRL3__PLL0_PDIV_R 12
|
||||
#define A72_CRM_PLL0_CTRL4 0x0000010c
|
||||
#define A72_CRM_PLL0_CTRL4__PLL0_KP_R 0
|
||||
#define A72_CRM_PLL0_CTRL4__PLL0_KI_R 4
|
||||
#define A72_CRM_PLL0_CTRL4__PLL0_KA_R 7
|
||||
#define A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R 10
|
||||
|
||||
#define PLL_MODE_VCO 0x0
|
||||
#define PLL_MODE_BYPASS 0x1
|
||||
#define PLL_RESET_TYPE_PLL 0x1
|
||||
#define PLL_RESET_TYPE_POST 0x2
|
||||
#define PLL_VCO 0x1
|
||||
#define PLL_POSTDIV 0x2
|
||||
#define ARM_FREQ_3G PLL_FREQ_FULL
|
||||
#define ARM_FREQ_1P5G PLL_FREQ_HALF
|
||||
#define ARM_FREQ_750M PLL_FREQ_QRTR
|
||||
|
||||
static unsigned int ARMCOE_crm_getBaseAddress(unsigned int cluster_num)
|
||||
{
|
||||
unsigned int ihostx_config_root;
|
||||
|
||||
switch (cluster_num) {
|
||||
case 0:
|
||||
default:
|
||||
ihostx_config_root = IHOST0_CONFIG_ROOT;
|
||||
break;
|
||||
case 1:
|
||||
ihostx_config_root = IHOST1_CONFIG_ROOT;
|
||||
break;
|
||||
case 2:
|
||||
ihostx_config_root = IHOST2_CONFIG_ROOT;
|
||||
break;
|
||||
case 3:
|
||||
ihostx_config_root = IHOST3_CONFIG_ROOT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ihostx_config_root;
|
||||
}
|
||||
|
||||
static void ARMCOE_crm_pllAssertReset(unsigned int cluster_num,
|
||||
unsigned int reset_type)
|
||||
{
|
||||
unsigned long ihostx_config_root;
|
||||
unsigned int pll_rst_ctrl;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
|
||||
|
||||
// PLL reset
|
||||
if (reset_type & PLL_RESET_TYPE_PLL) {
|
||||
pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
|
||||
}
|
||||
// post-div channel reset
|
||||
if (reset_type & PLL_RESET_TYPE_POST) {
|
||||
pll_rst_ctrl &= ~(0x1<<A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
|
||||
}
|
||||
|
||||
mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
|
||||
}
|
||||
|
||||
static void ARMCOE_crm_pllSetMode(unsigned int cluster_num, unsigned int mode)
|
||||
{
|
||||
unsigned long ihostx_config_root;
|
||||
unsigned int pll_byp_ctrl;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
pll_byp_ctrl = mmio_read_32(ihostx_config_root +
|
||||
A72_CRM_PLL_CHNL_BYPS_EN);
|
||||
|
||||
if (mode == PLL_MODE_VCO) {
|
||||
// use PLL DCO output
|
||||
pll_byp_ctrl &=
|
||||
~BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
|
||||
} else {
|
||||
// use PLL bypass sources
|
||||
pll_byp_ctrl |=
|
||||
BIT(A72_CRM_PLL_CHNL_BYPS_EN__PLL_0_CHNL_0_BYPS_EN_R);
|
||||
}
|
||||
|
||||
mmio_write_32(ihostx_config_root + A72_CRM_PLL_CHNL_BYPS_EN,
|
||||
pll_byp_ctrl);
|
||||
}
|
||||
|
||||
static void ARMCOE_crm_pllFreqSet(unsigned int cluster_num,
|
||||
unsigned int ihost_pll_freq_sel,
|
||||
unsigned int pdiv)
|
||||
{
|
||||
unsigned int ndiv_int;
|
||||
unsigned int ndiv_frac_low, ndiv_frac_high;
|
||||
unsigned long ihostx_config_root;
|
||||
|
||||
ndiv_frac_low = 0x0;
|
||||
ndiv_frac_high = 0x0;
|
||||
|
||||
if (ihost_pll_freq_sel == ARM_FREQ_3G) {
|
||||
ndiv_int = 0x78;
|
||||
} else if (ihost_pll_freq_sel == ARM_FREQ_1P5G) {
|
||||
ndiv_int = 0x3c;
|
||||
} else if (ihost_pll_freq_sel == ARM_FREQ_750M) {
|
||||
ndiv_int = 0x1e;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
ndiv_int &= 0x3FF; // low 10 bits
|
||||
ndiv_frac_low &= 0x3FF;
|
||||
ndiv_frac_high &= 0x3FF;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
|
||||
mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL1, ndiv_frac_low);
|
||||
mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL2, ndiv_frac_high);
|
||||
mmio_write_32(ihostx_config_root+A72_CRM_PLL0_CTRL3,
|
||||
ndiv_int |
|
||||
((pdiv << A72_CRM_PLL0_CTRL3__PLL0_PDIV_R & 0xF000)));
|
||||
|
||||
mmio_write_32(ihostx_config_root + A72_CRM_PLL0_CTRL4,
|
||||
/* From Section 10 of PLL spec */
|
||||
(3 << A72_CRM_PLL0_CTRL4__PLL0_KP_R) |
|
||||
/* From Section 10 of PLL spec */
|
||||
(2 << A72_CRM_PLL0_CTRL4__PLL0_KI_R) |
|
||||
/* Normal mode (i.e. not fast-locking) */
|
||||
(0 << A72_CRM_PLL0_CTRL4__PLL0_KA_R) |
|
||||
/* 50 MHz */
|
||||
(50 << A72_CRM_PLL0_CTRL4__PLL0_FREFEFF_INFO_R));
|
||||
}
|
||||
|
||||
static void ARMCOE_crm_pllDeassertReset(unsigned int cluster_num,
|
||||
unsigned int reset_type)
|
||||
{
|
||||
unsigned long ihostx_config_root;
|
||||
unsigned int pll_rst_ctrl;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
pll_rst_ctrl = mmio_read_32(ihostx_config_root + A72_CRM_PLL_PWR_ON);
|
||||
|
||||
// PLL reset
|
||||
if (reset_type & PLL_RESET_TYPE_PLL) {
|
||||
pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_RESETB_R);
|
||||
}
|
||||
|
||||
// post-div channel reset
|
||||
if (reset_type & PLL_RESET_TYPE_POST) {
|
||||
pll_rst_ctrl |= (0x1 << A72_CRM_PLL_PWR_ON__PLL0_POST_RESETB_R);
|
||||
}
|
||||
|
||||
mmio_write_32(ihostx_config_root + A72_CRM_PLL_PWR_ON, pll_rst_ctrl);
|
||||
}
|
||||
|
||||
static void ARMCOE_crm_pllUpdate(unsigned int cluster_num, unsigned int type)
|
||||
{
|
||||
unsigned long ihostx_config_root;
|
||||
unsigned int pll_cmd;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
pll_cmd = mmio_read_32(ihostx_config_root + A72_CRM_PLL_CMD);
|
||||
|
||||
// VCO update
|
||||
if (type & PLL_VCO) {
|
||||
pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_VCO_R);
|
||||
}
|
||||
// post-div channel update
|
||||
if (type & PLL_POSTDIV) {
|
||||
pll_cmd |= BIT(A72_CRM_PLL_CMD__UPDATE_PLL0_FREQUENCY_POST_R);
|
||||
}
|
||||
|
||||
mmio_write_32(ihostx_config_root+A72_CRM_PLL_CMD, pll_cmd);
|
||||
}
|
||||
|
||||
static void insert_delay(unsigned int delay)
|
||||
{
|
||||
volatile unsigned int index;
|
||||
|
||||
for (index = 0; index < delay; index++)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns 1 if PLL locked within certain interval
|
||||
*/
|
||||
static unsigned int ARMCOE_crm_pllIsLocked(unsigned int cluster_num)
|
||||
{
|
||||
unsigned long ihostx_config_root;
|
||||
unsigned int lock_status;
|
||||
unsigned int i;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
|
||||
/* wait a while for pll to lock before returning from this function */
|
||||
for (i = 0; i < 1500; i++) {
|
||||
insert_delay(256);
|
||||
lock_status = mmio_read_32(ihostx_config_root +
|
||||
A72_CRM_PLL_STATUS);
|
||||
if (lock_status & BIT(A72_CRM_PLL_STATUS__PLL0_LOCK_R))
|
||||
return 1;
|
||||
}
|
||||
|
||||
ERROR("PLL of Cluster #%u failed to lock\n", cluster_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ihost PLL Variable Frequency Configuration
|
||||
*
|
||||
* Frequency Limit {VCO,ARM} (GHz):
|
||||
* 0 - no limit,
|
||||
* 1 - {3.0,1.5},
|
||||
* 2 - {4.0,2.0},
|
||||
* 3 - {5.0,2.5}
|
||||
*/
|
||||
uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel)
|
||||
{
|
||||
NOTICE("cluster: %u, freq_sel:0x%x\n", cluster_num, ihost_pll_freq_sel);
|
||||
|
||||
//bypass PLL
|
||||
ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_BYPASS);
|
||||
//assert reset
|
||||
ARMCOE_crm_pllAssertReset(cluster_num,
|
||||
PLL_RESET_TYPE_PLL | PLL_RESET_TYPE_POST);
|
||||
//set ndiv_int for different freq
|
||||
ARMCOE_crm_pllFreqSet(cluster_num, ihost_pll_freq_sel, 0x1);
|
||||
//de-assert reset
|
||||
ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_PLL);
|
||||
ARMCOE_crm_pllUpdate(cluster_num, PLL_VCO);
|
||||
//waiting for PLL lock
|
||||
ARMCOE_crm_pllIsLocked(cluster_num);
|
||||
ARMCOE_crm_pllDeassertReset(cluster_num, PLL_RESET_TYPE_POST);
|
||||
//disable bypass PLL
|
||||
ARMCOE_crm_pllSetMode(cluster_num, PLL_MODE_VCO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num)
|
||||
{
|
||||
unsigned long ihostx_config_root;
|
||||
uint32_t ndiv_int;
|
||||
uint32_t ihost_pll_freq_sel;
|
||||
|
||||
ihostx_config_root = ARMCOE_crm_getBaseAddress(cluster_num);
|
||||
ndiv_int = mmio_read_32(ihostx_config_root+A72_CRM_PLL0_CTRL3) & 0x3FF;
|
||||
|
||||
if (ndiv_int == 0x78) {
|
||||
ihost_pll_freq_sel = ARM_FREQ_3G;
|
||||
} else if (ndiv_int == 0x3c) {
|
||||
ihost_pll_freq_sel = ARM_FREQ_1P5G;
|
||||
} else if (ndiv_int == 0x1e) {
|
||||
ihost_pll_freq_sel = ARM_FREQ_750M;
|
||||
} else {
|
||||
/* return unlimit otherwise*/
|
||||
ihost_pll_freq_sel = 0;
|
||||
}
|
||||
return ihost_pll_freq_sel;
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define ICFG_IPROC_IOPAD_CTRL_4 (IPROC_ROOT + 0x9c0)
|
||||
#define ICFG_IPROC_IOPAD_CTRL_5 (IPROC_ROOT + 0x9c4)
|
||||
#define ICFG_IPROC_IOPAD_CTRL_6 (IPROC_ROOT + 0x9c8)
|
||||
#define ICFG_IPROC_IOPAD_CTRL_7 (IPROC_ROOT + 0x9cc)
|
||||
|
||||
#define IOPAD_CTRL4_SDIO0_CD_IND_R 30
|
||||
#define IOPAD_CTRL4_SDIO0_CD_SRC_R 31
|
||||
#define IOPAD_CTRL4_SDIO0_CD_HYS_R 29
|
||||
#define IOPAD_CTRL4_SDIO0_CD_PULL_R 28
|
||||
#define IOPAD_CTRL4_SDIO0_CD_DRIVE_R 24
|
||||
#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R 23
|
||||
#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R 21
|
||||
#define IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R 17
|
||||
|
||||
#define IOPAD_CTRL4_SDIO0_DATA0_SRC_R 15
|
||||
#define IOPAD_CTRL4_SDIO0_DATA0_HYS_R 13
|
||||
#define IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R 9
|
||||
#define IOPAD_CTRL4_SDIO0_DATA1_SRC_R 7
|
||||
#define IOPAD_CTRL4_SDIO0_DATA1_HYS_R 5
|
||||
#define IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R 1
|
||||
|
||||
#define IOPAD_CTRL5_SDIO0_DATA2_SRC_R 31
|
||||
#define IOPAD_CTRL5_SDIO0_DATA2_HYS_R 29
|
||||
#define IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R 25
|
||||
#define IOPAD_CTRL5_SDIO0_DATA3_SRC_R 23
|
||||
#define IOPAD_CTRL5_SDIO0_DATA3_IND_R 22
|
||||
#define IOPAD_CTRL5_SDIO0_DATA3_HYS_R 21
|
||||
#define IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R 17
|
||||
#define IOPAD_CTRL5_SDIO0_DATA4_SRC_R 15
|
||||
#define IOPAD_CTRL5_SDIO0_DATA4_HYS_R 13
|
||||
#define IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R 9
|
||||
#define IOPAD_CTRL5_SDIO0_DATA5_SRC_R 7
|
||||
#define IOPAD_CTRL5_SDIO0_DATA5_HYS_R 5
|
||||
#define IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R 1
|
||||
|
||||
#define IOPAD_CTRL6_SDIO0_DATA6_SRC_R 31
|
||||
#define IOPAD_CTRL6_SDIO0_DATA6_HYS_R 29
|
||||
#define IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R 25
|
||||
#define IOPAD_CTRL6_SDIO0_DATA7_SRC_R 23
|
||||
#define IOPAD_CTRL6_SDIO0_DATA7_HYS_R 21
|
||||
#define IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R 17
|
||||
|
||||
void emmc_soft_reset(void)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
|
||||
val = (BIT(IOPAD_CTRL6_SDIO0_DATA7_SRC_R) |
|
||||
BIT(IOPAD_CTRL6_SDIO0_DATA7_HYS_R) |
|
||||
BIT(IOPAD_CTRL6_SDIO0_DATA7_DRIVE_R) |
|
||||
BIT(IOPAD_CTRL6_SDIO0_DATA6_SRC_R) |
|
||||
BIT(IOPAD_CTRL6_SDIO0_DATA6_HYS_R) |
|
||||
BIT(IOPAD_CTRL6_SDIO0_DATA6_DRIVE_R));
|
||||
|
||||
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
|
||||
|
||||
val = (BIT(IOPAD_CTRL5_SDIO0_DATA3_SRC_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA3_HYS_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA3_DRIVE_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA4_SRC_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA4_HYS_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA4_DRIVE_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA5_SRC_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA5_HYS_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA5_DRIVE_R));
|
||||
|
||||
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_5, val);
|
||||
|
||||
val = (BIT(IOPAD_CTRL4_SDIO0_DATA0_SRC_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_DATA0_HYS_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_DATA0_DRIVE_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_DATA1_SRC_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_DATA1_HYS_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_DATA1_DRIVE_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA2_SRC_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA2_HYS_R) |
|
||||
BIT(IOPAD_CTRL5_SDIO0_DATA2_DRIVE_R));
|
||||
|
||||
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_6, val);
|
||||
|
||||
val = (BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_SRC_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_HYS_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_CLK_SDCARD_DRIVE_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_CD_SRC_R) |
|
||||
BIT(IOPAD_CTRL4_SDIO0_CD_HYS_R));
|
||||
|
||||
/*
|
||||
* set pull-down, clear pull-up=0
|
||||
* bit 12: pull-down bit 11: pull-up
|
||||
* Note: In emulation, this pull-down setting was not
|
||||
* sufficient. Board design likely requires pull down on
|
||||
* this pin for eMMC.
|
||||
*/
|
||||
|
||||
val |= BIT(IOPAD_CTRL4_SDIO0_CD_PULL_R);
|
||||
|
||||
mmio_write_32(ICFG_IPROC_IOPAD_CTRL_4, val);
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2019 - 2021, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SR_USB_H
|
||||
#define SR_USB_H
|
||||
|
||||
#define CDRU_PM_RESET_N_R BIT(CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R)
|
||||
#define CDRU_USBSS_RESET_N BIT(CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N)
|
||||
#define CDRU_MISC_CLK_USBSS \
|
||||
BIT(CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R)
|
||||
|
||||
#define RESCAL_I_RSTB BIT(26)
|
||||
#define RESCAL_I_PWRDNB BIT(27)
|
||||
|
||||
#define DRDU3_U3PHY_CTRL 0x68500014
|
||||
#define PHY_RESET BIT(1)
|
||||
#define POR_RESET BIT(28)
|
||||
#define MDIO_RESET BIT(29)
|
||||
|
||||
#define DRDU3_PWR_CTRL 0x6850002c
|
||||
#define POWER_CTRL_OVRD BIT(2)
|
||||
|
||||
#define USB3H_U3PHY_CTRL 0x68510014
|
||||
#define USB3H_U3SOFT_RST_N BIT(30)
|
||||
|
||||
#define USB3H_PWR_CTRL 0x68510028
|
||||
|
||||
#define USB3_PHY_MDIO_BLOCK_BASE_REG 0x1f
|
||||
#define BDC_AXI_SOFT_RST_N_OFFSET 0
|
||||
#define XHC_AXI_SOFT_RST_N_OFFSET 1
|
||||
#define MDIO_BUS_ID 3
|
||||
#define USB3H_PHY_ID 5
|
||||
#define USB3DRD_PHY_ID 2
|
||||
|
||||
#define USB3_PHY_RXPMD_BLOCK_BASE 0x8020
|
||||
#define USB3_PHY_RXPMD_REG1 0x1
|
||||
#define USB3_PHY_RXPMD_REG2 0x2
|
||||
#define USB3_PHY_RXPMD_REG5 0x5
|
||||
#define USB3_PHY_RXPMD_REG7 0x7
|
||||
|
||||
#define USB3_PHY_TXPMD_BLOCK_BASE 0x8040
|
||||
#define USB3_PHY_TXPMD_REG1 0x1
|
||||
#define USB3_PHY_TXPMD_REG2 0x2
|
||||
|
||||
#define USB3_PHY_ANA_BLOCK_BASE 0x8090
|
||||
#define USB3_PHY_ANA_REG0 0x0
|
||||
#define USB3_PHY_ANA_REG1 0x1
|
||||
#define USB3_PHY_ANA_REG2 0x2
|
||||
#define USB3_PHY_ANA_REG5 0x5
|
||||
#define USB3_PHY_ANA_REG8 0x8
|
||||
#define USB3_PHY_ANA_REG11 0xb
|
||||
|
||||
#define USB3_PHY_AEQ_BLOCK_BASE 0x80e0
|
||||
#define USB3_PHY_AEQ_REG1 0x1
|
||||
#define USB3_PHY_AEQ_REG3 0x3
|
||||
|
||||
#ifdef USB_DMA_COHERENT
|
||||
#define DRDU3_U3XHC_SOFT_RST_N BIT(31)
|
||||
#define DRDU3_U3BDC_SOFT_RST_N BIT(30)
|
||||
|
||||
#define DRDU3_SOFT_RESET_CTRL 0x68500030
|
||||
#define DRDU3_XHC_AXI_SOFT_RST_N BIT(1)
|
||||
#define DRDU3_BDC_AXI_SOFT_RST_N BIT(0)
|
||||
|
||||
#define DRDU2_PHY_CTRL 0x6852000c
|
||||
#define DRDU2_U2SOFT_RST_N BIT(29)
|
||||
|
||||
#define USB3H_SOFT_RESET_CTRL 0x6851002c
|
||||
#define USB3H_XHC_AXI_SOFT_RST_N BIT(1)
|
||||
|
||||
#define DRDU2_SOFT_RESET_CTRL 0x68520020
|
||||
#define DRDU2_BDC_AXI_SOFT_RST_N BIT(0)
|
||||
|
||||
#define DRD2U3H_XHC_REGS_AXIWRA 0x68511c08
|
||||
#define DRD2U3H_XHC_REGS_AXIRDA 0x68511c0c
|
||||
#define DRDU2D_BDC_REGS_AXIWRA 0x68521c08
|
||||
#define DRDU2D_BDC_REGS_AXIRDA 0x68521c0c
|
||||
#define DRDU3H_XHC_REGS_AXIWRA 0x68501c08
|
||||
#define DRDU3H_XHC_REGS_AXIRDA 0x68501c0c
|
||||
#define DRDU3D_BDC_REGS_AXIWRA 0x68502c08
|
||||
#define DRDU3D_BDC_REGS_AXIRDA 0x68502c0c
|
||||
/* cacheable write-back, allocate on both reads and writes */
|
||||
#define USBAXI_AWCACHE 0xf
|
||||
#define USBAXI_ARCACHE 0xf
|
||||
/* non-secure */
|
||||
#define USBAXI_AWPROT 0x8
|
||||
#define USBAXI_ARPROT 0x8
|
||||
#define USBAXIWR_SA_VAL ((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 0)
|
||||
#define USBAXIWR_SA_MASK ((0xf << 4 | 0xf) << 0)
|
||||
#define USBAXIWR_UA_VAL ((USBAXI_AWCACHE << 4 | USBAXI_AWPROT) << 16)
|
||||
#define USBAXIWR_UA_MASK ((0xf << 4 | 0xf) << 0)
|
||||
#define USBAXIRD_SA_VAL ((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 0)
|
||||
#define USBAXIRD_SA_MASK ((0xf << 4 | 0xf) << 0)
|
||||
#define USBAXIRD_UA_VAL ((USBAXI_ARCACHE << 4 | USBAXI_ARPROT) << 16)
|
||||
#define USBAXIRD_UA_MASK ((0xf << 4 | 0xf) << 0)
|
||||
#endif /* USB_DMA_COHERENT */
|
||||
|
||||
#define ICFG_DRDU3_SID_CTRL 0x6850001c
|
||||
#define ICFG_USB3H_SID_CTRL 0x6851001c
|
||||
#define ICFG_DRDU2_SID_CTRL 0x68520010
|
||||
#define ICFG_USB_SID_SHIFT 5
|
||||
#define ICFG_USB_SID_AWADDR_OFFSET 0x0
|
||||
#define ICFG_USB_SID_ARADDR_OFFSET 0x4
|
||||
|
||||
#define USBIC_GPV_BASE 0x68600000
|
||||
#define USBIC_GPV_SECURITY0 (USBIC_GPV_BASE + 0x8)
|
||||
#define USBIC_GPV_SECURITY0_FIELD BIT(0)
|
||||
#define USBIC_GPV_SECURITY1 (USBIC_GPV_BASE + 0xc)
|
||||
#define USBIC_GPV_SECURITY1_FIELD (BIT(0) | BIT(1))
|
||||
#define USBIC_GPV_SECURITY2 (USBIC_GPV_BASE + 0x10)
|
||||
#define USBIC_GPV_SECURITY2_FIELD (BIT(0) | BIT(1))
|
||||
#define USBIC_GPV_SECURITY4 (USBIC_GPV_BASE + 0x18)
|
||||
#define USBIC_GPV_SECURITY4_FIELD BIT(0)
|
||||
#define USBIC_GPV_SECURITY10 (USBIC_GPV_BASE + 0x30)
|
||||
#define USBIC_GPV_SECURITY10_FIELD (0x7 << 0)
|
||||
|
||||
#define USBSS_TZPCDECPROT_BASE 0x68540800
|
||||
#define USBSS_TZPCDECPROT0set (USBSS_TZPCDECPROT_BASE + 0x4)
|
||||
#define USBSS_TZPCDECPROT0clr (USBSS_TZPCDECPROT_BASE + 0x8)
|
||||
#define DECPROT0_USBSS_DRD2U3H BIT(3)
|
||||
#define DECPROT0_USBSS_DRDU2H BIT(2)
|
||||
#define DECPROT0_USBSS_DRDU3D BIT(1)
|
||||
#define DECPROT0_USBSS_DRDU2D BIT(0)
|
||||
#define USBSS_TZPCDECPROT0 \
|
||||
(DECPROT0_USBSS_DRD2U3H | \
|
||||
DECPROT0_USBSS_DRDU2H | \
|
||||
DECPROT0_USBSS_DRDU3D | \
|
||||
DECPROT0_USBSS_DRDU2D)
|
||||
|
||||
int32_t usb_device_init(unsigned int);
|
||||
|
||||
#endif /* SR_USB_H */
|
||||
+375
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <sr_utils.h>
|
||||
#include <swreg.h>
|
||||
|
||||
#define MIN_VOLT 760000
|
||||
#define MAX_VOLT 1060000
|
||||
|
||||
#define BSTI_WRITE 0x1
|
||||
#define BSTI_READ 0x2
|
||||
#define BSTI_COMMAND_TA 0x2
|
||||
#define BSTI_COMMAND_DATA 0xFF
|
||||
#define BSTI_CONTROL_VAL 0x81
|
||||
#define BSTI_CONTROL_BUSY 0x100
|
||||
#define BSTI_TOGGLE_BIT 0x2
|
||||
#define BSTI_CONFI_DONE_MASK 0xFFFFFFFD
|
||||
#define BSTI_REG_DATA_MASK 0xFFFF
|
||||
#define BSTI_CMD(sb, op, pa, ra, ta, data) \
|
||||
((((sb) & 0x3) << 30) | (((op) & 0x3) << 28) | \
|
||||
(((pa) & 0x1F) << 23) | (((ra) & 0x1F) << 18) | \
|
||||
(((ta) & 0x3) << 16) | (data))
|
||||
|
||||
#define PHY_REG0 0x0
|
||||
#define PHY_REG1 0x1
|
||||
#define PHY_REG4 0x4
|
||||
#define PHY_REG5 0x5
|
||||
#define PHY_REG6 0x6
|
||||
#define PHY_REG7 0x7
|
||||
#define PHY_REGC 0xc
|
||||
|
||||
#define IHOST_VDDC_DATA 0x560
|
||||
#define DDR_CORE_DATA 0x2560
|
||||
#define UPDATE_POS_EDGE(data, set) ((data) | ((set) << 1))
|
||||
|
||||
/*
|
||||
* Formula for SR A2 reworked board:
|
||||
* step = ((vol/(1.4117 * 0.98)) - 500000)/3125
|
||||
* where,
|
||||
* vol - input voltage
|
||||
* 500000 - Reference voltage
|
||||
* 3125 - one step value
|
||||
*/
|
||||
#define A2_VOL_REF 500000
|
||||
#define ONE_STEP_VALUE 3125
|
||||
#define VOL_DIV(vol) (((vol*10000ull)/(14117*98ull)) * 100ull)
|
||||
#define STEP_VALUE(vol) \
|
||||
((((((VOL_DIV(vol)) - A2_VOL_REF) / ONE_STEP_VALUE) & 0xFF) << 8) | 4)
|
||||
|
||||
#define B0_VOL_REF ((500000/100)*98)
|
||||
#define B0_ONE_STEP_VALUE 3125
|
||||
/*
|
||||
* Formula for SR B0 chip for IHOST12/03 and VDDC_CORE
|
||||
* step = ((vol/1.56) - (500000 * 0.98))/3125
|
||||
* where,
|
||||
* vol - input voltage
|
||||
* 500000 - Reference voltage
|
||||
* 3125 - one step value
|
||||
*/
|
||||
#define B0_VOL_DIV(vol) (((vol)*100ull)/156)
|
||||
#define B0_STEP_VALUE(vol) \
|
||||
((((((B0_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
|
||||
& 0xFF) << 8) | 4)
|
||||
|
||||
/*
|
||||
* Formula for SR B0 chip for DDR-CORE
|
||||
* step = ((vol/1) - (500000 * 0.98))/3125
|
||||
* where,
|
||||
* vol - input voltage
|
||||
* 500000 - Reference voltage
|
||||
* 3125 - one step value
|
||||
*/
|
||||
#define B0_DDR_VDDC_VOL_DIV(vol) ((vol)/1)
|
||||
#define B0_DDR_VDDC_STEP_VALUE(vol) \
|
||||
((((((B0_DDR_VDDC_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
|
||||
& 0xFF) << 8) | 4)
|
||||
|
||||
#define MAX_SWREG_CNT 8
|
||||
#define MAX_ADDR_PER_SWREG 16
|
||||
#define MAX_REG_ADDR 0xF
|
||||
#define MIN_REG_ADDR 0x0
|
||||
|
||||
static const char *sw_reg_name[MAX_SWREG_CNT] = {
|
||||
"DDR_VDDC",
|
||||
"IHOST03",
|
||||
"IHOST12",
|
||||
"IHOST_ARRAY",
|
||||
"DDRIO_SLAVE",
|
||||
"VDDC_CORE",
|
||||
"VDDC1",
|
||||
"DDRIO_MASTER"
|
||||
};
|
||||
|
||||
/* firmware values for all SWREG for 3.3V input operation */
|
||||
static const uint16_t swreg_fm_data_bx[MAX_SWREG_CNT][MAX_ADDR_PER_SWREG] = {
|
||||
/* DDR logic: Power Domains independent of 12v or 3p3v */
|
||||
{0x25E0, 0x2D54, 0x0EC6, 0x01EC, 0x28BB, 0x1144, 0x0200, 0x69C0,
|
||||
0x0010, 0x0EDF, 0x90D7, 0x8000, 0x820C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* ihost03, 3p3V */
|
||||
{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
|
||||
0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* ihost12 3p3v */
|
||||
{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
|
||||
0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* ihost array */
|
||||
{0x25E0, 0x2D94, 0x0EC6, 0x01EC, 0x2ABB, 0x1144, 0x0340, 0x69C0,
|
||||
0x0010, 0x0EDF, 0x90D7, 0x8000, 0x860C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* ddr io slave : 3p3v */
|
||||
{0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
|
||||
0x003F, 0x0FFF, 0x10D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* core master 3p3v */
|
||||
{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
|
||||
0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* core slave 3p3v */
|
||||
{0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
|
||||
0x003F, 0x0FFF, 0x10D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
|
||||
|
||||
/* ddr io master : 3p3v */
|
||||
{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
|
||||
0x003F, 0x0FFF, 0x90D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
|
||||
};
|
||||
|
||||
#define FM_DATA swreg_fm_data_bx
|
||||
|
||||
static int swreg_poll(void)
|
||||
{
|
||||
uint32_t data;
|
||||
int retry = 100;
|
||||
|
||||
do {
|
||||
data = mmio_read_32(BSTI_CONTROL_OFFSET);
|
||||
if ((data & BSTI_CONTROL_BUSY) != BSTI_CONTROL_BUSY)
|
||||
return 0;
|
||||
retry--;
|
||||
udelay(1);
|
||||
} while (retry > 0);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int write_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t data)
|
||||
{
|
||||
uint32_t cmd;
|
||||
int ret;
|
||||
|
||||
cmd = BSTI_CMD(0x1, BSTI_WRITE, reg_id, addr, BSTI_COMMAND_TA, data);
|
||||
mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
|
||||
mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
|
||||
ret = swreg_poll();
|
||||
if (ret) {
|
||||
ERROR("Failed to write swreg %s addr 0x%x\n",
|
||||
sw_reg_name[reg_id-1], addr);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t *data)
|
||||
{
|
||||
uint32_t cmd;
|
||||
int ret;
|
||||
|
||||
cmd = BSTI_CMD(0x1, BSTI_READ, reg_id, addr, BSTI_COMMAND_TA, PHY_REG0);
|
||||
mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
|
||||
mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
|
||||
ret = swreg_poll();
|
||||
if (ret) {
|
||||
ERROR("Failed to read swreg %s addr 0x%x\n",
|
||||
sw_reg_name[reg_id-1], addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*data = mmio_read_32(BSTI_COMMAND_OFFSET);
|
||||
*data &= BSTI_REG_DATA_MASK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int swreg_config_done(enum sw_reg reg_id)
|
||||
{
|
||||
uint32_t read_data;
|
||||
int ret;
|
||||
|
||||
ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
read_data &= BSTI_CONFI_DONE_MASK;
|
||||
read_data |= BSTI_TOGGLE_BIT;
|
||||
ret = write_swreg_config(reg_id, PHY_REG0, read_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
read_data &= BSTI_CONFI_DONE_MASK;
|
||||
ret = write_swreg_config(reg_id, PHY_REG0, read_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DUMP_SWREG
|
||||
static void dump_swreg_firmware(void)
|
||||
{
|
||||
enum sw_reg reg_id;
|
||||
uint32_t data;
|
||||
int addr;
|
||||
int ret;
|
||||
|
||||
for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
|
||||
INFO("SWREG: %s\n", sw_reg_name[reg_id - 1]);
|
||||
for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
|
||||
ret = read_swreg_config(reg_id, addr, &data);
|
||||
if (ret)
|
||||
ERROR("Failed to read offset %d\n", addr);
|
||||
INFO("\t0x%x: 0x%04x\n", addr, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int set_swreg(enum sw_reg reg_id, uint32_t micro_volts)
|
||||
{
|
||||
uint32_t step, programmed_step;
|
||||
uint32_t data = IHOST_VDDC_DATA;
|
||||
int ret;
|
||||
|
||||
if ((micro_volts > MAX_VOLT) || (micro_volts < MIN_VOLT)) {
|
||||
ERROR("input voltage out-of-range\n");
|
||||
ret = -EINVAL;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = read_swreg_config(reg_id, PHY_REGC, &programmed_step);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
if (reg_id == DDR_VDDC)
|
||||
step = B0_DDR_VDDC_STEP_VALUE(micro_volts);
|
||||
else
|
||||
step = B0_STEP_VALUE(micro_volts);
|
||||
|
||||
if ((step >> 8) != (programmed_step >> 8)) {
|
||||
ret = write_swreg_config(reg_id, PHY_REGC, step);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
if (reg_id == DDR_VDDC)
|
||||
data = DDR_CORE_DATA;
|
||||
|
||||
ret = write_swreg_config(reg_id, PHY_REG0,
|
||||
UPDATE_POS_EDGE(data, 1));
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
ret = write_swreg_config(reg_id, PHY_REG0,
|
||||
UPDATE_POS_EDGE(data, 0));
|
||||
if (ret)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
INFO("%s voltage updated to %duV\n", sw_reg_name[reg_id-1],
|
||||
micro_volts);
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
/*
|
||||
* Stop booting if voltages are not set
|
||||
* correctly. Booting will fail at random point
|
||||
* if we continue with wrong voltage settings.
|
||||
*/
|
||||
ERROR("Failed to set %s voltage to %duV\n", sw_reg_name[reg_id-1],
|
||||
micro_volts);
|
||||
assert(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Update SWREG firmware for all power doman for A2 chip */
|
||||
int swreg_firmware_update(void)
|
||||
{
|
||||
enum sw_reg reg_id;
|
||||
uint32_t data;
|
||||
int addr;
|
||||
int ret;
|
||||
|
||||
/* write firmware values */
|
||||
for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
|
||||
/* write higher location first */
|
||||
for (addr = MAX_REG_ADDR; addr >= MIN_REG_ADDR; addr--) {
|
||||
ret = write_swreg_config(reg_id, addr,
|
||||
FM_DATA[reg_id - 1][addr]);
|
||||
if (ret)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* trigger SWREG firmware update */
|
||||
for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
|
||||
/*
|
||||
* Slave regulator doesn't have to be updated,
|
||||
* Updating Master is enough
|
||||
*/
|
||||
if ((reg_id == DDRIO_SLAVE) || (reg_id == VDDC1))
|
||||
continue;
|
||||
|
||||
ret = swreg_config_done(reg_id);
|
||||
if (ret) {
|
||||
ERROR("Failed to trigger SWREG firmware update for %s\n"
|
||||
, sw_reg_name[reg_id-1]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
|
||||
/*
|
||||
* IHOST_ARRAY will be used on some boards like STRATUS and
|
||||
* there will not be any issue even if it is updated on other
|
||||
* boards where it is not used.
|
||||
*/
|
||||
if (reg_id == IHOST_ARRAY)
|
||||
continue;
|
||||
|
||||
for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
|
||||
ret = read_swreg_config(reg_id, addr, &data);
|
||||
if (ret || (!ret &&
|
||||
(data != FM_DATA[reg_id - 1][addr]))) {
|
||||
ERROR("swreg fm update failed: %s at off %d\n",
|
||||
sw_reg_name[reg_id - 1], addr);
|
||||
ERROR("Read val: 0x%x, expected val: 0x%x\n",
|
||||
data, FM_DATA[reg_id - 1][addr]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Updated SWREG firmware\n");
|
||||
|
||||
#ifdef DUMP_SWREG
|
||||
dump_swreg_firmware();
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Stop booting if swreg firmware update fails.
|
||||
* Booting will fail at random point if we
|
||||
* continue with wrong voltage settings.
|
||||
*/
|
||||
ERROR("Failed to update firmware for %s SWREG\n",
|
||||
sw_reg_name[reg_id-1]);
|
||||
assert(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (c) 2019 - 2021, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mdio.h>
|
||||
#include <platform_usb.h>
|
||||
#include <sr_utils.h>
|
||||
#include "sr_usb.h"
|
||||
#include <usbh_xhci_regs.h>
|
||||
|
||||
static uint32_t usb_func = USB3_DRD | USB3H_USB2DRD;
|
||||
|
||||
static void usb_pm_rescal_init(void)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t try;
|
||||
|
||||
mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PM_RESET_N_R);
|
||||
/* release reset */
|
||||
mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0, RESCAL_I_RSTB);
|
||||
udelay(10U);
|
||||
/* power up */
|
||||
mmio_setbits_32(CDRU_CHIP_TOP_SPARE_REG0,
|
||||
RESCAL_I_RSTB | RESCAL_I_PWRDNB);
|
||||
try = 1000U;
|
||||
do {
|
||||
udelay(1U);
|
||||
data = mmio_read_32(CDRU_CHIP_TOP_SPARE_REG1);
|
||||
try--;
|
||||
} while ((data & RESCAL_I_PWRDNB) == 0x0U && (try != 0U));
|
||||
|
||||
if (try == 0U) {
|
||||
ERROR("CDRU_CHIP_TOP_SPARE_REG1: 0x%x\n", data);
|
||||
}
|
||||
|
||||
INFO("USB and PM Rescal Init done..\n");
|
||||
}
|
||||
|
||||
const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS] = {
|
||||
XHC_PORTSC1_OFFSET,
|
||||
XHC_PORTSC2_OFFSET,
|
||||
XHC_PORTSC3_OFFSET,
|
||||
};
|
||||
|
||||
static void usb3h_usb2drd_init(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
INFO("USB3H + USB 2DRD init\n");
|
||||
mmio_clrbits_32(USB3H_U3PHY_CTRL, POR_RESET);
|
||||
val = mmio_read_32(USB3H_PWR_CTRL);
|
||||
val &= ~(0x3U << POWER_CTRL_OVRD);
|
||||
val |= (1U << POWER_CTRL_OVRD);
|
||||
mmio_write_32(USB3H_PWR_CTRL, val);
|
||||
mmio_setbits_32(USB3H_U3PHY_CTRL, PHY_RESET);
|
||||
/* Phy to come out of reset */
|
||||
udelay(2U);
|
||||
mmio_clrbits_32(USB3H_U3PHY_CTRL, MDIO_RESET);
|
||||
|
||||
/* MDIO in reset */
|
||||
udelay(2U);
|
||||
mmio_setbits_32(USB3H_U3PHY_CTRL, MDIO_RESET);
|
||||
|
||||
/* After MDIO reset release */
|
||||
udelay(2U);
|
||||
|
||||
/* USB 3.0 phy Analog Block Initialization */
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_ANA_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU);
|
||||
|
||||
/* USB 3.0 phy RXPMD Block initialization*/
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_RXPMD_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U);
|
||||
|
||||
/* USB 3.0 phy AEQ Block initialization*/
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_AEQ_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U);
|
||||
|
||||
/* USB 3.0 phy TXPMD Block initialization*/
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_TXPMD_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU);
|
||||
mdio_write(MDIO_BUS_ID, USB3H_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU);
|
||||
}
|
||||
|
||||
static void usb3drd_init(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
INFO("USB3DRD init\n");
|
||||
mmio_clrbits_32(DRDU3_U3PHY_CTRL, POR_RESET);
|
||||
val = mmio_read_32(DRDU3_PWR_CTRL);
|
||||
val &= ~(0x3U << POWER_CTRL_OVRD);
|
||||
val |= (1U << POWER_CTRL_OVRD);
|
||||
mmio_write_32(DRDU3_PWR_CTRL, val);
|
||||
mmio_setbits_32(DRDU3_U3PHY_CTRL, PHY_RESET);
|
||||
/* Phy to come out of reset */
|
||||
udelay(2U);
|
||||
mmio_clrbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET);
|
||||
|
||||
/* MDIO in reset */
|
||||
udelay(2U);
|
||||
mmio_setbits_32(DRDU3_U3PHY_CTRL, MDIO_RESET);
|
||||
|
||||
/* After MDIO reset release */
|
||||
udelay(2U);
|
||||
|
||||
/* USB 3.0 DRD phy Analog Block Initialization */
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_ANA_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG0, 0x4646U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG1, 0x80c9U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG2, 0x88a6U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG5, 0x7c12U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG8, 0x1d07U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_ANA_REG11, 0x25cU);
|
||||
|
||||
/* USB 3.0 DRD phy RXPMD Block initialization*/
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_RXPMD_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG1, 0x4052U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG2, 0x4cU);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG5, 0x7U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_RXPMD_REG7, 0x173U);
|
||||
|
||||
/* USB 3.0 DRD phy AEQ Block initialization*/
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_AEQ_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG1, 0x3000U);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_AEQ_REG3, 0x2c70U);
|
||||
|
||||
/* USB 3.0 DRD phy TXPMD Block initialization*/
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_MDIO_BLOCK_BASE_REG,
|
||||
USB3_PHY_TXPMD_BLOCK_BASE);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG1, 0x100fU);
|
||||
mdio_write(MDIO_BUS_ID, USB3DRD_PHY_ID, USB3_PHY_TXPMD_REG2, 0x238cU);
|
||||
}
|
||||
|
||||
static void usb3_phy_init(void)
|
||||
{
|
||||
usb_pm_rescal_init();
|
||||
|
||||
if ((usb_func & USB3H_USB2DRD) != 0U) {
|
||||
usb3h_usb2drd_init();
|
||||
}
|
||||
|
||||
if ((usb_func & USB3_DRD) != 0U) {
|
||||
usb3drd_init();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USB_DMA_COHERENT
|
||||
void usb_enable_coherence(void)
|
||||
{
|
||||
if (usb_func & USB3H_USB2DRD) {
|
||||
mmio_setbits_32(USB3H_SOFT_RESET_CTRL,
|
||||
USB3H_XHC_AXI_SOFT_RST_N);
|
||||
mmio_setbits_32(DRDU2_SOFT_RESET_CTRL,
|
||||
DRDU2_BDC_AXI_SOFT_RST_N);
|
||||
mmio_setbits_32(USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
|
||||
mmio_setbits_32(DRDU2_PHY_CTRL, DRDU2_U2SOFT_RST_N);
|
||||
|
||||
mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIWRA,
|
||||
(USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
|
||||
(USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
|
||||
|
||||
mmio_clrsetbits_32(DRD2U3H_XHC_REGS_AXIRDA,
|
||||
(USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
|
||||
(USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
|
||||
|
||||
mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIWRA,
|
||||
(USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
|
||||
(USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
|
||||
|
||||
mmio_clrsetbits_32(DRDU2D_BDC_REGS_AXIRDA,
|
||||
(USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
|
||||
(USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
|
||||
|
||||
}
|
||||
|
||||
if (usb_func & USB3_DRD) {
|
||||
mmio_setbits_32(DRDU3_SOFT_RESET_CTRL,
|
||||
(DRDU3_XHC_AXI_SOFT_RST_N |
|
||||
DRDU3_BDC_AXI_SOFT_RST_N));
|
||||
mmio_setbits_32(DRDU3_U3PHY_CTRL,
|
||||
(DRDU3_U3XHC_SOFT_RST_N |
|
||||
DRDU3_U3BDC_SOFT_RST_N));
|
||||
|
||||
mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIWRA,
|
||||
(USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
|
||||
(USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
|
||||
|
||||
mmio_clrsetbits_32(DRDU3H_XHC_REGS_AXIRDA,
|
||||
(USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
|
||||
(USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
|
||||
|
||||
mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIWRA,
|
||||
(USBAXIWR_UA_MASK | USBAXIWR_SA_MASK),
|
||||
(USBAXIWR_UA_VAL | USBAXIWR_SA_VAL));
|
||||
|
||||
mmio_clrsetbits_32(DRDU3D_BDC_REGS_AXIRDA,
|
||||
(USBAXIRD_UA_MASK | USBAXIRD_SA_MASK),
|
||||
(USBAXIRD_UA_VAL | USBAXIRD_SA_VAL));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void xhci_phy_init(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
INFO("usb init start\n");
|
||||
mmio_setbits_32(CDRU_MISC_CLK_ENABLE_CONTROL,
|
||||
CDRU_MISC_CLK_USBSS);
|
||||
|
||||
mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_USBSS_RESET_N);
|
||||
|
||||
if (usb_func & USB3_DRD) {
|
||||
VERBOSE(" - configure stream_id = 0x6800 for DRDU3\n");
|
||||
val = SR_SID_VAL(0x3U, 0x1U, 0x0U) << ICFG_USB_SID_SHIFT;
|
||||
mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
|
||||
val);
|
||||
mmio_write_32(ICFG_DRDU3_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
|
||||
val);
|
||||
|
||||
/*
|
||||
* DRDU3 Device USB Space, DRDU3 Host USB Space,
|
||||
* DRDU3 SS Config
|
||||
*/
|
||||
mmio_setbits_32(USBIC_GPV_SECURITY10,
|
||||
USBIC_GPV_SECURITY10_FIELD);
|
||||
}
|
||||
|
||||
if (usb_func & USB3H_USB2DRD) {
|
||||
VERBOSE(" - configure stream_id = 0x6801 for USB3H\n");
|
||||
val = SR_SID_VAL(0x3U, 0x1U, 0x1U) << ICFG_USB_SID_SHIFT;
|
||||
mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
|
||||
val);
|
||||
mmio_write_32(ICFG_USB3H_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
|
||||
val);
|
||||
|
||||
VERBOSE(" - configure stream_id = 0x6802 for DRDU2\n");
|
||||
val = SR_SID_VAL(0x3U, 0x1U, 0x2U) << ICFG_USB_SID_SHIFT;
|
||||
mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_AWADDR_OFFSET,
|
||||
val);
|
||||
mmio_write_32(ICFG_DRDU2_SID_CTRL + ICFG_USB_SID_ARADDR_OFFSET,
|
||||
val);
|
||||
|
||||
/* DRDU2 APB Bridge:DRDU2 USB Device, USB3H SS Config */
|
||||
mmio_setbits_32(USBIC_GPV_SECURITY1, USBIC_GPV_SECURITY1_FIELD);
|
||||
|
||||
/*
|
||||
* USB3H APB Bridge:DRDU2 Host + USB3 Host USB Space,
|
||||
* USB3H SS Config
|
||||
*/
|
||||
mmio_setbits_32(USBIC_GPV_SECURITY2, USBIC_GPV_SECURITY2_FIELD);
|
||||
}
|
||||
|
||||
/* Configure Host masters as non-Secure */
|
||||
mmio_setbits_32(USBSS_TZPCDECPROT0set, USBSS_TZPCDECPROT0);
|
||||
|
||||
/* CCN Slave on USBIC */
|
||||
mmio_setbits_32(USBIC_GPV_SECURITY0, USBIC_GPV_SECURITY0_FIELD);
|
||||
|
||||
/* SLAVE_8:IDM Register Space */
|
||||
mmio_setbits_32(USBIC_GPV_SECURITY4, USBIC_GPV_SECURITY4_FIELD);
|
||||
|
||||
usb3_phy_init();
|
||||
#ifdef USB_DMA_COHERENT
|
||||
usb_enable_coherence();
|
||||
#endif
|
||||
|
||||
usb_device_init(usb_func);
|
||||
|
||||
INFO("PLAT USB: init done.\n");
|
||||
}
|
||||
+601
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* Copyright (c) 2019 - 2021, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_usb.h>
|
||||
#include <usb_phy.h>
|
||||
|
||||
#define USB_PHY_ALREADY_STARTED (-2)
|
||||
#define USB_MAX_DEVICES 2
|
||||
#define USB3H_USB2DRD_PHY 0
|
||||
#define USB3_DRD_PHY 1
|
||||
|
||||
/* Common bit fields for all the USB2 phy */
|
||||
#define USB2_PHY_ISO DRDU2_U2PHY_ISO
|
||||
#define USB2_AFE_PLL_PWRDWNB DRDU2_U2AFE_PLL_PWRDWNB
|
||||
#define USB2_AFE_BG_PWRDWNB DRDU2_U2AFE_BG_PWRDWNB
|
||||
#define USB2_AFE_LDO_PWRDWNB DRDU2_U2AFE_LDO_PWRDWNB
|
||||
#define USB2_CTRL_CORERDY DRDU2_U2CTRL_CORERDY
|
||||
|
||||
#define USB2_PHY_PCTL_MASK DRDU2_U2PHY_PCTL_MASK
|
||||
#define USB2_PHY_PCTL_OFFSET DRDU2_U2PHY_PCTL_OFFSET
|
||||
#define USB2_PHY_PCTL_VAL U2PHY_PCTL_VAL
|
||||
|
||||
#define USB2_PLL_RESETB DRDU2_U2PLL_RESETB
|
||||
#define USB2_PHY_RESETB DRDU2_U2PHY_RESETB
|
||||
|
||||
static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS];
|
||||
|
||||
static usb_phy_t usb_phy_info[2U] = {
|
||||
{DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY},
|
||||
{0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *pcd_id;
|
||||
} usb_platform_dev;
|
||||
|
||||
/* index 0: USB3H + USB2 DRD, 1: USB3 DRD */
|
||||
static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = {
|
||||
{&usb_phy_info[0U]},
|
||||
{&usb_phy_info[1U]}
|
||||
};
|
||||
|
||||
static int32_t pll_lock_check(uint32_t address, uint32_t bit)
|
||||
{
|
||||
uint32_t retry;
|
||||
uint32_t data;
|
||||
|
||||
retry = PLL_LOCK_RETRY_COUNT;
|
||||
do {
|
||||
data = mmio_read_32(address);
|
||||
if ((data & bit) != 0U) {
|
||||
return 0;
|
||||
}
|
||||
udelay(1);
|
||||
} while (--retry != 0);
|
||||
|
||||
ERROR("%s(): FAIL (0x%08x)\n", __func__, address);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* USB2 PHY using external FSM bringup sequence
|
||||
* Total #3 USB2 phys. All phys has the same
|
||||
* bringup sequence. Register bit fields for
|
||||
* some of the PHY's are different.
|
||||
* Bit fields which are different are passed using
|
||||
* struct u2_phy_ext_fsm with bit-fields and register addr.
|
||||
*/
|
||||
|
||||
static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy)
|
||||
{
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
|
||||
mmio_clrbits_32(u2_phy->phy_ctrl_reg,
|
||||
(USB2_AFE_BG_PWRDWNB |
|
||||
USB2_AFE_PLL_PWRDWNB |
|
||||
USB2_AFE_LDO_PWRDWNB |
|
||||
USB2_CTRL_CORERDY));
|
||||
|
||||
mmio_clrsetbits_32(u2_phy->phy_ctrl_reg,
|
||||
(USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET),
|
||||
(USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET));
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(160U);
|
||||
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(50U);
|
||||
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(200U);
|
||||
|
||||
mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin);
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
|
||||
mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
|
||||
mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(1U);
|
||||
|
||||
mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB);
|
||||
mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB);
|
||||
|
||||
}
|
||||
|
||||
static int32_t usb3h_u2_phy_power_on(uint32_t base)
|
||||
{
|
||||
int32_t status;
|
||||
struct u2_phy_ext_fsm u2_phy;
|
||||
|
||||
u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL;
|
||||
u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL;
|
||||
u2_phy.phy_iddq = USB3H_U2PHY_IDDQ;
|
||||
u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL;
|
||||
u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN;
|
||||
u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN;
|
||||
|
||||
u2_phy_ext_fsm_power_on(&u2_phy);
|
||||
|
||||
status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK);
|
||||
if (status != 0) {
|
||||
/* re-try by toggling the PLL reset */
|
||||
mmio_clrbits_32(base + USB3H_U2PLL_CTRL,
|
||||
(uint32_t)USB3H_U2PLL_RESETB);
|
||||
mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB);
|
||||
status = pll_lock_check(base + USB3H_U2PLL_CTRL,
|
||||
USB3H_U2PLL_LOCK);
|
||||
if (status != 0)
|
||||
ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
|
||||
base + USB3H_U2PLL_CTRL);
|
||||
}
|
||||
|
||||
mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL,
|
||||
(USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET),
|
||||
(U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET));
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t usb3h_u3_phy_power_on(uint32_t base)
|
||||
{
|
||||
int32_t status;
|
||||
|
||||
/* Set pctl with mode and soft reset */
|
||||
mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL,
|
||||
(USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET),
|
||||
(U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET));
|
||||
|
||||
mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL,
|
||||
(uint32_t) USB3H_U3SSPLL_SUSPEND_EN);
|
||||
mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START);
|
||||
mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB);
|
||||
|
||||
/* Time to stabilize the PLL Control */
|
||||
mdelay(1U);
|
||||
|
||||
status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL,
|
||||
USB3H_U3PLL_SS_LOCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t drdu3_u2_phy_power_on(uint32_t base)
|
||||
{
|
||||
int32_t status;
|
||||
struct u2_phy_ext_fsm u2_phy;
|
||||
|
||||
u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL;
|
||||
u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL;
|
||||
u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ;
|
||||
u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL;
|
||||
u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN;
|
||||
u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN;
|
||||
|
||||
u2_phy_ext_fsm_power_on(&u2_phy);
|
||||
|
||||
status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK);
|
||||
if (status != 0) {
|
||||
/* re-try by toggling the PLL reset */
|
||||
mmio_clrbits_32(base + DRDU3_U2PLL_CTRL,
|
||||
(uint32_t)DRDU2_U2PLL_RESETB);
|
||||
mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB);
|
||||
|
||||
status = pll_lock_check(base + DRDU3_U2PLL_CTRL,
|
||||
DRDU3_U2PLL_LOCK);
|
||||
if (status != 0) {
|
||||
ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
|
||||
base + DRDU3_U2PLL_CTRL);
|
||||
}
|
||||
}
|
||||
mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL,
|
||||
(DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET),
|
||||
(U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t drdu3_u3_phy_power_on(uint32_t base)
|
||||
{
|
||||
int32_t status;
|
||||
|
||||
/* Set pctl with mode and soft reset */
|
||||
mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL,
|
||||
(DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET),
|
||||
(U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET));
|
||||
|
||||
mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL,
|
||||
(uint32_t) DRDU3_U3SSPLL_SUSPEND_EN);
|
||||
mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START);
|
||||
mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB);
|
||||
|
||||
/* Time to stabilize the PLL Control */
|
||||
mdelay(1U);
|
||||
|
||||
status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL,
|
||||
DRDU3_U3PLL_SS_LOCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t drdu2_u2_phy_power_on(uint32_t base)
|
||||
{
|
||||
int32_t status;
|
||||
struct u2_phy_ext_fsm u2_phy;
|
||||
|
||||
u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL;
|
||||
u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL;
|
||||
u2_phy.phy_iddq = DRDU2_U2IDDQ;
|
||||
u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL;
|
||||
u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I;
|
||||
u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I;
|
||||
|
||||
u2_phy_ext_fsm_power_on(&u2_phy);
|
||||
|
||||
status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK);
|
||||
if (status != 0) {
|
||||
/* re-try by toggling the PLL reset */
|
||||
mmio_clrbits_32(base + DRDU2_U2PLL_CTRL,
|
||||
(uint32_t)DRDU2_U2PLL_RESETB);
|
||||
mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB);
|
||||
|
||||
status = pll_lock_check(base + DRDU2_U2PLL_CTRL,
|
||||
DRDU2_U2PLL_LOCK);
|
||||
if (status != 0)
|
||||
ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__,
|
||||
base + DRDU2_U2PLL_CTRL);
|
||||
}
|
||||
mmio_clrsetbits_32(base + DRDU2_PHY_CTRL,
|
||||
(DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET),
|
||||
(U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port)
|
||||
{
|
||||
usb_phy_t *phy = phy_port->p;
|
||||
|
||||
switch (phy_port->port_id) {
|
||||
case USB3HS_PORT:
|
||||
mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
|
||||
(uint32_t) USB3H_U2CTRL_CORERDY);
|
||||
mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL,
|
||||
USB3H_U2CTRL_CORERDY);
|
||||
break;
|
||||
case DRDU2_PORT:
|
||||
mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
|
||||
(uint32_t) DRDU2_U2CTRL_CORERDY);
|
||||
mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
|
||||
DRDU2_U2CTRL_CORERDY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void u3drd_phy_reset(usb_phy_port_t *phy_port)
|
||||
{
|
||||
usb_phy_t *phy = phy_port->p;
|
||||
|
||||
if (phy_port->port_id == DRD3HS_PORT) {
|
||||
mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
|
||||
(uint32_t) DRDU3_U2CTRL_CORERDY);
|
||||
mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL,
|
||||
DRDU3_U2CTRL_CORERDY);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port)
|
||||
{
|
||||
usb_phy_t *phy = phy_port->p;
|
||||
int32_t status;
|
||||
|
||||
switch (phy_port->port_id) {
|
||||
case USB3SS_PORT:
|
||||
mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
(uint32_t) USB3H_DISABLE_USB30_P0);
|
||||
status = usb3h_u3_phy_power_on(phy->usb3hreg);
|
||||
if (status != 0) {
|
||||
goto err_usb3h_phy_on;
|
||||
}
|
||||
break;
|
||||
case USB3HS_PORT:
|
||||
mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
(uint32_t) USB3H_DISABLE_EUSB_P1);
|
||||
mmio_setbits_32(AXI_DEBUG_CTRL,
|
||||
AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
|
||||
mmio_setbits_32(USB3H_DEBUG_CTRL,
|
||||
USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
|
||||
|
||||
mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
|
||||
USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL,
|
||||
USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN);
|
||||
status = usb3h_u2_phy_power_on(phy->usb3hreg);
|
||||
if (status != 0) {
|
||||
goto err_usb3h_phy_on;
|
||||
}
|
||||
break;
|
||||
case DRDU2_PORT:
|
||||
mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
(uint32_t) USB3H_DISABLE_EUSB_P0);
|
||||
mmio_setbits_32(AXI_DEBUG_CTRL,
|
||||
AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
|
||||
mmio_setbits_32(USB3H_DEBUG_CTRL,
|
||||
USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
|
||||
|
||||
mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
|
||||
DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL,
|
||||
DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I);
|
||||
|
||||
status = drdu2_u2_phy_power_on(phy->drdu2reg);
|
||||
if (status != 0) {
|
||||
mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
USB3H_DISABLE_EUSB_P0);
|
||||
goto err_drdu2_phy_on;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Device Mode */
|
||||
if (phy_port->port_id == DRDU2_PORT) {
|
||||
mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL,
|
||||
DRDU2_BDC_AXI_SOFT_RST_N);
|
||||
mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL,
|
||||
DRDU2_U2SOFT_RST_N);
|
||||
}
|
||||
/* Host Mode */
|
||||
mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL,
|
||||
USB3H_XHC_AXI_SOFT_RST_N);
|
||||
mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N);
|
||||
|
||||
return 0U;
|
||||
err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
(USB3H_DISABLE_EUSB_P1 |
|
||||
USB3H_DISABLE_USB30_P0));
|
||||
err_drdu2_phy_on:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port)
|
||||
{
|
||||
usb_phy_t *phy = phy_port->p;
|
||||
int32_t status;
|
||||
|
||||
switch (phy_port->port_id) {
|
||||
case DRD3SS_PORT:
|
||||
mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
|
||||
(uint32_t) DRDU3_DISABLE_USB30_P0);
|
||||
|
||||
status = drdu3_u3_phy_power_on(phy->drdu3reg);
|
||||
if (status != 0) {
|
||||
goto err_drdu3_phy_on;
|
||||
}
|
||||
break;
|
||||
case DRD3HS_PORT:
|
||||
mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
|
||||
(uint32_t) DRDU3_DISABLE_EUSB_P0);
|
||||
mmio_setbits_32(AXI_DEBUG_CTRL,
|
||||
AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
|
||||
mmio_setbits_32(USB3H_DEBUG_CTRL,
|
||||
USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE);
|
||||
|
||||
mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
|
||||
DRDU3_U2PHY_DFE_SWITCH_PWRONIN);
|
||||
/* Delay as per external FSM spec */
|
||||
udelay(10U);
|
||||
mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL,
|
||||
DRDU3_U2PHY_DFE_SWITCH_PWROKIN);
|
||||
|
||||
status = drdu3_u2_phy_power_on(phy->drdu3reg);
|
||||
if (status != 0) {
|
||||
goto err_drdu3_phy_on;
|
||||
}
|
||||
|
||||
/* Host Mode */
|
||||
mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
|
||||
DRDU3_XHC_AXI_SOFT_RST_N);
|
||||
mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
|
||||
DRDU3_U3XHC_SOFT_RST_N);
|
||||
/* Device Mode */
|
||||
mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL,
|
||||
DRDU3_BDC_AXI_SOFT_RST_N);
|
||||
mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL,
|
||||
DRDU3_U3BDC_SOFT_RST_N);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0U;
|
||||
err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL,
|
||||
(DRDU3_DISABLE_EUSB_P0 |
|
||||
DRDU3_DISABLE_USB30_P0));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port)
|
||||
{
|
||||
usb_phy_t *p = phy_port->p;
|
||||
|
||||
switch (phy_port->port_id) {
|
||||
case USB3SS_PORT:
|
||||
mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
USB3H_DISABLE_USB30_P0);
|
||||
break;
|
||||
case USB3HS_PORT:
|
||||
mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
USB3H_DISABLE_EUSB_P1);
|
||||
break;
|
||||
case DRDU2_PORT:
|
||||
mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL,
|
||||
USB3H_DISABLE_EUSB_P0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void u3drd_phy_power_off(usb_phy_port_t *phy_port)
|
||||
{
|
||||
usb_phy_t *p = phy_port->p;
|
||||
|
||||
switch (phy_port->port_id) {
|
||||
case DRD3SS_PORT:
|
||||
mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
|
||||
DRDU3_DISABLE_USB30_P0);
|
||||
break;
|
||||
case DRD3HS_PORT:
|
||||
mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL,
|
||||
DRDU3_DISABLE_EUSB_P0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t usb_info_fill(usb_phy_t *phy_info)
|
||||
{
|
||||
int32_t index;
|
||||
|
||||
if (phy_info->initialized != 0U) {
|
||||
return USB_PHY_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
if (phy_info->phy_id == USB3H_DRDU2_PHY) {
|
||||
phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U];
|
||||
phy_info->ports_enabled = 0x7U;
|
||||
} else {
|
||||
phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U];
|
||||
phy_info->ports_enabled = 0x3U;
|
||||
}
|
||||
|
||||
for (index = MAX_NR_PORTS - 1U; index > -1; index--) {
|
||||
phy_info->phy_port[index].enabled = (phy_info->ports_enabled
|
||||
>> index) & 0x1U;
|
||||
phy_info->phy_port[index].p = phy_info;
|
||||
phy_info->phy_port[index].port_id = index;
|
||||
}
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
int32_t usb_phy_init(usb_platform_dev *device)
|
||||
{
|
||||
int32_t status;
|
||||
usb_phy_t *phy_info;
|
||||
uint32_t index;
|
||||
|
||||
phy_info = (usb_phy_t *)device->pcd_id;
|
||||
|
||||
status = usb_info_fill(phy_info);
|
||||
if (status != 0) {
|
||||
return (status == USB_PHY_ALREADY_STARTED) ? 0 : status;
|
||||
}
|
||||
|
||||
for (index = 0U; index < MAX_NR_PORTS; index++) {
|
||||
if (phy_info->phy_port[index].enabled != 0U) {
|
||||
switch (phy_info->phy_id) {
|
||||
case USB3H_DRDU2_PHY:
|
||||
status =
|
||||
u3h_u2drd_phy_power_on(&phy_info->
|
||||
phy_port[index]);
|
||||
break;
|
||||
default:
|
||||
status =
|
||||
u3drd_phy_power_on(&phy_info->
|
||||
phy_port[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
phy_info->initialized = !status;
|
||||
return status;
|
||||
}
|
||||
|
||||
void usb_phy_shutdown(usb_platform_dev *device)
|
||||
{
|
||||
usb_phy_t *phy_info;
|
||||
uint32_t index;
|
||||
|
||||
phy_info = (usb_phy_t *)device->pcd_id;
|
||||
|
||||
phy_info->initialized = 0U;
|
||||
|
||||
for (index = 0U; index < MAX_NR_PORTS; index++) {
|
||||
if (phy_info->phy_port[index].enabled != 0U) {
|
||||
switch (phy_info->phy_id) {
|
||||
case USB3H_DRDU2_PHY:
|
||||
u3h_u2drd_phy_power_off(&phy_info->
|
||||
phy_port[index]);
|
||||
break;
|
||||
case DRDU3_PHY:
|
||||
u3drd_phy_power_off(&phy_info->phy_port[index]);
|
||||
break;
|
||||
default:
|
||||
INFO("%s: invalid phy id 0x%x\n", __func__,
|
||||
phy_info->phy_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t usb_xhci_init(usb_platform_dev *device)
|
||||
{
|
||||
int32_t status;
|
||||
|
||||
status = usb_phy_init(device);
|
||||
if (status == USB_PHY_ALREADY_STARTED) {
|
||||
status = 0U;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int32_t usb_device_init(unsigned int usb_func)
|
||||
{
|
||||
int32_t status;
|
||||
int32_t devices_initialized = 0U;
|
||||
|
||||
if ((usb_func & USB3H_USB2DRD) != 0U) {
|
||||
status = usb_xhci_init(
|
||||
&xhci_devices_configs[USB3H_USB2DRD_PHY]);
|
||||
if (status == 0) {
|
||||
devices_initialized++;
|
||||
} else {
|
||||
ERROR("%s(): USB3H_USB2DRD init failure\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
if ((usb_func & USB3_DRD) != 0U) {
|
||||
status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]);
|
||||
if (status == 0) {
|
||||
devices_initialized++;
|
||||
} else {
|
||||
ERROR("%s(): USB3_DRD init failure\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
return devices_initialized;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef BL33_INFO_H
|
||||
#define BL33_INFO_H
|
||||
|
||||
/* Increase version number each time this file is modified */
|
||||
#define BL33_INFO_VERSION 4
|
||||
|
||||
struct chip_info {
|
||||
unsigned int chip_id;
|
||||
unsigned int rev_id;
|
||||
};
|
||||
|
||||
struct boot_time_info {
|
||||
unsigned int bl1_start;
|
||||
unsigned int bl1_end;
|
||||
unsigned int bl2_start;
|
||||
unsigned int bl2_end;
|
||||
unsigned int bl31_start;
|
||||
unsigned int bl31_end;
|
||||
unsigned int bl32_start;
|
||||
unsigned int bl32_end;
|
||||
unsigned int bl33_start;
|
||||
unsigned int bl33_prompt;
|
||||
unsigned int bl33_end;
|
||||
};
|
||||
|
||||
struct bl33_info {
|
||||
unsigned int version;
|
||||
struct chip_info chip;
|
||||
struct boot_time_info boot_time_info;
|
||||
};
|
||||
|
||||
#endif
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef BOARD_INFO_H
|
||||
#define BOARD_INFO_H
|
||||
|
||||
#define IHOST_REG_INTEGRATED 0
|
||||
#define IHOST_REG_EXT_PROGRAMMABLE 1
|
||||
#define IHOST_REG_EXT_FIXED 2
|
||||
|
||||
#if defined(IHOST_REG_TYPE)
|
||||
#if ((IHOST_REG_TYPE != IHOST_REG_INTEGRATED) && \
|
||||
(IHOST_REG_TYPE != IHOST_REG_EXT_PROGRAMMABLE) && \
|
||||
(IHOST_REG_TYPE != IHOST_REG_EXT_FIXED))
|
||||
#error "IHOST_REG_TYPE not valid"
|
||||
#endif
|
||||
#else
|
||||
#define IHOST_REG_TYPE IHOST_REG_INTEGRATED
|
||||
#endif
|
||||
|
||||
#define VDDC_REG_INTEGRATED 0
|
||||
#define VDDC_REG_EXT_PROGRAMMABLE 1
|
||||
#define VDDC_REG_EXT_FIXED 2
|
||||
|
||||
#if defined(VDDC_REG_TYPE)
|
||||
#if ((VDDC_REG_TYPE != VDDC_REG_INTEGRATED) && \
|
||||
(VDDC_REG_TYPE != VDDC_REG_EXT_PROGRAMMABLE) && \
|
||||
(VDDC_REG_TYPE != VDDC_REG_EXT_FIXED))
|
||||
#error "VDDC_REG_TYPE not valid"
|
||||
#endif
|
||||
#else
|
||||
#define VDDC_REG_TYPE VDDC_REG_INTEGRATED
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef CRMU_DEF_H
|
||||
#define CRMU_DEF_H
|
||||
|
||||
#define CRMU_REGS_BASE 0x66410000
|
||||
/* 32 kB IDRAM */
|
||||
#define CRMU_IDRAM_BASE_ADDR CRMU_REGS_BASE
|
||||
#define CRMU_IDRAM_SIZE 0x8000
|
||||
/* 4 kB Scratch RAM */
|
||||
#define CRMU_SRAM_BASE (CRMU_IDRAM_BASE_ADDR + CRMU_IDRAM_SIZE)
|
||||
#define CRMU_SRAM_SIZE 0x1000
|
||||
|
||||
#define CRMU_RESERVED_SPACE 0x3000
|
||||
#define CRMU_CORE_BASE (CRMU_SRAM_BASE + CRMU_SRAM_SIZE + \
|
||||
CRMU_RESERVED_SPACE)
|
||||
|
||||
#define CRMU_SHARED_SRAM_BASE CRMU_SRAM_BASE
|
||||
#define CRMU_SHARED_SRAM_SIZE 0x200
|
||||
#define CRMU_CFG_BASE (CRMU_SHARED_SRAM_BASE + \
|
||||
CRMU_SHARED_SRAM_SIZE)
|
||||
|
||||
#define CRMU_PWR_GOOD_STATUS CRMU_CORE_BASE
|
||||
#define CRMU_PWR_GOOD_STATUS__BBL_POWER_GOOD 0
|
||||
#define CRMU_ISO_CELL_CONTROL (CRMU_CORE_BASE + 0x4)
|
||||
#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL 16
|
||||
#define CRMU_ISO_CELL_CONTROL__CRMU_ISO_PDBBL_TAMPER 24
|
||||
#define CRMU_SPRU_SOURCE_SEL_STAT (CRMU_CORE_BASE + 0xc)
|
||||
#define CRMU_SPRU_SOURCE_SEL_STAT__SPRU_SOURCE_SELECT 0
|
||||
#define BSTI_BASE (CRMU_CORE_BASE + 0x28)
|
||||
#define BSTI_CONTROL_OFFSET BSTI_BASE
|
||||
#define BSTI_COMMAND_OFFSET (BSTI_BASE + 0x4)
|
||||
|
||||
#define OCOTP_REGS_BASE (CRMU_CORE_BASE + 0x400)
|
||||
|
||||
#define CRMU_TCI_BASE (CRMU_CORE_BASE + 0x800)
|
||||
#define CRMU_SWREG_STATUS_ADDR (CRMU_TCI_BASE + 0x0c)
|
||||
#define CRMU_CHIP_OTPC_STATUS (CRMU_TCI_BASE + 0x10)
|
||||
#define CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE 19
|
||||
#define CRMU_BISR_PDG_MASK (CRMU_TCI_BASE + 0x4c)
|
||||
#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST0 2
|
||||
#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1 3
|
||||
#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2 4
|
||||
#define CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3 0
|
||||
#define CRMU_POWER_POLL (CRMU_TCI_BASE + 0x60)
|
||||
#define CRMU_OTP_STATUS CRMU_POWER_POLL
|
||||
#define CRMU_OTP_STATUS_BIT 1
|
||||
#define CRMU_DDR_PHY_AON_CTRL (CRMU_TCI_BASE + 0x64)
|
||||
#define CRMU_DDRPHY2_HW_RESETN_R BIT(21)
|
||||
#define CRMU_DDRPHY2_PWROKIN_PHY_R BIT(20)
|
||||
#define CRMU_DDRPHY2_PWRONIN_PHY_R BIT(19)
|
||||
#define CRMU_DDRPHY2_ISO_PHY_DFI_R BIT(18)
|
||||
#define CRMU_DDRPHY2_ISO_PHY_REGS_R BIT(17)
|
||||
#define CRMU_DDRPHY2_ISO_PHY_PLL_R BIT(16)
|
||||
#define CRMU_DDRPHY1_HW_RESETN_R BIT(13)
|
||||
#define CRMU_DDRPHY1_PWROKIN_PHY_R BIT(12)
|
||||
#define CRMU_DDRPHY1_PWRONIN_PHY_R BIT(11)
|
||||
#define CRMU_DDRPHY1_ISO_PHY_DFI_R BIT(10)
|
||||
#define CRMU_DDRPHY1_ISO_PHY_REGS_R BIT(9)
|
||||
#define CRMU_DDRPHY1_ISO_PHY_PLL_R BIT(8)
|
||||
#define CRMU_DDRPHY0_HW_RESETN_R BIT(5)
|
||||
#define CRMU_DDRPHY0_PWROKIN_PHY_R BIT(4)
|
||||
#define CRMU_DDRPHY0_PWRONIN_PHY_R BIT(3)
|
||||
#define CRMU_DDRPHY0_ISO_PHY_DFI_R BIT(2)
|
||||
#define CRMU_DDRPHY0_ISO_PHY_REGS_R BIT(1)
|
||||
#define CRMU_DDRPHY0_ISO_PHY_PLL_R BIT(0)
|
||||
#define CRMU_EMEM_RESET_N_R BIT(16)
|
||||
#define CRMU_EMEM_PRESET_N_R BIT(0)
|
||||
#define CRMU_SWREG_CTRL_ADDR (CRMU_TCI_BASE + 0x6c)
|
||||
#define CRMU_AON_CTRL1 (CRMU_TCI_BASE + 0x70)
|
||||
#define CRMU_AON_CTRL1__LCPLL1_ISO_IN 18
|
||||
#define CRMU_AON_CTRL1__LCPLL1_PWRON_LDO 19
|
||||
#define CRMU_AON_CTRL1__LCPLL1_PWR_ON 20
|
||||
#define CRMU_AON_CTRL1__LCPLL0_ISO_IN 21
|
||||
#define CRMU_AON_CTRL1__LCPLL0_PWRON_LDO 22
|
||||
#define CRMU_AON_CTRL1__LCPLL0_PWR_ON 23
|
||||
#define CRMU_PCIE_LCPLL_PWR_ON_SHIFT 29
|
||||
#define CRMU_PCIE_LCPLL_PWR_ON_MASK BIT(CRMU_PCIE_LCPLL_PWR_ON_SHIFT)
|
||||
#define CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT 28
|
||||
#define CRMU_PCIE_LCPLL_PWRON_LDO_MASK BIT(CRMU_PCIE_LCPLL_PWRON_LDO_SHIFT)
|
||||
#define CRMU_PCIE_LCPLL_ISO_IN_SHIFT 27
|
||||
#define CRMU_PCIE_LCPLL_ISO_IN_MASK BIT(CRMU_PCIE_LCPLL_ISO_IN_SHIFT)
|
||||
#define CRMU_MASTER_AXI_ARUSER_CONFIG (CRMU_TCI_BASE + 0x74)
|
||||
#define CRMU_MASTER_AXI_AWUSER_CONFIG (CRMU_TCI_BASE + 0x78)
|
||||
#define CRMU_DDR_PHY_AON_CTRL_1 (CRMU_TCI_BASE + 0x8c)
|
||||
|
||||
#define CDRU_BASE_ADDR (CRMU_CORE_BASE + 0x1000)
|
||||
#define CDRU_MISC_RESET_CONTROL CDRU_BASE_ADDR
|
||||
#define CDRU_MISC_RESET_CONTROL_TS_RESET_N 16
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_USBSS_RESET_N 14
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_SATA_RESET_N_R 15
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R 13
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R 3
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R 2
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R 1
|
||||
|
||||
#define CDRU_PROC_EVENT_CLEAR (CDRU_BASE_ADDR + 0x48)
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2 0
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI 3
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2 5
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI 8
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2 10
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI 13
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2 15
|
||||
#define CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI 18
|
||||
|
||||
#define CDRU_CHIP_STRAP_CTRL (CDRU_BASE_ADDR + 0x50)
|
||||
#define CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE 31
|
||||
|
||||
#define CDRU_CHIP_IO_PAD_CONTROL (CDRU_BASE_ADDR + 0x58)
|
||||
#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PDN_R 8
|
||||
#define CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R 0
|
||||
|
||||
#define CDRU_CHIP_STRAP_DATA_LSW (CDRU_BASE_ADDR + 0x5c)
|
||||
#define CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE 18
|
||||
#define CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK BIT(8)
|
||||
#define CDRU_CHIP_STRAP_DATA_LSW_PAD_USB_MODE BIT(26)
|
||||
|
||||
#define CDRU_CHIP_STRAP_DATA (CDRU_BASE_ADDR + 0x5c)
|
||||
#define CDRU_DDR0_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xb8)
|
||||
#define CDRU_DDR1_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xbc)
|
||||
#define CDRU_DDR2_CONTROL_OFFSET (CDRU_BASE_ADDR + 0xc0)
|
||||
#define CRMU_SW_POR_RESET_CTRL (CDRU_BASE_ADDR + 0x100)
|
||||
|
||||
#define CDRU_GENPLL2_CONTROL1 (CDRU_BASE_ADDR + 0x1b0)
|
||||
#define CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK BIT(11)
|
||||
#define CDRU_GENPLL5_CONTROL1 (CDRU_BASE_ADDR + 0x24c)
|
||||
#define CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK BIT(6)
|
||||
#define CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK BIT(7)
|
||||
#define CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK BIT(8)
|
||||
|
||||
#define CDRU_NITRO_CONTROL (CDRU_BASE_ADDR + 0x2c4)
|
||||
#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R 20
|
||||
#define CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R 16
|
||||
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL (CDRU_BASE_ADDR + 0x2c8)
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM2_CLK_EN_R 11
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM1_CLK_EN_R 10
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_EMEM0_CLK_EN_R 9
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SATA_CLK_EN_R 8
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_USBSS_CLK_EN_R 7
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_MHB_CLK_EN_R 6
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_HSLS_CLK_EN_R 5
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_SCR_CLK_EN_R 4
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_FS4_CLK_EN_R 3
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PCIE_CLK_EN_R 2
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_PM_CLK_EN_R 1
|
||||
#define CDRU_MISC_CLK_ENABLE_CONTROL__CDRU_NITRO_CLK_EN_R 0
|
||||
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1 (CDRU_BASE_ADDR + 0x324)
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM0_BIT 6
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM1_BIT 5
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_EMEM2_BIT 4
|
||||
|
||||
#define CDRU_CHIP_TOP_SPARE_REG0 (CDRU_BASE_ADDR + 0x378)
|
||||
#define CDRU_CHIP_TOP_SPARE_REG1 (CDRU_BASE_ADDR + 0x37c)
|
||||
|
||||
#define CENTRAL_TIMER_BASE (CRMU_CORE_BASE + 0x5000)
|
||||
#define CENTRAL_TIMER_CTRL (CENTRAL_TIMER_BASE + 0x0)
|
||||
#define CENTRAL_TIMER_GET_L (CENTRAL_TIMER_BASE + 0x4)
|
||||
#define CENTRAL_TIMER_GET_L0 (CENTRAL_TIMER_BASE + 0x8) /* SCR STM */
|
||||
#define CENTRAL_TIMER_GET_L1 (CENTRAL_TIMER_BASE + 0xC) /* FS STM */
|
||||
#define CENTRAL_TIMER_GET_L2 (CENTRAL_TIMER_BASE + 0x10) /* iHost0 */
|
||||
#define CENTRAL_TIMER_GET_L3 (CENTRAL_TIMER_BASE + 0x14) /* iHost1 */
|
||||
#define CENTRAL_TIMER_GET_L4 (CENTRAL_TIMER_BASE + 0x18) /* iHost2 */
|
||||
#define CENTRAL_TIMER_GET_L5 (CENTRAL_TIMER_BASE + 0x1C) /* iHost3 */
|
||||
#define CENTRAL_TIMER_GET_H (CENTRAL_TIMER_BASE + 0x28)
|
||||
#define CENTRAL_TIMER_SAT_TMR_ENA (CENTRAL_TIMER_BASE + 0x34)
|
||||
#define CENTRAL_TIMER_GET_IHOST_ENA_BASE (CENTRAL_TIMER_GET_L2)
|
||||
|
||||
#define CRMU_WDT_REGS_BASE (CRMU_CORE_BASE + 0x6000)
|
||||
|
||||
#define CRMU_MAIL_BOX0 (CRMU_CORE_BASE + 0x8024)
|
||||
#define CRMU_MAIL_BOX1 (CRMU_CORE_BASE + 0x8028)
|
||||
#define CRMU_READ_MAIL_BOX0 (CRMU_CORE_BASE + 0x802c)
|
||||
#define CRMU_READ_MAIL_BOX1 (CRMU_CORE_BASE + 0x8030)
|
||||
#define AP_TO_SCP_MAILBOX1 CRMU_MAIL_BOX1
|
||||
#define SCP_TO_AP_MAILBOX1 CRMU_READ_MAIL_BOX1
|
||||
#define CRMU_IHOST_POWER_CONFIG (CRMU_CORE_BASE + 0x8038)
|
||||
#define CRMU_RESET_EVENT_LOG (CRMU_CORE_BASE + 0x8064)
|
||||
#define CRMU_SOFT_RESET_CTRL (CRMU_CORE_BASE + 0x8090)
|
||||
#define CRMU_SOFT_RESET_CTRL__SOFT_PWR_UP_RST 0
|
||||
#define CRMU_SOFT_RESET_CTRL__SOFT_SYS_RST 1
|
||||
#define CRMU_SPARE_REG_0 (CRMU_CORE_BASE + 0x80b8)
|
||||
#define CRMU_SPARE_REG_1 (CRMU_CORE_BASE + 0x80bc)
|
||||
#define CRMU_SPARE_REG_2 (CRMU_CORE_BASE + 0x80c0)
|
||||
#define CRMU_SPARE_REG_3 (CRMU_CORE_BASE + 0x80c4)
|
||||
#define CRMU_SPARE_REG_4 (CRMU_CORE_BASE + 0x80c8)
|
||||
#define CRMU_SPARE_REG_5 (CRMU_CORE_BASE + 0x80cc)
|
||||
#define CRMU_CORE_ADDR_RANGE0_LOW (CRMU_CORE_BASE + 0x8c30)
|
||||
#define CRMU_CORE_ADDR_RANGE1_LOW (CRMU_CORE_BASE + 0x8c38)
|
||||
#define CRMU_CORE_ADDR_RANGE2_LOW (CRMU_CORE_BASE + 0x8c40)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG0 (CRMU_CORE_BASE + 0x8c54)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG1 (CRMU_CORE_BASE + 0x8c58)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG2 (CRMU_CORE_BASE + 0x8c5c)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG3 (CRMU_CORE_BASE + 0x8c60)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG4 (CRMU_CORE_BASE + 0x8c64)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG5 (CRMU_CORE_BASE + 0x8c68)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG6 (CRMU_CORE_BASE + 0x8c6c)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG7 (CRMU_CORE_BASE + 0x8c70)
|
||||
#define CRMU_BBL_AUTH_CHECK (CRMU_CORE_BASE + 0x8c78)
|
||||
#define CRMU_SOTP_NEUTRALIZE_ENABLE (CRMU_CORE_BASE + 0x8c84)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG8 (CRMU_CORE_BASE + 0x8c88)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG9 (CRMU_CORE_BASE + 0x8c8c)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG10 (CRMU_CORE_BASE + 0x8c90)
|
||||
#define CRMU_IHOST_SW_PERSISTENT_REG11 (CRMU_CORE_BASE + 0x8c94)
|
||||
|
||||
#define CNT_CONTROL_BASE (CRMU_CORE_BASE + 0x9000)
|
||||
#define CNTCR (CNT_CONTROL_BASE)
|
||||
#define CNTCR__EN BIT(0)
|
||||
|
||||
#define SPRU_BBL_WDATA (CRMU_CORE_BASE + 0xa000)
|
||||
#define SPRU_BBL_CMD (CRMU_CORE_BASE + 0xa004)
|
||||
#define SPRU_BBL_CMD__IND_SOFT_RST_N 10
|
||||
#define SPRU_BBL_CMD__IND_WR 11
|
||||
#define SPRU_BBL_CMD__BBL_ADDR_R 0
|
||||
#define SPRU_BBL_CMD__IND_RD 12
|
||||
#define SPRU_BBL_CMD__BBL_ADDR_R 0
|
||||
#define SPRU_BBL_STATUS (CRMU_CORE_BASE + 0xa008)
|
||||
#define SPRU_BBL_STATUS__ACC_DONE 0
|
||||
#define SPRU_BBL_RDATA (CRMU_CORE_BASE + 0xa00c)
|
||||
|
||||
#endif /* CRMU_DEF_H */
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef DDR_INIT_H
|
||||
#define DDR_INIT_H
|
||||
|
||||
#include <fru.h>
|
||||
|
||||
#pragma weak ddr_initialize
|
||||
#pragma weak ddr_secure_region_config
|
||||
#pragma weak ddr_info_save
|
||||
#pragma weak get_active_ddr_channel
|
||||
#pragma weak is_warmboot
|
||||
|
||||
void ddr_initialize(struct ddr_info *ddr)
|
||||
{
|
||||
}
|
||||
|
||||
void ddr_secure_region_config(uint64_t start, uint64_t end)
|
||||
{
|
||||
}
|
||||
|
||||
void ddr_info_save(void)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned char get_active_ddr_channel(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int is_warmboot(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef FSX_H
|
||||
#define FSX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum FSX_TYPE {
|
||||
eFS4_RAID,
|
||||
eFS4_CRYPTO,
|
||||
eFS6_PKI,
|
||||
} eFSX_TYPE;
|
||||
|
||||
void fsx_init(eFSX_TYPE fsx_type,
|
||||
unsigned int ring_count,
|
||||
unsigned int dme_count,
|
||||
unsigned int ae_count,
|
||||
unsigned int start_stream_id,
|
||||
unsigned int msi_dev_id,
|
||||
uintptr_t idm_io_control_direct,
|
||||
uintptr_t idm_reset_control,
|
||||
uintptr_t base,
|
||||
uintptr_t dme_base);
|
||||
|
||||
void fsx_meminit(const char *name,
|
||||
uintptr_t idm_io_control_direct,
|
||||
uintptr_t idm_io_status);
|
||||
|
||||
void fs4_disable_clocks(bool disable_sram,
|
||||
bool disable_crypto,
|
||||
bool disable_raid);
|
||||
|
||||
#endif /* FSX_H */
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef IHOST_PM
|
||||
#define IHOST_PM
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CLUSTER_POWER_ON 0x1
|
||||
#define CLUSTER_POWER_OFF 0x0
|
||||
|
||||
void ihost_power_on_cluster(u_register_t mpidr);
|
||||
void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar);
|
||||
void ihost_enable_satellite_timer(unsigned int cluster_id);
|
||||
|
||||
#endif
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef IOMMU_H
|
||||
#define IOMMU_H
|
||||
|
||||
enum iommu_domain {
|
||||
PCIE_PAXC,
|
||||
DOMAIN_CRMU,
|
||||
};
|
||||
|
||||
void arm_smmu_create_identity_map(enum iommu_domain dom);
|
||||
void arm_smmu_reserve_secure_cntxt(void);
|
||||
void arm_smmu_enable_secure_client_port(void);
|
||||
|
||||
#endif /* IOMMU_H */
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef NCSI_H
|
||||
#define NCSI_H
|
||||
|
||||
/*
|
||||
* There are 10 registers for NCSI IO drivers.
|
||||
*/
|
||||
#define NITRO_NCSI_IOPAD_CONTROL_NUM 10
|
||||
#define NITRO_NCSI_IOPAD_CONTROL_BASE 0x60e05080
|
||||
|
||||
/*
|
||||
* NCSI IO Drive strength
|
||||
* 000 - Drives 2mA
|
||||
* 001 - Drives 4mA
|
||||
* 010 - Drives 6mA
|
||||
* 011 - Drives 8mA
|
||||
* 100 - Drives 10mA
|
||||
* 101 - Drives 12mA
|
||||
* 110 - Drives 14mA
|
||||
* 111 - Drives 16mA
|
||||
*/
|
||||
#define PAD_SELX_VALUE(selx) ((selx) << 1)
|
||||
#define PAD_SELX_MASK (0x7 << 1)
|
||||
|
||||
void brcm_stingray_ncsi_init(void);
|
||||
|
||||
#endif
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PAXB_H
|
||||
#define PAXB_H
|
||||
|
||||
/* total number of PCIe cores */
|
||||
#define NUM_OF_SR_PCIE_CORES 8
|
||||
#define NUM_OF_NS3Z_PCIE_CORES 1
|
||||
|
||||
/*
|
||||
* List of PCIe core and PAXB wrapper memory power registers
|
||||
*/
|
||||
#define PCIE_CORE_BASE 0x40000800
|
||||
#define PCIE_CORE_SOFT_RST_CFG_BASE (PCIE_CORE_BASE + 0x40)
|
||||
#define PCIE_CORE_SOFT_RST 0x1
|
||||
#define PCIE_CORE_ISO_CFG_BASE (PCIE_CORE_BASE + 0x54)
|
||||
#define PCIE_CORE_MEM_ISO 0x2
|
||||
#define PCIE_CORE_ISO 0x1
|
||||
|
||||
#define PCIE_CORE_MEM_PWR_BASE (PCIE_CORE_BASE + 0x58)
|
||||
#define PCIE_PAXB_MEM_PWR_BASE (PCIE_CORE_BASE + 0x5c)
|
||||
#define PCIE_CORE_PMI_CFG_BASE (PCIE_CORE_BASE + 0x64)
|
||||
#define PCIE_CORE_RESERVED_CFG (PCIE_CORE_BASE + 0x6c)
|
||||
#define PCIE_CORE_MEM_PWR_STATUS_BASE (PCIE_CORE_BASE + 0x74)
|
||||
#define PCIE_PAXB_MEM_PWR_STATUS_BASE (PCIE_CORE_BASE + 0x78)
|
||||
#define PCIE_CORE_PWR_OFFSET 0x100
|
||||
|
||||
#define SR_A0_DEVICE_ID 0xd713
|
||||
#define SR_B0_DEVICE_ID 0xd714
|
||||
/* TODO: Modify device ID once available */
|
||||
#define NS3Z_DEVICE_ID 0xd715
|
||||
|
||||
/* FIXME: change link speed to GEN3 when it's ready */
|
||||
#define GEN1_LINK_SPEED 1
|
||||
#define GEN2_LINK_SPEED 2
|
||||
#define GEN3_LINK_SPEED 3
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t device_id;
|
||||
uint32_t pipemux_idx;
|
||||
uint32_t num_cores;
|
||||
int (*pipemux_init)(void);
|
||||
int (*phy_init)(void);
|
||||
int (*core_needs_enable)(unsigned int core_idx);
|
||||
unsigned int (*get_link_width)(unsigned int core_idx);
|
||||
unsigned int (*get_link_speed)(void);
|
||||
} paxb_cfg;
|
||||
|
||||
enum paxb_type {
|
||||
PAXB_SR,
|
||||
PAXB_NS3Z,
|
||||
};
|
||||
|
||||
extern const paxb_cfg *paxb;
|
||||
|
||||
#ifdef USE_PAXB
|
||||
void paxb_init(void);
|
||||
void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
|
||||
uint32_t val);
|
||||
unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where);
|
||||
int pcie_core_needs_enable(unsigned int core_idx);
|
||||
const paxb_cfg *paxb_get_sr_config(void);
|
||||
#else
|
||||
static inline void paxb_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PAXB_H */
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PAXC_H
|
||||
#define PAXC_H
|
||||
|
||||
#ifdef USE_PAXC
|
||||
void paxc_init(void);
|
||||
void paxc_mhb_ns_init(void);
|
||||
#else
|
||||
static inline void paxc_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void paxc_mhb_ns_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PAXC_H */
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
.section .rodata.gic_reg_name, "aS"
|
||||
gicc_regs:
|
||||
.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
|
||||
gicd_pend_reg:
|
||||
.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
|
||||
newline:
|
||||
.asciz "\n"
|
||||
spacer:
|
||||
.asciz ":\t\t0x"
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below required platform porting macro
|
||||
* prints out relevant registers whenever an
|
||||
* unhandled exception is taken in BL31.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
nop
|
||||
.endm
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below macro prints out relevant GIC
|
||||
* registers whenever an unhandled exception is
|
||||
* taken in BL31.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_print_gic_regs
|
||||
nop
|
||||
/*TBD-STINGRAY*/
|
||||
.endm
|
||||
|
||||
/* ------------------------------------------------
|
||||
* The below required platform porting macro prints
|
||||
* out relevant interconnect registers whenever an
|
||||
* unhandled exception is taken in BL3-1.
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
.macro plat_print_interconnect_regs
|
||||
nop
|
||||
/*TBD-STINGRAY*/
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
#include <brcm_def.h>
|
||||
#include "sr_def.h"
|
||||
#include <cmn_plat_def.h>
|
||||
|
||||
/*
|
||||
* Most platform porting definitions provided by included headers
|
||||
*/
|
||||
#define PLAT_BRCM_SCP_TZC_DRAM1_SIZE ULL(0x0)
|
||||
|
||||
/*
|
||||
* Required by standard platform porting definitions
|
||||
*/
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT 2
|
||||
#define PLATFORM_CLUSTER1_CORE_COUNT 2
|
||||
#define PLATFORM_CLUSTER2_CORE_COUNT 2
|
||||
#define PLATFORM_CLUSTER3_CORE_COUNT 2
|
||||
|
||||
#define BRCM_SYSTEM_COUNT 1
|
||||
#define BRCM_CLUSTER_COUNT 4
|
||||
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \
|
||||
PLATFORM_CLUSTER1_CORE_COUNT+ \
|
||||
PLATFORM_CLUSTER2_CORE_COUNT+ \
|
||||
PLATFORM_CLUSTER3_CORE_COUNT)
|
||||
|
||||
#define PLAT_NUM_PWR_DOMAINS (BRCM_SYSTEM_COUNT + \
|
||||
BRCM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
|
||||
|
||||
/* TBD-STINGRAY */
|
||||
#define CACHE_WRITEBACK_SHIFT 6
|
||||
/*
|
||||
* Some data must be 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.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/* TBD-STINGRAY */
|
||||
#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL1
|
||||
|
||||
#define BL1_PLATFORM_STACK_SIZE 0x3300
|
||||
#define BL2_PLATFORM_STACK_SIZE 0xc000
|
||||
#define BL11_PLATFORM_STACK_SIZE 0x2b00
|
||||
#define DEFAULT_PLATFORM_STACK_SIZE 0x400
|
||||
#if IMAGE_BL1
|
||||
# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE
|
||||
#else
|
||||
#if IMAGE_BL2
|
||||
#ifdef USE_BL1_RW
|
||||
# define PLATFORM_STACK_SIZE BL2_PLATFORM_STACK_SIZE
|
||||
#else
|
||||
# define PLATFORM_STACK_SIZE BL1_PLATFORM_STACK_SIZE
|
||||
#endif
|
||||
#else
|
||||
#if IMAGE_BL11
|
||||
# define PLATFORM_STACK_SIZE BL11_PLATFORM_STACK_SIZE
|
||||
#else
|
||||
# define PLATFORM_STACK_SIZE DEFAULT_PLATFORM_STACK_SIZE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PLAT_BRCM_TRUSTED_SRAM_BASE 0x66D00000
|
||||
#define PLAT_BRCM_TRUSTED_SRAM_SIZE 0x00040000
|
||||
|
||||
#ifdef RUN_BL1_FROM_QSPI /* BL1 XIP from QSPI */
|
||||
# define PLAT_BRCM_TRUSTED_ROM_BASE QSPI_BASE_ADDR
|
||||
#elif RUN_BL1_FROM_NAND /* BL1 XIP from NAND */
|
||||
# define PLAT_BRCM_TRUSTED_ROM_BASE NAND_BASE_ADDR
|
||||
#else /* BL1 executed in ROM */
|
||||
# define PLAT_BRCM_TRUSTED_ROM_BASE ROM_BASE_ADDR
|
||||
#endif
|
||||
#define PLAT_BRCM_TRUSTED_ROM_SIZE 0x00040000
|
||||
|
||||
/*******************************************************************************
|
||||
* BL1 specific defines.
|
||||
******************************************************************************/
|
||||
#define BL1_RO_BASE PLAT_BRCM_TRUSTED_ROM_BASE
|
||||
#define BL1_RO_LIMIT (PLAT_BRCM_TRUSTED_ROM_BASE \
|
||||
+ PLAT_BRCM_TRUSTED_ROM_SIZE)
|
||||
|
||||
/*
|
||||
* Put BL1 RW at the beginning of the Trusted SRAM.
|
||||
*/
|
||||
#define BL1_RW_BASE (BRCM_BL_RAM_BASE)
|
||||
#define BL1_RW_LIMIT (BL1_RW_BASE + 0x12000)
|
||||
|
||||
#define BL11_RW_BASE BL1_RW_LIMIT
|
||||
#define BL11_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \
|
||||
PLAT_BRCM_TRUSTED_SRAM_SIZE)
|
||||
|
||||
/*******************************************************************************
|
||||
* BL2 specific defines.
|
||||
******************************************************************************/
|
||||
#if RUN_BL2_FROM_QSPI /* BL2 XIP from QSPI */
|
||||
#define BL2_BASE QSPI_BASE_ADDR
|
||||
#define BL2_LIMIT (BL2_BASE + 0x40000)
|
||||
#define BL2_RW_BASE BL1_RW_LIMIT
|
||||
#define BL2_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \
|
||||
PLAT_BRCM_TRUSTED_SRAM_SIZE)
|
||||
#elif RUN_BL2_FROM_NAND /* BL2 XIP from NAND */
|
||||
#define BL2_BASE NAND_BASE_ADDR
|
||||
#define BL2_LIMIT (BL2_BASE + 0x40000)
|
||||
#define BL2_RW_BASE BL1_RW_LIMIT
|
||||
#define BL2_RW_LIMIT (PLAT_BRCM_TRUSTED_SRAM_BASE + \
|
||||
PLAT_BRCM_TRUSTED_SRAM_SIZE)
|
||||
#else
|
||||
#define BL2_BASE (BL1_RW_LIMIT + PAGE_SIZE)
|
||||
#define BL2_LIMIT (BRCM_BL_RAM_BASE + BRCM_BL_RAM_SIZE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BL1 persistent area in internal SRAM
|
||||
* This area will increase as more features gets into BL1
|
||||
*/
|
||||
#define BL1_PERSISTENT_DATA_SIZE 0x2000
|
||||
|
||||
/* To reduce BL2 runtime footprint, we can re-use some BL1_RW area */
|
||||
#define BL1_RW_RECLAIM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \
|
||||
BL1_PERSISTENT_DATA_SIZE)
|
||||
|
||||
/*******************************************************************************
|
||||
* BL3-1 specific defines.
|
||||
******************************************************************************/
|
||||
/* Max Size of BL31 (in DRAM) */
|
||||
#define PLAT_BRCM_MAX_BL31_SIZE 0x30000
|
||||
|
||||
#ifdef USE_DDR
|
||||
#define BL31_BASE BRCM_AP_TZC_DRAM1_BASE
|
||||
|
||||
#define BL31_LIMIT (BRCM_AP_TZC_DRAM1_BASE + \
|
||||
PLAT_BRCM_MAX_BL31_SIZE)
|
||||
#else
|
||||
/* Put BL3-1 at the end of external on-board SRAM connected as NOR flash */
|
||||
#define BL31_BASE (NOR_BASE_ADDR + NOR_SIZE - \
|
||||
PLAT_BRCM_MAX_BL31_SIZE)
|
||||
|
||||
#define BL31_LIMIT (NOR_BASE_ADDR + NOR_SIZE)
|
||||
#endif
|
||||
|
||||
#define SECURE_DDR_END_ADDRESS BL31_LIMIT
|
||||
|
||||
#ifdef NEED_SCP_BL2
|
||||
#define SCP_BL2_BASE BL31_BASE
|
||||
#define PLAT_MAX_SCP_BL2_SIZE 0x9000
|
||||
#define PLAT_SCP_COM_SHARED_MEM_BASE (CRMU_SHARED_SRAM_BASE)
|
||||
/* dummy defined */
|
||||
#define PLAT_BRCM_MHU_BASE 0x0
|
||||
#endif
|
||||
|
||||
#define SECONDARY_CPU_SPIN_BASE_ADDR BRCM_SHARED_RAM_BASE
|
||||
|
||||
/* Generic system timer counter frequency */
|
||||
#ifndef SYSCNT_FREQ
|
||||
#define SYSCNT_FREQ (125 * 1000 * 1000)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable the BL32 definitions, only when optee os is selected as secure
|
||||
* payload (BL32).
|
||||
*/
|
||||
#ifdef SPD_opteed
|
||||
/*
|
||||
* Reserved Memory Map : SHMEM & TZDRAM.
|
||||
*
|
||||
* +--------+----------+ 0x8D000000
|
||||
* | SHMEM (NS) | 16MB
|
||||
* +-------------------+ 0x8E000000
|
||||
* | | TEE_RAM(S)| 4MB
|
||||
* + TZDRAM +----------+ 0x8E400000
|
||||
* | | TA_RAM(S) | 12MB
|
||||
* +-------------------+ 0x8F000000
|
||||
* | BL31 Binary (S) | 192KB
|
||||
* +-------------------+ 0x8F030000
|
||||
*/
|
||||
|
||||
#define BL32_VA_SIZE (4 * 1024 * 1024)
|
||||
#define BL32_BASE (0x8E000000)
|
||||
#define BL32_LIMIT (BL32_BASE + BL32_VA_SIZE)
|
||||
#define TSP_SEC_MEM_BASE BL32_BASE
|
||||
#define TSP_SEC_MEM_SIZE BL32_VA_SIZE
|
||||
#endif
|
||||
|
||||
#ifdef SPD_opteed
|
||||
#define SECURE_DDR_BASE_ADDRESS BL32_BASE
|
||||
#else
|
||||
#define SECURE_DDR_BASE_ADDRESS BL31_BASE
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
* Platform specific page table and MMU setup constants
|
||||
******************************************************************************/
|
||||
|
||||
#define MAX_XLAT_TABLES 7
|
||||
|
||||
#define PLAT_BRCM_MMAP_ENTRIES 10
|
||||
|
||||
#define MAX_MMAP_REGIONS (PLAT_BRCM_MMAP_ENTRIES + \
|
||||
BRCM_BL_REGIONS)
|
||||
|
||||
#ifdef USE_DDR
|
||||
#ifdef BL33_OVERRIDE_LOAD_ADDR
|
||||
#define PLAT_BRCM_NS_IMAGE_OFFSET BL33_OVERRIDE_LOAD_ADDR
|
||||
#else
|
||||
/*
|
||||
* BL3-3 image starting offset.
|
||||
* Putting start of DRAM as of now.
|
||||
*/
|
||||
#define PLAT_BRCM_NS_IMAGE_OFFSET 0x80000000
|
||||
#endif /* BL33_OVERRIDE_LOAD_ADDR */
|
||||
#else
|
||||
/*
|
||||
* BL3-3 image starting offset.
|
||||
* Putting start of external on-board SRAM as of now.
|
||||
*/
|
||||
#define PLAT_BRCM_NS_IMAGE_OFFSET NOR_BASE_ADDR
|
||||
#endif /* USE_DDR */
|
||||
/******************************************************************************
|
||||
* Required platform porting definitions common to all BRCM platforms
|
||||
*****************************************************************************/
|
||||
|
||||
#define MAX_IO_DEVICES 5
|
||||
#define MAX_IO_HANDLES 6
|
||||
|
||||
#define PRIMARY_CPU 0
|
||||
|
||||
/* GIC Parameter */
|
||||
#define PLAT_BRCM_GICD_BASE GIC500_BASE
|
||||
#define PLAT_BRCM_GICR_BASE (GIC500_BASE + 0x200000)
|
||||
|
||||
/* Define secure interrupt as per Group here */
|
||||
#define PLAT_BRCM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(BRCM_IRQ_SEC_SPI_0, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define PLAT_BRCM_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(BRCM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
|
||||
/*
|
||||
*CCN 502 related constants.
|
||||
*/
|
||||
#define PLAT_BRCM_CLUSTER_COUNT 4 /* Number of RN-F Masters */
|
||||
#define PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP CLUSTER0_NODE_ID, CLUSTER1_NODE_ID, CLUSTER2_NODE_ID, CLUSTER3_NODE_ID
|
||||
#define CCN_SIZE 0x1000000
|
||||
#define CLUSTER0_NODE_ID 1
|
||||
#define CLUSTER1_NODE_ID 7
|
||||
#define CLUSTER2_NODE_ID 9
|
||||
#define CLUSTER3_NODE_ID 15
|
||||
|
||||
#endif
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_SOTP_H
|
||||
#define PLATFORM_SOTP_H
|
||||
|
||||
#define SOTP_DEVICE_SECURE_CFG0_ROW 17
|
||||
#define SOTP_DEVICE_SECURE_CFG1_ROW 18
|
||||
#define SOTP_DEVICE_SECURE_CFG2_ROW 19
|
||||
#define SOTP_DEVICE_SECURE_CFG3_ROW 20
|
||||
#define SOTP_BRCM_SOFTWARE_CFG0_ROW 21
|
||||
#define SOTP_BRCM_SOFTWARE_CFG1_ROW 22
|
||||
#define SOTP_BRCM_SOFTWARE_CFG2_ROW 23
|
||||
#define SOTP_BRCM_SOFTWARE_CFG3_ROW 24
|
||||
#define SOTP_CUSTOMER_ID_CFG0_ROW 25
|
||||
#define SOTP_CUSTOMER_ID_CFG1_ROW 26
|
||||
#define SOTP_CUSTOMER_ID_CFG2_ROW 27
|
||||
#define SOTP_CUSTOMER_ID_CFG3_ROW 28
|
||||
#define SOTP_CUSTOMER_DEV_CFG0_ROW 29
|
||||
#define SOTP_CUSTOMER_DEV_CFG1_ROW 30
|
||||
#define SOTP_CUSTOMER_DEV_CFG2_ROW 31
|
||||
#define SOTP_CUSTOMER_DEV_CFG3_ROW 32
|
||||
#define SOTP_DAUTH_ROW 33
|
||||
#define SOTP_K_HMAC_ROW 45
|
||||
#define SOTP_K_AES_ROW 57
|
||||
#define SOTP_NVCOUNTER_ROW 69
|
||||
|
||||
#define SOTP_BRCM_CFG_ECC_ERROR_MASK 0x100000
|
||||
#define SOTP_DAUTH_ECC_ERROR_MASK 0x800000
|
||||
#define SOTP_K_HMAC_ECC_ERROR_MASK 0x1000000
|
||||
#define SOTP_K_AES_ECC_ERROR_MASK 0x2000000
|
||||
|
||||
#endif
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2019 - 2021, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_USB_H
|
||||
#define PLATFORM_USB_H
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define USB3_DRD BIT(0U)
|
||||
#define USB3H_USB2DRD BIT(1U)
|
||||
|
||||
extern const unsigned int xhc_portsc_reg_offset[MAX_USB_PORTS];
|
||||
|
||||
void xhci_phy_init(void);
|
||||
|
||||
#endif /* PLATFORM_USB_H */
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SCP_CMD_H
|
||||
#define SCP_SMD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
int cmd;
|
||||
int completed;
|
||||
int ret;
|
||||
} crmu_response_t;
|
||||
|
||||
|
||||
#define SCP_CMD_MASK 0xffff
|
||||
#define SCP_CMD_DEFAULT_TIMEOUT_US 1000
|
||||
#define SCP_CMD_SCP_BOOT_TIMEOUT_US 5000
|
||||
|
||||
int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout);
|
||||
|
||||
#endif
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SCP_UTILS_H
|
||||
#define SCP_UTILS_H
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <m0_cfg.h>
|
||||
|
||||
int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info);
|
||||
|
||||
bool is_crmu_alive(void);
|
||||
bool bcm_scp_issue_sys_reset(void);
|
||||
|
||||
#define SCP_READ_CFG(cfg) mmio_read_32(CRMU_CFG_BASE + \
|
||||
offsetof(M0CFG, cfg))
|
||||
#define SCP_WRITE_CFG(cfg, value) mmio_write_32(CRMU_CFG_BASE + \
|
||||
offsetof(M0CFG, cfg), value)
|
||||
|
||||
#define SCP_READ_CFG16(cfg) mmio_read_16(CRMU_CFG_BASE + \
|
||||
offsetof(M0CFG, cfg))
|
||||
#define SCP_WRITE_CFG16(cfg, value) mmio_write_16(CRMU_CFG_BASE + \
|
||||
offsetof(M0CFG, cfg), value)
|
||||
|
||||
#define SCP_READ_CFG8(cfg) mmio_read_8(CRMU_CFG_BASE + \
|
||||
offsetof(M0CFG, cfg))
|
||||
#define SCP_WRITE_CFG8(cfg, value) mmio_write_8(CRMU_CFG_BASE + \
|
||||
offsetof(M0CFG, cfg), value)
|
||||
#endif
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SDIO_H
|
||||
#define SDIO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SR_IPROC_SDIO0_CFG_BASE 0x689006e4
|
||||
#define SR_IPROC_SDIO0_SID_BASE 0x68900b00
|
||||
#define SR_IPROC_SDIO0_PAD_BASE 0x68a4017c
|
||||
#define SR_IPROC_SDIO0_IOCTRL_BASE 0x68e02408
|
||||
|
||||
#define SR_IPROC_SDIO1_CFG_BASE 0x68900734
|
||||
#define SR_IPROC_SDIO1_SID_BASE 0x68900b08
|
||||
#define SR_IPROC_SDIO1_PAD_BASE 0x68a401b4
|
||||
#define SR_IPROC_SDIO1_IOCTRL_BASE 0x68e03408
|
||||
|
||||
#define NS3Z_IPROC_SDIO0_CFG_BASE 0x68a20540
|
||||
#define NS3Z_IPROC_SDIO0_SID_BASE 0x68900b00
|
||||
#define NS3Z_IPROC_SDIO0_TP_OUT_SEL 0x68a20308
|
||||
#define NS3Z_IPROC_SDIO0_PAD_BASE 0x68a20500
|
||||
#define NS3Z_IPROC_SDIO0_IOCTRL_BASE 0x68e02408
|
||||
|
||||
#define PHY_BYPASS BIT(14)
|
||||
#define LEGACY_EN BIT(31)
|
||||
#define PHY_DISABLE (LEGACY_EN | PHY_BYPASS)
|
||||
|
||||
#define NS3Z_IPROC_SDIO1_CFG_BASE 0x68a30540
|
||||
#define NS3Z_IPROC_SDIO1_SID_BASE 0x68900b08
|
||||
#define NS3Z_IPROC_SDIO1_PAD_BASE 0x68a30500
|
||||
#define NS3Z_IPROC_SDIO1_IOCTRL_BASE 0x68e03408
|
||||
|
||||
#define ICFG_SDIO_CAP0 0x10
|
||||
#define ICFG_SDIO_CAP1 0x14
|
||||
#define ICFG_SDIO_STRAPSTATUS_0 0x0
|
||||
#define ICFG_SDIO_STRAPSTATUS_1 0x4
|
||||
#define ICFG_SDIO_STRAPSTATUS_2 0x8
|
||||
#define ICFG_SDIO_STRAPSTATUS_3 0xc
|
||||
#define ICFG_SDIO_STRAPSTATUS_4 0x18
|
||||
|
||||
#define ICFG_SDIO_SID_ARADDR 0x0
|
||||
#define ICFG_SDIO_SID_AWADDR 0x4
|
||||
|
||||
#define ICFG_SDIOx_CAP0__SLOT_TYPE_MASK 0x3
|
||||
#define ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT 27
|
||||
#define ICFG_SDIOx_CAP0__INT_MODE_SHIFT 26
|
||||
#define ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT 25
|
||||
#define ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT 24
|
||||
#define ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT 23
|
||||
#define ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT 22
|
||||
#define ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT 21
|
||||
#define ICFG_SDIOx_CAP0__SDMA_SHIFT 20
|
||||
#define ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT 19
|
||||
#define ICFG_SDIOx_CAP0__ADMA2_SHIFT 18
|
||||
#define ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT 17
|
||||
#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_MASK 0x3
|
||||
#define ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT 15
|
||||
#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_MASK 0xff
|
||||
#define ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT 7
|
||||
#define ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT 6
|
||||
#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_MASK 0x3f
|
||||
#define ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT 0
|
||||
|
||||
#define ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT 22
|
||||
#define ICFG_SDIOx_CAP1__SPI_MODE_SHIFT 21
|
||||
#define ICFG_SDIOx_CAP1__CLK_MULT_MASK 0xff
|
||||
#define ICFG_SDIOx_CAP1__CLK_MULT_SHIFT 13
|
||||
#define ICFG_SDIOx_CAP1__RETUNING_MODE_MASK 0x3
|
||||
#define ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT 11
|
||||
#define ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT 10
|
||||
#define ICFG_SDIOx_CAP1__TIME_RETUNE_MASK 0xf
|
||||
#define ICFG_SDIOx_CAP1__TIME_RETUNE_SHIFT 6
|
||||
#define ICFG_SDIOx_CAP1__DRIVER_D_SHIFT 5
|
||||
#define ICFG_SDIOx_CAP1__DRIVER_C_SHIFT 4
|
||||
#define ICFG_SDIOx_CAP1__DRIVER_A_SHIFT 3
|
||||
#define ICFG_SDIOx_CAP1__DDR50_SHIFT 2
|
||||
#define ICFG_SDIOx_CAP1__SDR104_SHIFT 1
|
||||
#define ICFG_SDIOx_CAP1__SDR50_SHIFT 0
|
||||
|
||||
#ifdef USE_DDR
|
||||
#define SDIO_DMA 1
|
||||
#else
|
||||
#define SDIO_DMA 0
|
||||
#endif
|
||||
|
||||
#define SDIO0_CAP0_CFG \
|
||||
(0x1 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
|
||||
| (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
|
||||
| (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
|
||||
| (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
|
||||
| (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
|
||||
| (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
|
||||
| (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
|
||||
| (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
|
||||
|
||||
#define SDIO0_CAP1_CFG \
|
||||
(0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
|
||||
| (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
|
||||
| (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
|
||||
| (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
|
||||
| (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
|
||||
|
||||
#define SDIO1_CAP0_CFG \
|
||||
(0x0 << ICFG_SDIOx_CAP0__SLOT_TYPE_SHIFT) \
|
||||
| (0x0 << ICFG_SDIOx_CAP0__INT_MODE_SHIFT) \
|
||||
| (0x0 << ICFG_SDIOx_CAP0__SYS_BUS_64BIT_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_1P8V_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P0V_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__VOLTAGE_3P3V_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__SUSPEND_RESUME_SHIFT) \
|
||||
| (SDIO_DMA << ICFG_SDIOx_CAP0__SDMA_SHIFT) \
|
||||
| (SDIO_DMA << ICFG_SDIOx_CAP0__ADMA2_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__HIGH_SPEED_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__EXTENDED_MEDIA_SHIFT) \
|
||||
| (0x2 << ICFG_SDIOx_CAP0__MAX_BLOCK_LEN_SHIFT) \
|
||||
| (0xc8 << ICFG_SDIOx_CAP0__BASE_CLK_FREQ_SHIFT) \
|
||||
| (0x1 << ICFG_SDIOx_CAP0__TIMEOUT_UNIT_SHIFT) \
|
||||
| (0x30 << ICFG_SDIOx_CAP0__TIMEOUT_CLK_FREQ_SHIFT)
|
||||
|
||||
#define SDIO1_CAP1_CFG \
|
||||
(0x1 << ICFG_SDIOx_CAP1__SPI_BLOCK_MODE_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__SPI_MODE_SHIFT)\
|
||||
| (0x0 << ICFG_SDIOx_CAP1__CLK_MULT_SHIFT)\
|
||||
| (0x2 << ICFG_SDIOx_CAP1__RETUNING_MODE_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__TUNE_SDR50_SHIFT)\
|
||||
| (0x0 << ICFG_SDIOx_CAP1__DRIVER_D_SHIFT)\
|
||||
| (0x0 << ICFG_SDIOx_CAP1__DRIVER_C_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__DRIVER_A_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__DDR50_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__SDR104_SHIFT)\
|
||||
| (0x1 << ICFG_SDIOx_CAP1__SDR50_SHIFT)
|
||||
|
||||
#define PAD_SDIO_CLK 0x4
|
||||
#define PAD_SDIO_DATA0 0x8
|
||||
#define PAD_SDIO_DATA1 0xc
|
||||
#define PAD_SDIO_DATA2 0x10
|
||||
#define PAD_SDIO_DATA3 0x14
|
||||
#define PAD_SDIO_DATA4 0x18
|
||||
#define PAD_SDIO_DATA5 0x1c
|
||||
#define PAD_SDIO_DATA6 0x20
|
||||
#define PAD_SDIO_DATA7 0x24
|
||||
#define PAD_SDIO_CMD 0x28
|
||||
|
||||
/* 12mA Drive strength*/
|
||||
#define PAD_SDIO_SELX (0x5 << 1)
|
||||
#define PAD_SDIO_SRC (1 << 0)
|
||||
#define PAD_SDIO_MASK (0xF << 0)
|
||||
#define PAD_SDIO_VALUE (PAD_SDIO_SELX | PAD_SDIO_SRC)
|
||||
|
||||
/*
|
||||
* SDIO_PRESETVAL0
|
||||
*
|
||||
* Each 13 Bit filed consists:
|
||||
* drivestrength - 12:11
|
||||
* clkgensel - b10
|
||||
* sdkclkfreqsel - 9:0
|
||||
* Field Bit(s) Description
|
||||
* ============================================================
|
||||
* SDR25_PRESET 25:13 Preset Value for SDR25
|
||||
* SDR50_PRESET 12:0 Preset Value for SDR50
|
||||
*/
|
||||
#define SDIO_PRESETVAL0 0x01005001
|
||||
|
||||
/*
|
||||
* SDIO_PRESETVAL1
|
||||
*
|
||||
* Each 13 Bit filed consists:
|
||||
* drivestrength - 12:11
|
||||
* clkgensel - b10
|
||||
* sdkclkfreqsel - 9:0
|
||||
* Field Bit(s) Description
|
||||
* ============================================================
|
||||
* SDR104_PRESET 25:13 Preset Value for SDR104
|
||||
* SDR12_PRESET 12:0 Preset Value for SDR12
|
||||
*/
|
||||
#define SDIO_PRESETVAL1 0x03000004
|
||||
|
||||
/*
|
||||
* SDIO_PRESETVAL2
|
||||
*
|
||||
* Each 13 Bit filed consists:
|
||||
* drivestrength - 12:11
|
||||
* clkgensel - b10
|
||||
* sdkclkfreqsel - 9:0
|
||||
* Field Bit(s) Description
|
||||
* ============================================================
|
||||
* HIGH_SPEED_PRESET 25:13 Preset Value for High Speed
|
||||
* INIT_PRESET 12:0 Preset Value for Initialization
|
||||
*/
|
||||
#define SDIO_PRESETVAL2 0x010040FA
|
||||
|
||||
/*
|
||||
* SDIO_PRESETVAL3
|
||||
*
|
||||
* Each 13 Bit filed consists:
|
||||
* drivestrength - 12:11
|
||||
* clkgensel - b10
|
||||
* sdkclkfreqsel - 9:0
|
||||
* Field Bit(s) Description
|
||||
* ============================================================
|
||||
* DDR50_PRESET 25:13 Preset Value for DDR50
|
||||
* DEFAULT_PRESET 12:0 Preset Value for Default Speed
|
||||
*/
|
||||
#define SDIO_PRESETVAL3 0x01004004
|
||||
|
||||
/*
|
||||
* SDIO_PRESETVAL4
|
||||
*
|
||||
* Field Bit(s) Description
|
||||
* ============================================================
|
||||
* FORCE_USE_IP_TUNE_CLK 30 Force use IP clock
|
||||
* TUNING_COUNT 29:24 Tuning count
|
||||
* OVERRIDE_1P8V 23:16
|
||||
* OVERRIDE_3P3V 15:8
|
||||
* OVERRIDE_3P0V 7:0
|
||||
*/
|
||||
#define SDIO_PRESETVAL4 0x20010101
|
||||
|
||||
#define SDIO_SID_SHIFT 5
|
||||
|
||||
typedef struct {
|
||||
uintptr_t cfg_base;
|
||||
uintptr_t sid_base;
|
||||
uintptr_t io_ctrl_base;
|
||||
uintptr_t pad_base;
|
||||
} SDIO_CFG;
|
||||
|
||||
void brcm_stingray_sdio_init(void);
|
||||
|
||||
#endif /* SDIO_H */
|
||||
+624
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2021, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SR_DEF_H
|
||||
#define SR_DEF_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <lib/mmio.h>
|
||||
#endif
|
||||
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
|
||||
#include <crmu_def.h>
|
||||
|
||||
/* Special value used to verify platform parameters from BL2 to BL3-1 */
|
||||
#define BRCM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978)
|
||||
|
||||
#define MHB_BASE_ADDR 0x60000000
|
||||
#define PLAT_BRCM_CCN_BASE 0x61000000
|
||||
#define CORESIGHT_BASE_ADDR 0x62000000
|
||||
#define SMMU_BASE 0x64000000
|
||||
|
||||
/* memory map entries*/
|
||||
/* Grouping block device for bigger MMU region */
|
||||
/* covers MHB, CNN, coresight, GIC, MMU, APB, CRMU */
|
||||
#define PERIPH0_BASE MHB_BASE_ADDR
|
||||
#define PERIPH0_SIZE 0x06d00000
|
||||
|
||||
#define PERIPH1_BASE 0x66d80000
|
||||
#define PERIPH1_SIZE 0x00f80000
|
||||
|
||||
#define HSLS_BASE_ADDR 0x68900000
|
||||
#define HSLS_SIZE 0x04500000
|
||||
|
||||
#define GIC500_BASE 0x63c00000
|
||||
#define GIC500_SIZE 0x400000
|
||||
|
||||
/*******************************************************************************
|
||||
* CCN related constants
|
||||
******************************************************************************/
|
||||
#define OLY_MN_REGISTERS_NODE0_SECURE_ACCESS (PLAT_BRCM_CCN_BASE + 0x0)
|
||||
|
||||
#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x880500)
|
||||
|
||||
/* Used for acceleration of coherent ordered writes */
|
||||
#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WUO BIT(4)
|
||||
/* Wait for completion of requests at RN-I */
|
||||
#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_WFC BIT(3)
|
||||
|
||||
/*
|
||||
* Forces all reads from the RN-I to be sent with the request order bit set
|
||||
* and this ensures ordered allocation of read data buffers in the RN-I
|
||||
*/
|
||||
#define OLY_RNI3PDVM_REGISTERS_NODE8_AUX_CTL_RQO BIT(5)
|
||||
|
||||
#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x8e0500)
|
||||
|
||||
/* Wait for completion of requests at RN-I */
|
||||
#define OLY_RNI3PDVM_REGISTERS_NODE14_AUX_CTL_WFC BIT(3)
|
||||
|
||||
#define OLY_HNI_REGISTERS_NODE0_POS_CONTROL (PLAT_BRCM_CCN_BASE + 0x80000)
|
||||
#define POS_CONTROL_HNI_POS_EN BIT(0)
|
||||
|
||||
#define OLY_HNI_REGISTERS_NODE0_PCIERC_RNI_NODEID_LIST \
|
||||
(PLAT_BRCM_CCN_BASE + 0x80008)
|
||||
/* PAXB and PAXC connected to 8th Node */
|
||||
#define SR_RNI_PCIE_CONNECTED BIT(8)
|
||||
/* PAXB connected to 6th Node */
|
||||
#define SRP_RNI_PCIE_CONNECTED BIT(6)
|
||||
|
||||
#define OLY_HNI_REGISTERS_NODE0_SA_AUX_CTL (PLAT_BRCM_CCN_BASE + 0x80500)
|
||||
#define SA_AUX_CTL_POS_EARLY_WR_COMP_EN BIT(5)
|
||||
#define SA_AUX_CTL_SER_DEVNE_WR BIT(9)
|
||||
|
||||
/*******************************************************************************
|
||||
* Coresight related constants
|
||||
******************************************************************************/
|
||||
#define CORESIGHT_BASE_ADDR 0x62000000
|
||||
|
||||
#define IHOST0_BASE 0x66000000
|
||||
#define IHOST_ADDR_SPACE 0x2000
|
||||
|
||||
/*******************************************************************************
|
||||
* SCR related constants
|
||||
******************************************************************************/
|
||||
#define SCR_BASE 0x6600a000
|
||||
#define SCR_ARCACHE_OFFSET 4
|
||||
#define SCR_ARCACHE_MASK (0x3 << SCR_ARCACHE_OFFSET)
|
||||
#define SCR_AWCACHE_OFFSET 6
|
||||
#define SCR_AWCACHE_MASK (0x3 << SCR_AWCACHE_OFFSET)
|
||||
#define SCR_AXCACHE_CONFIG_MASK (SCR_ARCACHE_MASK | SCR_AWCACHE_MASK)
|
||||
#define SCR_TBUX_AXCACHE_CONFIG ((0x1 << SCR_AWCACHE_OFFSET) | \
|
||||
(0x1 << SCR_ARCACHE_OFFSET))
|
||||
|
||||
#define SCR_REGS_SCR_SOFT_RESET (SCR_BASE + 0x1c)
|
||||
#define SCR_REGS_GIC_SOFT_RESET BIT(0)
|
||||
|
||||
#define SCR_GPV_BASE 0x66100000
|
||||
#define SCR_NOC_SECURITY0 (SCR_GPV_BASE + 0x08)
|
||||
#define SCR_NOC_DDR_REGISTER_ACCESS (SCR_GPV_BASE + 0x30)
|
||||
|
||||
/*******************************************************************************
|
||||
* MEMC and DDR related constants
|
||||
******************************************************************************/
|
||||
#define DDR0_CONTROL_ROOT 0x66200000
|
||||
#define EMEM_SS_CFG_0_ROOT 0x66202000
|
||||
#define EMEM_SYS_IF_0_ROOT 0x66204000
|
||||
#define DDR_PHY0_ROOT 0x66240000
|
||||
|
||||
#define DDR1_CONTROL_ROOT 0x66280000
|
||||
#define EMEM_SS_CFG_1_ROOT 0x66282000
|
||||
#define EMEM_SYS_IF_1_ROOT 0x66284000
|
||||
#define DDR_PHY1_ROOT 0x662c0000
|
||||
|
||||
#define DDR2_CONTROL_ROOT 0x66300000
|
||||
#define EMEM_SS_CFG_2_ROOT 0x66302000
|
||||
#define EMEM_SYS_IF_2_ROOT 0x66304000
|
||||
#define DDR_PHY2_ROOT 0x66340000
|
||||
|
||||
/*******************************************************************************
|
||||
* TZC400 related constants
|
||||
******************************************************************************/
|
||||
#define TZC_400_BASE 0x66d84000
|
||||
|
||||
/*******************************************************************************
|
||||
* FS4 related constants
|
||||
******************************************************************************/
|
||||
#define FS4_SRAM_IDM_IO_CONTROL_DIRECT 0x66d8a408
|
||||
|
||||
#define FS4_CRYPTO_IDM_IO_CONTROL_DIRECT 0x66d8e408
|
||||
#define FS4_CRYPTO_IDM_RESET_CONTROL 0x66d8e800
|
||||
#define FS4_CRYPTO_BASE 0x67000000
|
||||
#define FS4_CRYPTO_DME_BASE (FS4_CRYPTO_BASE + 0x280000)
|
||||
|
||||
#define FS4_RAID_IDM_IO_CONTROL_DIRECT 0x66d8f408
|
||||
#define FS4_RAID_IDM_IO_STATUS 0x66d8f500
|
||||
#define FS4_RAID_IDM_RESET_CONTROL 0x66d8f800
|
||||
#define FS4_RAID_BASE 0x67400000
|
||||
#define FS4_RAID_DME_BASE (FS4_RAID_BASE + 0x280000)
|
||||
|
||||
#define FS4_CRYPTO_GPV_BASE 0x67300000
|
||||
#define FS4_RAID_GPV_BASE 0x67700000
|
||||
|
||||
#define FS6_PKI_BASE 0x67400000
|
||||
#define FS6_PKI_DME_BASE 0x66D90000
|
||||
|
||||
#define TZC400_FS_SRAM_ROOT 0x66d84000
|
||||
#define GATE_KEEPER_OFFSET 0x8
|
||||
#define REGION_ATTRIBUTES_0_OFFSET 0x110
|
||||
#define REGION_ID_ACCESS_0_OFFSET 0x114
|
||||
|
||||
#define NIC400_FS_NOC_ROOT 0x66e00000
|
||||
#define NIC400_FS_NOC_SECURITY2_OFFSET 0x10
|
||||
#define NIC400_FS_NOC_SECURITY4_OFFSET 0x18
|
||||
#define NIC400_FS_NOC_SECURITY7_OFFSET 0x24
|
||||
|
||||
/*******************************************************************************
|
||||
* SATA PHY related constants
|
||||
******************************************************************************/
|
||||
#define SATA_BASE 0x67d00000
|
||||
|
||||
/*******************************************************************************
|
||||
* USB related constants
|
||||
******************************************************************************/
|
||||
#define USB_BASE 0x68500000
|
||||
#define USB_SIZE 0x00400000
|
||||
#define XHC_BASE (USB_BASE + 0x11000)
|
||||
#define MAX_USB_PORTS 3
|
||||
|
||||
/*******************************************************************************
|
||||
* HSLS related constants
|
||||
******************************************************************************/
|
||||
#define IPROC_ROOT 0x68900000
|
||||
#define HSLS_ICFG_REGS_BASE IPROC_ROOT
|
||||
#define HSLS_IDM_REGS_BASE 0x68e00000
|
||||
#define HSLS_MODE_SEL_CONTROL 0x68a40000
|
||||
#define HSLS_TZPC_BASE 0x68b40000
|
||||
#define HSLS_GPV_BASE 0x6cd00000
|
||||
|
||||
/*******************************************************************************
|
||||
* Chip ID related constants
|
||||
******************************************************************************/
|
||||
#define ICFG_CHIP_ID HSLS_ICFG_REGS_BASE
|
||||
#define CHIP_ID_SR 0xd730
|
||||
#define CHIP_ID_NS3Z 0xe56d
|
||||
#define CHIP_ID_MASK 0xf000
|
||||
#define ICFG_CHIP_REVISION_ID (HSLS_ICFG_REGS_BASE + 0x4)
|
||||
#define PLAT_CHIP_ID_GET (mmio_read_32(ICFG_CHIP_ID))
|
||||
#define PLAT_CHIP_REV_GET (mmio_read_32(ICFG_CHIP_REVISION_ID))
|
||||
|
||||
/*******************************************************************************
|
||||
* CMIC MII (MDIO) related constant
|
||||
******************************************************************************/
|
||||
#define PLAT_CMIC_MIIM_BASE 0x68920000U
|
||||
|
||||
/*******************************************************************************
|
||||
* Timers related constants
|
||||
******************************************************************************/
|
||||
/* ChipcommonG_tim0_TIM_TIMER1Load 0x68930000 */
|
||||
#define SP804_TIMER0_BASE 0x68930000
|
||||
#define SP804_TIMER1_BASE 0x68940000
|
||||
#define SP804_TIMER0_TIMER_VAL_REG_OFFSET 0x4
|
||||
#define SP804_TIMER0_CLKMULT 2
|
||||
#define SP804_TIMER0_CLKDIV 25
|
||||
|
||||
/*******************************************************************************
|
||||
* GPIO related constants
|
||||
******************************************************************************/
|
||||
#define IPROC_GPIO_NS_BASE 0x689d0000
|
||||
#define IPROC_GPIO_S_BASE 0x68b00000
|
||||
#define IPROC_GPIO_NR 151
|
||||
#define GPIO_S_CNTRL_REG 0x68b60000
|
||||
|
||||
/*******************************************************************************
|
||||
* I2C SMBUS related constants
|
||||
******************************************************************************/
|
||||
#define SMBUS0_REGS_BASE 0x689b0000
|
||||
#define SMBUS1_REGS_BASE 0x689e0000
|
||||
|
||||
/*******************************************************************************
|
||||
* UART related constants
|
||||
******************************************************************************/
|
||||
#define ChipcommonG_UART0_UART_RBR_THR_DLL 0x68a00000
|
||||
#define ChipcommonG_UART1_UART_RBR_THR_DLL 0x68a10000
|
||||
#define ChipcommonG_UART2_UART_RBR_THR_DLL 0x68a20000
|
||||
#define ChipcommonG_UART3_UART_RBR_THR_DLL 0x68a30000
|
||||
|
||||
#define UART0_BASE_ADDR ChipcommonG_UART0_UART_RBR_THR_DLL
|
||||
#define UART1_BASE_ADDR ChipcommonG_UART1_UART_RBR_THR_DLL
|
||||
#define UART2_BASE_ADDR ChipcommonG_UART2_UART_RBR_THR_DLL
|
||||
#define UART3_BASE_ADDR ChipcommonG_UART3_UART_RBR_THR_DLL
|
||||
|
||||
#define UART_SPR_OFFSET 0x1c /* Scratch Pad Register */
|
||||
|
||||
#define LOG_LEVEL_REGISTER CRMU_SPARE_REG_3
|
||||
#define GET_LOG_LEVEL() (mmio_read_32(LOG_LEVEL_REGISTER))
|
||||
#define SET_LOG_LEVEL(x) (mmio_write_32(LOG_LEVEL_REGISTER, x))
|
||||
|
||||
#define IO_RETRY_REGISTER CRMU_SPARE_REG_4
|
||||
|
||||
#define DWC_UART_REFCLK (25 * 1000 * 1000)
|
||||
#define DWC_UART_REFCLK_DIV 16
|
||||
/* Baud rate in emulation will vary based on setting of 25MHz SCLK */
|
||||
#define DWC_UART_BAUDRATE 115200
|
||||
|
||||
#define BRCM_CRASH_CONSOLE_BASE UART1_BASE_ADDR
|
||||
#define BRCM_CRASH_CONSOLE_REFCLK DWC_UART_REFCLK
|
||||
#define BRCM_CRASH_CONSOLE_BAUDRATE DWC_UART_BAUDRATE
|
||||
|
||||
#ifdef BOARD_CONSOLE_UART
|
||||
#define PLAT_BRCM_BOOT_UART_BASE BOARD_CONSOLE_UART
|
||||
#else
|
||||
#define PLAT_BRCM_BOOT_UART_BASE UART1_BASE_ADDR
|
||||
#endif
|
||||
#define CONSOLE_UART_ID ((PLAT_BRCM_BOOT_UART_BASE >> 16) & 0x3)
|
||||
|
||||
#define PLAT_BRCM_BOOT_UART_CLK_IN_HZ DWC_UART_REFCLK
|
||||
#define BRCM_CONSOLE_BAUDRATE DWC_UART_BAUDRATE
|
||||
|
||||
#define PLAT_BRCM_BL31_RUN_UART_BASE PLAT_BRCM_BOOT_UART_BASE
|
||||
#define PLAT_BRCM_BL31_RUN_UART_CLK_IN_HZ PLAT_BRCM_BOOT_UART_CLK_IN_HZ
|
||||
|
||||
/*******************************************************************************
|
||||
* IOMUX related constants
|
||||
******************************************************************************/
|
||||
#define HSLS_IOPAD_BASE HSLS_MODE_SEL_CONTROL
|
||||
#define MODE_SEL_CONTROL_FSEL_MASK 0x7
|
||||
#define MODE_SEL_CONTROL_FSEL_MODE0 0x0
|
||||
#define MODE_SEL_CONTROL_FSEL_MODE1 0x1
|
||||
#define MODE_SEL_CONTROL_FSEL_MODE2 0x2
|
||||
#define MODE_SEL_CONTROL_FSEL_MODE3 0x3
|
||||
#define MODE_SEL_CONTROL_FSEL_DEBUG 0x4
|
||||
#define IPROC_IOPAD_MODE_BASE (HSLS_MODE_SEL_CONTROL + 0x29c)
|
||||
#define UART0_SIN_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x4a8)
|
||||
#define UART0_SOUT_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x4ac)
|
||||
#define UART1_SIN_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3b8)
|
||||
#define UART1_SOUT_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3bc)
|
||||
#define UARTx_SIN_MODE_SEL_CONTROL_FSEL 0
|
||||
#define UARTx_SOUT_MODE_SEL_CONTROL_FSEL 0
|
||||
|
||||
/*******************************************************************************
|
||||
* PKA constants
|
||||
******************************************************************************/
|
||||
#define ICFG_PKA_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xac0)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__POWERONIN BIT(0)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__POWEROKIN BIT(1)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONIN BIT(2)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKIN BIT(3)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__POWERONOUT BIT(4)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__POWEROKOUT BIT(5)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWERONOUT BIT(6)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__ARRPOWEROKOUT BIT(7)
|
||||
#define ICFG_PKA_MEM_PWR_CTRL__ISO BIT(8)
|
||||
|
||||
/*******************************************************************************
|
||||
* RNG constants
|
||||
******************************************************************************/
|
||||
#define RNG_BASE_ADDR 0x68b20000
|
||||
|
||||
/*******************************************************************************
|
||||
* Trusted Watchdog constants
|
||||
******************************************************************************/
|
||||
#define ARM_SP805_TWDG_BASE 0x68b30000
|
||||
#define ARM_SP805_TWDG_CLK_HZ ((25 * 1000 * 1000) / 2)
|
||||
/*
|
||||
* The TBBR document specifies a watchdog timeout of 256 seconds. SP805
|
||||
* asserts reset after two consecutive countdowns (2 x 128 = 256 sec)
|
||||
*/
|
||||
#define ARM_TWDG_TIMEOUT_SEC 128
|
||||
#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \
|
||||
ARM_TWDG_TIMEOUT_SEC)
|
||||
|
||||
/*******************************************************************************
|
||||
* SOTP related constants
|
||||
******************************************************************************/
|
||||
#define SOTP_REGS_OTP_BASE 0x68b50000
|
||||
#define SOTP_CHIP_CTRL (SOTP_REGS_OTP_BASE + 0x4c)
|
||||
#define SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS 0
|
||||
|
||||
/*******************************************************************************
|
||||
* DMAC/PL330 related constants
|
||||
******************************************************************************/
|
||||
#define DMAC_M0_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x408)
|
||||
#define BOOT_MANAGER_NS BIT(25)
|
||||
#define DMAC_M0_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x800)
|
||||
#define ICFG_DMAC_CONFIG_0 (HSLS_ICFG_REGS_BASE + 0x190)
|
||||
#define ICFG_DMAC_CONFIG_1 (HSLS_ICFG_REGS_BASE + 0x194)
|
||||
#define ICFG_DMAC_CONFIG_2 (HSLS_ICFG_REGS_BASE + 0x198)
|
||||
#define BOOT_PERIPHERAL_NS 0xffffffff
|
||||
#define ICFG_DMAC_CONFIG_3 (HSLS_ICFG_REGS_BASE + 0x19c)
|
||||
#define BOOT_IRQ_NS 0x0000ffff
|
||||
#define ICFG_DMAC_SID_ARADDR_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf0)
|
||||
#define ICFG_DMAC_SID_AWADDR_CONTROL (HSLS_ICFG_REGS_BASE + 0xaf4)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__POWERONIN BIT(0)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKIN BIT(1)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONIN BIT(2)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKIN BIT(3)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__POWERONOUT BIT(4)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__POWEROKOUT BIT(5)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWERONOUT BIT(6)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__ARRPOWEROKOUT BIT(7)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL__ISO BIT(8)
|
||||
#define ICFG_DMAC_MEM_PWR_CTRL (HSLS_ICFG_REGS_BASE + 0xadc)
|
||||
|
||||
/*******************************************************************************
|
||||
* PNOR related constants
|
||||
******************************************************************************/
|
||||
#define PNOR_ICFG_BASE (HSLS_ICFG_REGS_BASE + 0x780)
|
||||
#define PNOR_ICFG_CS_0 PNOR_ICFG_BASE
|
||||
#define PNOR_ICFG_CS_1 (PNOR_ICFG_BASE + 0x4)
|
||||
#define PNOR_ICFG_CS_2 (PNOR_ICFG_BASE + 0x8)
|
||||
#define PNOR_ICFG_CS_x_MASK0_MASK 0xff
|
||||
#define PNOR_ICFG_CS_x_MASK0_SHIFT 8
|
||||
#define PNOR_ICFG_CS_x_MATCH0_MASK 0xff
|
||||
#define PNOR_ICFG_CS_x_MATCH0_SHIFT 0
|
||||
|
||||
#define PNOR_IDM_BASE (HSLS_IDM_REGS_BASE + 0xb000)
|
||||
#define PNOR_IDM_IO_CONTROL_DIRECT (PNOR_IDM_BASE + 0x408)
|
||||
#define PNOR_IDM_IO_RESET_CONTROL (PNOR_IDM_BASE + 0x800)
|
||||
|
||||
#define PNOR_REG_BASE 0x68c50000
|
||||
#define PNOR_REG_DIRECT_CMD (PNOR_REG_BASE + 0x010)
|
||||
#define PNOR_REG_SET_CYCLES (PNOR_REG_BASE + 0x014)
|
||||
#define PNOR_REG_SET_OPMODE (PNOR_REG_BASE + 0x018)
|
||||
#define PNOR_REG_REFRESH_0 (PNOR_REG_BASE + 0x020)
|
||||
#define PNOR_REG_PERIPH_ID0 (PNOR_REG_BASE + 0xfe0)
|
||||
#define PNOR_REG_PERIPH_ID1 (PNOR_REG_BASE + 0xfe4)
|
||||
#define PNOR_REG_PERIPH_ID2 (PNOR_REG_BASE + 0xfe8)
|
||||
#define PNOR_REG_PERIPH_ID3 (PNOR_REG_BASE + 0xfec)
|
||||
#define PNOR_REG_PERIPH_IDx_MASK 0xff
|
||||
|
||||
/*******************************************************************************
|
||||
* NAND related constants
|
||||
******************************************************************************/
|
||||
#define NAND_FLASH_REVISION 0x68c60000
|
||||
#define NAND_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0xa408)
|
||||
#define NAND_IDM_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xa800)
|
||||
|
||||
/*******************************************************************************
|
||||
* eMMC related constants
|
||||
******************************************************************************/
|
||||
#define PLAT_SD_MAX_READ_LENGTH 0x400
|
||||
|
||||
#define SDIO0_EMMCSDXC_SYSADDR 0x68cf1000
|
||||
#define SDIO_IDM0_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x2408)
|
||||
#define SDIO_IDM1_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x3408)
|
||||
#define SDIO_IDM0_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0x2800)
|
||||
#define ICFG_SDIO0_BASE (HSLS_ICFG_REGS_BASE + 0x6e4)
|
||||
#define ICFG_SDIO1_BASE (HSLS_ICFG_REGS_BASE + 0x734)
|
||||
#define ICFG_SDIO0_CAP0 (ICFG_SDIO0_BASE + 0x10)
|
||||
#define ICFG_SDIO0_CAP1 (ICFG_SDIO0_BASE + 0x14)
|
||||
#define ICFG_SDIO0_SID (HSLS_ICFG_REGS_BASE + 0xb00)
|
||||
#define ICFG_SDIO1_SID (HSLS_ICFG_REGS_BASE + 0xb08)
|
||||
|
||||
/*******************************************************************************
|
||||
* Bootstrap related constants
|
||||
******************************************************************************/
|
||||
#define ROM_S0_IDM_IO_STATUS (HSLS_IDM_REGS_BASE + 0x9500)
|
||||
|
||||
/*******************************************************************************
|
||||
* ROM related constants
|
||||
******************************************************************************/
|
||||
#define ROM_BASE_ADDR 0x6ce00000
|
||||
#define ROM_VERSION_STRING_ADDR (ROM_BASE_ADDR + 0x28000)
|
||||
#define ROM_BUILD_MESSAGE_ADDR (ROM_BASE_ADDR + 0x28018)
|
||||
|
||||
/*******************************************************************************
|
||||
* Boot source peripheral related constants
|
||||
******************************************************************************/
|
||||
#define QSPI_CTRL_BASE_ADDR 0x68c70000
|
||||
#define QSPI_BASE_ADDR 0x70000000
|
||||
#define QSPI_SIZE 0x08000000
|
||||
#define NOR_BASE_ADDR 0x74000000
|
||||
#define NOR_SIZE 0x04000000
|
||||
#define NAND_BASE_ADDR 0x78000000
|
||||
#define NAND_SIZE 0x08000000
|
||||
|
||||
#define QSPI_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xc800)
|
||||
|
||||
#define APBR_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xe800)
|
||||
#define APBS_IDM_IDM_RESET_CONTROL (HSLS_IDM_REGS_BASE + 0xf800)
|
||||
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x10408)
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL 2
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM0_SCLK_SEL 4
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM1_SCLK_SEL 6
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM2_SCLK_SEL 8
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM3_SCLK_SEL 10
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM4_SCLK_SEL 12
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM5_SCLK_SEL 13
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM6_SCLK_SEL 14
|
||||
#define APBX_IDM_IDM_IO_CONTROL_DIRECT_TIM7_SCLK_SEL 15
|
||||
|
||||
#define APBY_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x11408)
|
||||
#define APBY_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0
|
||||
#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART0_SCLK_SEL 2
|
||||
#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART1_SCLK_SEL 4
|
||||
#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART2_SCLK_SEL 6
|
||||
#define APBY_IDM_IDM_IO_CONTROL_DIRECT_UART3_SCLK_SEL 8
|
||||
|
||||
#define APBZ_IDM_IDM_IO_CONTROL_DIRECT (HSLS_IDM_REGS_BASE + 0x12408)
|
||||
#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_CLK_ENABLE 0
|
||||
#define APBZ_IDM_IDM_IO_CONTROL_DIRECT_WDOG_SCLK_SEL 2
|
||||
|
||||
/*******************************************************************************
|
||||
* Stingray memory map related constants
|
||||
******************************************************************************/
|
||||
|
||||
/* The last 4KB of Trusted SRAM are used as shared memory */
|
||||
#define BRCM_SHARED_RAM_SIZE 0x0
|
||||
#define BRCM_SHARED_RAM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE + \
|
||||
PLAT_BRCM_TRUSTED_SRAM_SIZE - \
|
||||
BRCM_SHARED_RAM_SIZE)
|
||||
|
||||
/* Reserve 4 KB to store error logs in BL2 */
|
||||
#define BCM_ELOG_BL2_SIZE 0x00001000
|
||||
#define BCM_ELOG_BL2_BASE BL1_RW_LIMIT
|
||||
|
||||
/* The remaining Trusted SRAM is used to load the BL images */
|
||||
#define BRCM_BL_RAM_BASE (PLAT_BRCM_TRUSTED_SRAM_BASE)
|
||||
#define BRCM_BL_RAM_SIZE (PLAT_BRCM_TRUSTED_SRAM_SIZE - \
|
||||
BRCM_SHARED_RAM_SIZE)
|
||||
|
||||
/* DDR Address where TMON temperature values are written */
|
||||
#define TMON_SHARED_DDR_ADDRESS 0x8f100000
|
||||
|
||||
/* Reserve 4 kB to pass data to BL33 */
|
||||
#define BL33_SHARED_DDR_BASE 0x8f102000
|
||||
#define BL33_SHARED_DDR_SIZE 0x1000
|
||||
|
||||
/* Default AP error logging base addr */
|
||||
#ifndef ELOG_AP_UART_LOG_BASE
|
||||
#define ELOG_AP_UART_LOG_BASE 0x8f110000
|
||||
#endif
|
||||
|
||||
/* Reserve 16 to store error logs in BL31 */
|
||||
#define BCM_ELOG_BL31_BASE ELOG_AP_UART_LOG_BASE
|
||||
#define BCM_ELOG_BL31_SIZE 0x4000
|
||||
|
||||
/*******************************************************************************
|
||||
* Non-secure DDR Map
|
||||
******************************************************************************/
|
||||
#define BRCM_DRAM1_BASE ULL(0x80000000)
|
||||
#define BRCM_DRAM1_SIZE ULL(0x10000000)
|
||||
#define BRCM_DRAM2_BASE ULL(0x880000000)
|
||||
#define BRCM_DRAM2_SIZE ULL(0x780000000)
|
||||
#define BRCM_DRAM3_BASE ULL(0x8800000000)
|
||||
#define BRCM_DRAM3_SIZE ULL(0x7800000000)
|
||||
#define BRCM_SHARED_DRAM_BASE BL33_SHARED_DDR_BASE
|
||||
#define BRCM_SHARED_DRAM_SIZE BL33_SHARED_DDR_SIZE
|
||||
#define BRCM_EXT_SRAM_BASE ULL(0x74000000)
|
||||
#define BRCM_EXT_SRAM_SIZE ULL(0x4000000)
|
||||
|
||||
/* Priority levels for platforms */
|
||||
#define PLAT_RAS_PRI 0x10
|
||||
#define PLAT_SDEI_CRITICAL_PRI 0x60
|
||||
#define PLAT_SDEI_NORMAL_PRI 0x70
|
||||
|
||||
/* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 */
|
||||
#define BRCM_IRQ_SEC_SGI_0 14
|
||||
#define BRCM_IRQ_SEC_SGI_1 15
|
||||
|
||||
/* RTC periodic interrupt */
|
||||
#define BRCM_IRQ_SEC_SPI_0 49
|
||||
|
||||
/*
|
||||
* Macros for local power states in SR platforms encoded by State-ID field
|
||||
* within the power-state parameter.
|
||||
*/
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN 0
|
||||
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET 1
|
||||
|
||||
/*
|
||||
* Local power state for OFF/power-down. Valid for CPU and cluster power
|
||||
* domains.
|
||||
*/
|
||||
#define PLAT_LOCAL_STATE_OFF 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 PLAT_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 PLAT_LOCAL_STATE_OFF
|
||||
|
||||
/* ChiMP-related constants */
|
||||
|
||||
#define NITRO_TZPC_TZPCDECPROT0clr 0x60c01808
|
||||
#define NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R 1
|
||||
|
||||
#define NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT 0x60e00408
|
||||
|
||||
#define CHIMP_INDIRECT_ADDR_MASK 0x3fffff
|
||||
#define CHIMP_INDIRECT_BASE 0x60800000
|
||||
|
||||
#define CHIMP_REG_ECO_RESERVED 0x3042400
|
||||
|
||||
#define CHIMP_FLASH_ACCESS_DONE_BIT 2
|
||||
|
||||
/* indicate FRU table programming is done successfully */
|
||||
#define CHIMP_FRU_PROG_DONE_BIT 9
|
||||
|
||||
#define CHIMP_REG_CTRL_BPE_MODE_REG 0x0
|
||||
#define CHIMP_REG_CTRL_BPE_STAT_REG 0x4
|
||||
#define CHIMP_REG_CTRL_FSTBOOT_PTR_REG 0x8
|
||||
#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_L 1
|
||||
#define CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R 1
|
||||
#define CHIMP_REG_CTRL_BASE 0x3040000
|
||||
#define CHIMP_FAST_BOOT_MODE_BIT 2
|
||||
#define CHIMP_REG_CHIMP_APE_SCPAD 0x3300000
|
||||
#define CHIMP_REG_CHIMP_SCPAD 0x3100000
|
||||
|
||||
/* Chimp health status offset in scratch pad ram */
|
||||
#define CHIMP_HEALTH_STATUS_OFFSET 0x8
|
||||
/*
|
||||
* If not in NIC mode then FASTBOOT can be enabled.
|
||||
* "Not in NIC mode" means that FORCE_FASTBOOT is set
|
||||
* and a valid (1 or 2) fastboot type is specified.
|
||||
*
|
||||
* Three types of fastboot are supported:
|
||||
* 0 = No fastboot. Boots Nitro/ChiMP and lets ROM loader
|
||||
* initialize ChiMP from NVRAM (QSPI).
|
||||
*
|
||||
* 1 = Jump in place (need a flat image)
|
||||
* This is intended to speedup Nitro FW boot on Palladium,
|
||||
* can be used with a real chip as well.
|
||||
* 2 = Jump normally with decompression
|
||||
* Modus operandi for a real chip. Works also on Palladium
|
||||
* Note: image decompressing takes time on Palladium.
|
||||
* 3 = No fastboot support. No ChiMP bringup
|
||||
* (use only for AP debug or for ChiMP's deferred setup).
|
||||
*/
|
||||
#define CHIMP_FASTBOOT_JUMP_DECOMPRESS 2
|
||||
#define CHIMP_FASTBOOT_JUMP_IN_PLACE 1
|
||||
#define CHIMP_FASTBOOT_NITRO_RESET 0
|
||||
/*
|
||||
* Definitions for a non-Nitro access
|
||||
* to QSPI PAD after the handshake
|
||||
*/
|
||||
#define QSPI_HOLD_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3e8)
|
||||
#define QSPI_WP_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3ec)
|
||||
#define QSPI_SCK_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f0)
|
||||
#define QSPI_CS_N_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f4)
|
||||
#define QSPI_MOSI_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3f8)
|
||||
#define QSPI_MISO_MODE_SEL_CONTROL (HSLS_MODE_SEL_CONTROL + 0x3fc)
|
||||
|
||||
/*******************************************************************************
|
||||
* Stream IDs for different blocks of SR
|
||||
* block_id for different blocks is as follows:
|
||||
* PCIE : 0x0
|
||||
* PAXC : 0x1
|
||||
* FS4 : 0x2
|
||||
* Rest of the masters(includes MHB via RNI): 0x3
|
||||
******************************************************************************/
|
||||
#define SR_SID_VAL(block_id, subblock_id, device_num) ((block_id << 13) | \
|
||||
(subblock_id << 11) | \
|
||||
(device_num))
|
||||
|
||||
#define CRMU_STREAM_ID SR_SID_VAL(0x3, 0x0, 0x7)
|
||||
#define CRMU_SID_SHIFT 5
|
||||
|
||||
#define DMAC_STREAM_ID SR_SID_VAL(0x3, 0x0, 0x0)
|
||||
#define DMAC_SID_SHIFT 5
|
||||
|
||||
/* DDR SHMOO Values defines */
|
||||
#define IDRAM_SHMOO_VALUES_ADDR CRMU_IDRAM_BASE_ADDR
|
||||
#define DDR_SHMOO_VALUES_ADDR 0x8f103000
|
||||
#define SHMOO_SIZE_PER_CHANNEL 0x1000
|
||||
|
||||
#endif /* SR_DEF_H */
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SR_UTILS_H
|
||||
#define SR_UTILS_H
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <chip_id.h>
|
||||
#include <cmn_plat_util.h>
|
||||
#include <sr_def.h>
|
||||
|
||||
static inline void brcm_stingray_set_qspi_mux(int enable_ap)
|
||||
{
|
||||
mmio_write_32(QSPI_HOLD_N_MODE_SEL_CONTROL, enable_ap);
|
||||
mmio_write_32(QSPI_WP_N_MODE_SEL_CONTROL, enable_ap);
|
||||
mmio_write_32(QSPI_SCK_MODE_SEL_CONTROL, enable_ap);
|
||||
mmio_write_32(QSPI_CS_N_MODE_SEL_CONTROL, enable_ap);
|
||||
mmio_write_32(QSPI_MOSI_MODE_SEL_CONTROL, enable_ap);
|
||||
mmio_write_32(QSPI_MISO_MODE_SEL_CONTROL, enable_ap);
|
||||
}
|
||||
|
||||
static inline void brcm_stingray_set_straps(uint32_t boot_source)
|
||||
{
|
||||
/* Enable software strap override */
|
||||
mmio_setbits_32(CDRU_CHIP_STRAP_CTRL,
|
||||
BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE));
|
||||
|
||||
/* set straps to the next boot source */
|
||||
mmio_clrsetbits_32(CDRU_CHIP_STRAP_DATA,
|
||||
BOOT_SOURCE_MASK,
|
||||
boot_source);
|
||||
|
||||
/* Disable software strap override */
|
||||
mmio_clrbits_32(CDRU_CHIP_STRAP_CTRL,
|
||||
BIT(CDRU_CHIP_STRAP_CTRL__SOFTWARE_OVERRIDE));
|
||||
}
|
||||
|
||||
#endif
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SWREG_H
|
||||
#define SWREG_H
|
||||
|
||||
/* default voltage if no valid OTP */
|
||||
#define VDDC_CORE_DEF_VOLT 910000 /* 0.91v */
|
||||
#define IHOST_DEF_VOLT 940000 /* 0.94v */
|
||||
|
||||
#define B0_VDDC_CORE_DEF_VOLT 950000 /* 0.95v */
|
||||
#define B0_IHOST_DEF_VOLT 950000 /* 0.95v */
|
||||
#define B0_DDR_VDDC_DEF_VOLT 1000000 /* 1v */
|
||||
|
||||
#define SWREG_IHOST1_DIS 4
|
||||
#define SWREG_IHOST1_REG_RESETB 5
|
||||
#define SWREG_IHOST1_PMU_STABLE 2
|
||||
|
||||
enum sw_reg {
|
||||
DDR_VDDC = 1,
|
||||
IHOST03,
|
||||
IHOST12,
|
||||
IHOST_ARRAY,
|
||||
DDRIO_SLAVE,
|
||||
VDDC_CORE,
|
||||
VDDC1,
|
||||
DDRIO_MASTER
|
||||
};
|
||||
|
||||
int set_swreg(enum sw_reg reg_id, uint32_t micro_volts);
|
||||
int swreg_firmware_update(void);
|
||||
|
||||
#endif
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef TIMER_SYNC_H
|
||||
#define TIMER_SYNC_H
|
||||
|
||||
void brcm_timer_sync_init(void);
|
||||
|
||||
#endif
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2021, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef USB_PHY_H
|
||||
#define USB_PHY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define DRDU2_U2PLL_NDIV_FRAC_OFFSET 0x0U
|
||||
|
||||
#define DRDU2_U2PLL_NDIV_INT 0x4U
|
||||
|
||||
#define DRDU2_U2PLL_CTRL 0x8U
|
||||
#define DRDU2_U2PLL_LOCK BIT(6U)
|
||||
#define DRDU2_U2PLL_RESETB BIT(5U)
|
||||
#define DRDU2_U2PLL_PDIV_MASK 0xFU
|
||||
#define DRDU2_U2PLL_PDIV_OFFSET 1U
|
||||
#define DRDU2_U2PLL_SUSPEND_EN BIT(0U)
|
||||
|
||||
#define DRDU2_PHY_CTRL 0x0CU
|
||||
#define DRDU2_U2IDDQ BIT(30U)
|
||||
#define DRDU2_U2SOFT_RST_N BIT(29U)
|
||||
#define DRDU2_U2PHY_ON_FLAG BIT(22U)
|
||||
#define DRDU2_U2PHY_PCTL_MASK 0xFFFFU
|
||||
#define DRDU2_U2PHY_PCTL_OFFSET 6U
|
||||
#define DRDU2_U2PHY_RESETB BIT(5U)
|
||||
#define DRDU2_U2PHY_ISO BIT(4U)
|
||||
#define DRDU2_U2AFE_BG_PWRDWNB BIT(3U)
|
||||
#define DRDU2_U2AFE_PLL_PWRDWNB BIT(2U)
|
||||
#define DRDU2_U2AFE_LDO_PWRDWNB BIT(1U)
|
||||
#define DRDU2_U2CTRL_CORERDY BIT(0U)
|
||||
|
||||
#define DRDU2_STRAP_CTRL 0x18U
|
||||
#define DRDU2_FORCE_HOST_MODE BIT(5U)
|
||||
#define DRDU2_FORCE_DEVICE_MODE BIT(4U)
|
||||
#define BDC_USB_STP_SPD_MASK 0x7U
|
||||
#define BDC_USB_STP_SPD_OFFSET 0U
|
||||
|
||||
#define DRDU2_PWR_CTRL 0x1CU
|
||||
#define DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I BIT(2U)
|
||||
#define DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I BIT(1U)
|
||||
|
||||
#define DRDU2_SOFT_RESET_CTRL 0x20U
|
||||
#define DRDU2_BDC_AXI_SOFT_RST_N BIT(0U)
|
||||
|
||||
#define USB3H_U2PLL_NDIV_FRAC 0x4U
|
||||
|
||||
#define USB3H_U2PLL_NDIV_INT 0x8U
|
||||
|
||||
#define USB3H_U2PLL_CTRL 0xCU
|
||||
#define USB3H_U2PLL_LOCK BIT(6U)
|
||||
#define USB3H_U2PLL_RESETB BIT(5U)
|
||||
#define USB3H_U2PLL_PDIV_MASK 0xFU
|
||||
#define USB3H_U2PLL_PDIV_OFFSET 1U
|
||||
|
||||
#define USB3H_U2PHY_CTRL 0x10U
|
||||
#define USB3H_U2PHY_ON_FLAG 22U
|
||||
#define USB3H_U2PHY_PCTL_MASK 0xFFFFU
|
||||
#define USB3H_U2PHY_PCTL_OFFSET 6U
|
||||
#define USB3H_U2PHY_IDDQ BIT(29U)
|
||||
#define USB3H_U2PHY_RESETB BIT(5U)
|
||||
#define USB3H_U2PHY_ISO BIT(4U)
|
||||
#define USB3H_U2AFE_BG_PWRDWNB BIT(3U)
|
||||
#define USB3H_U2AFE_PLL_PWRDWNB BIT(2U)
|
||||
#define USB3H_U2AFE_LDO_PWRDWNB BIT(1U)
|
||||
#define USB3H_U2CTRL_CORERDY BIT(0U)
|
||||
|
||||
#define USB3H_U3PHY_CTRL 0x14U
|
||||
#define USB3H_U3SOFT_RST_N BIT(30U)
|
||||
#define USB3H_U3MDIO_RESETB_I BIT(29U)
|
||||
#define USB3H_U3POR_RESET_I BIT(28U)
|
||||
#define USB3H_U3PHY_PCTL_MASK 0xFFFFU
|
||||
#define USB3H_U3PHY_PCTL_OFFSET 2U
|
||||
#define USB3H_U3PHY_RESETB BIT(1U)
|
||||
|
||||
#define USB3H_U3PHY_PLL_CTRL 0x18U
|
||||
#define USB3H_U3PLL_REFCLK_MASK 0x7U
|
||||
#define USB3H_U3PLL_REFCLK_OFFSET 4U
|
||||
#define USB3H_U3PLL_SS_LOCK BIT(3U)
|
||||
#define USB3H_U3PLL_SEQ_START BIT(2U)
|
||||
#define USB3H_U3SSPLL_SUSPEND_EN BIT(1U)
|
||||
#define USB3H_U3PLL_RESETB BIT(0U)
|
||||
|
||||
#define USB3H_PWR_CTRL 0x28U
|
||||
#define USB3H_PWR_CTRL_OVERRIDE_I_R 4U
|
||||
#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN BIT(11U)
|
||||
#define USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN BIT(10U)
|
||||
|
||||
#define USB3H_SOFT_RESET_CTRL 0x2CU
|
||||
#define USB3H_XHC_AXI_SOFT_RST_N BIT(1U)
|
||||
|
||||
#define USB3H_PHY_PWR_CTRL 0x38U
|
||||
#define USB3H_DISABLE_USB30_P0 BIT(2U)
|
||||
#define USB3H_DISABLE_EUSB_P1 BIT(1U)
|
||||
#define USB3H_DISABLE_EUSB_P0 BIT(0U)
|
||||
|
||||
|
||||
#define DRDU3_U2PLL_NDIV_FRAC 0x4U
|
||||
|
||||
#define DRDU3_U2PLL_NDIV_INT 0x8U
|
||||
|
||||
#define DRDU3_U2PLL_CTRL 0xCU
|
||||
#define DRDU3_U2PLL_LOCK BIT(6U)
|
||||
#define DRDU3_U2PLL_RESETB BIT(5U)
|
||||
#define DRDU3_U2PLL_PDIV_MASK 0xFU
|
||||
#define DRDU3_U2PLL_PDIV_OFFSET 1U
|
||||
|
||||
#define DRDU3_U2PHY_CTRL 0x10U
|
||||
#define DRDU3_U2PHY_IDDQ BIT(29U)
|
||||
#define DRDU3_U2PHY_ON_FLAG BIT(22U)
|
||||
#define DRDU3_U2PHY_PCTL_MASK 0xFFFFU
|
||||
#define DRDU3_U2PHY_PCTL_OFFSET 6U
|
||||
#define DRDU3_U2PHY_RESETB BIT(5U)
|
||||
#define DRDU3_U2PHY_ISO BIT(4U)
|
||||
#define DRDU3_U2AFE_BG_PWRDWNB BIT(3U)
|
||||
#define DRDU3_U2AFE_PLL_PWRDWNB BIT(2U)
|
||||
#define DRDU3_U2AFE_LDO_PWRDWNB BIT(1U)
|
||||
#define DRDU3_U2CTRL_CORERDY BIT(0U)
|
||||
|
||||
#define DRDU3_U3PHY_CTRL 0x14U
|
||||
#define DRDU3_U3XHC_SOFT_RST_N BIT(31U)
|
||||
#define DRDU3_U3BDC_SOFT_RST_N BIT(30U)
|
||||
#define DRDU3_U3MDIO_RESETB_I BIT(29U)
|
||||
#define DRDU3_U3POR_RESET_I BIT(28U)
|
||||
#define DRDU3_U3PHY_PCTL_MASK 0xFFFFU
|
||||
#define DRDU3_U3PHY_PCTL_OFFSET 2U
|
||||
#define DRDU3_U3PHY_RESETB BIT(1U)
|
||||
|
||||
#define DRDU3_U3PHY_PLL_CTRL 0x18U
|
||||
#define DRDU3_U3PLL_REFCLK_MASK 0x7U
|
||||
#define DRDU3_U3PLL_REFCLK_OFFSET 4U
|
||||
#define DRDU3_U3PLL_SS_LOCK BIT(3U)
|
||||
#define DRDU3_U3PLL_SEQ_START BIT(2U)
|
||||
#define DRDU3_U3SSPLL_SUSPEND_EN BIT(1U)
|
||||
#define DRDU3_U3PLL_RESETB BIT(0U)
|
||||
|
||||
#define DRDU3_STRAP_CTRL 0x28U
|
||||
#define BDC_USB_STP_SPD_MASK 0x7U
|
||||
#define BDC_USB_STP_SPD_OFFSET 0U
|
||||
#define BDC_USB_STP_SPD_SS 0x0U
|
||||
#define BDC_USB_STP_SPD_HS 0x2U
|
||||
|
||||
#define DRDU3_PWR_CTRL 0x2cU
|
||||
#define DRDU3_U2PHY_DFE_SWITCH_PWROKIN BIT(12U)
|
||||
#define DRDU3_U2PHY_DFE_SWITCH_PWRONIN BIT(11U)
|
||||
#define DRDU3_PWR_CTRL_OVERRIDE_I_R 4U
|
||||
|
||||
#define DRDU3_SOFT_RESET_CTRL 0x30U
|
||||
#define DRDU3_XHC_AXI_SOFT_RST_N BIT(1U)
|
||||
#define DRDU3_BDC_AXI_SOFT_RST_N BIT(0U)
|
||||
|
||||
#define DRDU3_PHY_PWR_CTRL 0x3cU
|
||||
#define DRDU3_DISABLE_USB30_P0 BIT(2U)
|
||||
#define DRDU3_DISABLE_EUSB_P1 BIT(1U)
|
||||
#define DRDU3_DISABLE_EUSB_P0 BIT(0U)
|
||||
|
||||
#define PLL_REFCLK_PAD 0x0U
|
||||
#define PLL_REFCLK_25MHZ 0x1U
|
||||
#define PLL_REFCLK_96MHZ 0x2U
|
||||
#define PLL_REFCLK_INTERNAL 0x3U
|
||||
/* USB PLL lock time out for 10 ms */
|
||||
#define PLL_LOCK_RETRY_COUNT 10000U
|
||||
|
||||
|
||||
#define U2PLL_NDIV_INT_VAL 0x13U
|
||||
#define U2PLL_NDIV_FRAC_VAL 0x1005U
|
||||
#define U2PLL_PDIV_VAL 0x1U
|
||||
/*
|
||||
* Using external FSM
|
||||
* BIT-3:2: device mode; mode is not effect
|
||||
* BIT-1: soft reset active low
|
||||
*/
|
||||
#define U2PHY_PCTL_VAL 0x0003U
|
||||
/* Non-driving signal low */
|
||||
#define U2PHY_PCTL_NON_DRV_LOW 0x0002U
|
||||
#define U3PHY_PCTL_VAL 0x0006U
|
||||
|
||||
#define MAX_NR_PORTS 3U
|
||||
|
||||
#define USB3H_DRDU2_PHY 1U
|
||||
#define DRDU3_PHY 2U
|
||||
|
||||
#define USB_HOST_MODE 1U
|
||||
#define USB_DEV_MODE 2U
|
||||
|
||||
#define USB3SS_PORT 0U
|
||||
#define DRDU2_PORT 1U
|
||||
#define USB3HS_PORT 2U
|
||||
|
||||
#define DRD3SS_PORT 0U
|
||||
#define DRD3HS_PORT 1U
|
||||
|
||||
#define SR_USB_PHY_COUNT 2U
|
||||
|
||||
#define DRDU3_PIPE_CTRL 0x68500000U
|
||||
#define DRDU3H_XHC_REGS_CPLIVER 0x68501000U
|
||||
#define USB3H_PIPE_CTRL 0x68510000U
|
||||
#define DRD2U3H_XHC_REGS_CPLIVER 0x68511000U
|
||||
#define DRDU2_U2PLL_NDIV_FRAC 0x68520000U
|
||||
|
||||
#define AXI_DEBUG_CTRL 0x68500038U
|
||||
#define AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE BIT(12U)
|
||||
|
||||
#define USB3H_DEBUG_CTRL 0x68510034U
|
||||
#define USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE BIT(7U)
|
||||
|
||||
typedef struct _usb_phy_port usb_phy_port_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t drdu2reg;
|
||||
uint32_t usb3hreg;
|
||||
uint32_t drdu3reg;
|
||||
uint32_t phy_id;
|
||||
uint32_t ports_enabled;
|
||||
uint32_t initialized;
|
||||
usb_phy_port_t *phy_port;
|
||||
} usb_phy_t;
|
||||
|
||||
struct _usb_phy_port {
|
||||
uint32_t port_id;
|
||||
uint32_t mode;
|
||||
uint32_t enabled;
|
||||
usb_phy_t *p;
|
||||
};
|
||||
|
||||
struct u2_phy_ext_fsm {
|
||||
uint32_t pll_ctrl_reg;
|
||||
uint32_t phy_ctrl_reg;
|
||||
uint32_t phy_iddq;
|
||||
uint32_t pwr_ctrl_reg;
|
||||
uint32_t pwr_okin;
|
||||
uint32_t pwr_onin;
|
||||
};
|
||||
|
||||
#endif /* USB_PHY_H */
|
||||
@@ -0,0 +1,304 @@
|
||||
#
|
||||
# Copyright (c) 2019-2021, Broadcom
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Set the toc_flags to 1 for 100% speed operation
|
||||
# Set the toc_flags to 2 for 50% speed operation
|
||||
# Set the toc_flags to 3 for 25% speed operation
|
||||
# Set the toc_flags bit 3 to indicate ignore the fip in UEFI copy mode
|
||||
PLAT_TOC_FLAGS := 0x0
|
||||
|
||||
# Set the IHOST_PLL_FREQ to,
|
||||
# 1 for full speed
|
||||
# 2 for 50% speed
|
||||
# 3 for 25% speed
|
||||
# 0 for bypass
|
||||
$(eval $(call add_define_val,IHOST_PLL_FREQ,1))
|
||||
|
||||
# Enable workaround for ERRATA_A72_859971
|
||||
ERRATA_A72_859971 := 1
|
||||
|
||||
# Cache Coherency Interconnect Driver needed
|
||||
DRIVER_CC_ENABLE := 1
|
||||
$(eval $(call add_define,DRIVER_CC_ENABLE))
|
||||
|
||||
# Enable to erase eMMC
|
||||
INCLUDE_EMMC_DRIVER_ERASE_CODE := 0
|
||||
|
||||
ifeq (${INCLUDE_EMMC_DRIVER_ERASE_CODE},1)
|
||||
$(eval $(call add_define,INCLUDE_EMMC_DRIVER_ERASE_CODE))
|
||||
endif
|
||||
|
||||
# BL31 is in DRAM
|
||||
ARM_BL31_IN_DRAM := 1
|
||||
|
||||
ifneq (${USE_EMULATOR},yes)
|
||||
STINGRAY_EMULATION_SETUP := 0
|
||||
ifeq (${FASTBOOT_TYPE},)
|
||||
override FASTBOOT_TYPE := 0
|
||||
endif
|
||||
USE_PAXB := yes
|
||||
USE_PAXC := yes
|
||||
USE_CHIMP := yes
|
||||
endif
|
||||
|
||||
USE_CRMU_SRAM := yes
|
||||
|
||||
# Disable FS4 clocks - they can be reenabled when needed by linux
|
||||
FS4_DISABLE_CLOCK := yes
|
||||
|
||||
# Enable error logging by default for Stingray
|
||||
BCM_ELOG := yes
|
||||
|
||||
# Enable FRU support by default for Stingray
|
||||
ifeq (${USE_FRU},)
|
||||
USE_FRU := no
|
||||
endif
|
||||
|
||||
# Use single cluster
|
||||
ifeq (${USE_SINGLE_CLUSTER},yes)
|
||||
$(info Using Single Cluster)
|
||||
$(eval $(call add_define,USE_SINGLE_CLUSTER))
|
||||
endif
|
||||
|
||||
# Use DDR
|
||||
ifeq (${USE_DDR},yes)
|
||||
$(info Using DDR)
|
||||
$(eval $(call add_define,USE_DDR))
|
||||
endif
|
||||
|
||||
ifeq (${BOARD_CFG},)
|
||||
BOARD_CFG := bcm958742t
|
||||
endif
|
||||
|
||||
# Use USB
|
||||
ifeq (${USE_USB},yes)
|
||||
$(info Using USB)
|
||||
$(eval $(call add_define,USE_USB))
|
||||
endif
|
||||
|
||||
# Use PAXB
|
||||
ifeq (${USE_PAXB},yes)
|
||||
$(info Using PAXB)
|
||||
$(eval $(call add_define,USE_PAXB))
|
||||
endif
|
||||
|
||||
# Use FS4
|
||||
ifeq (${USE_FS4},yes)
|
||||
$(info Using FS4)
|
||||
$(eval $(call add_define,USE_FS4))
|
||||
endif
|
||||
|
||||
# Use FS6
|
||||
ifeq (${USE_FS6},yes)
|
||||
$(info Using FS6)
|
||||
$(eval $(call add_define,USE_FS6))
|
||||
endif
|
||||
|
||||
# Disable FS4 clock
|
||||
ifeq (${FS4_DISABLE_CLOCK},yes)
|
||||
$(info Using FS4_DISABLE_CLOCK)
|
||||
$(eval $(call add_define,FS4_DISABLE_CLOCK))
|
||||
endif
|
||||
|
||||
ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
|
||||
$(info Using NCSI_IO_DRIVE_STRENGTH_MA)
|
||||
$(eval $(call add_define,NCSI_IO_DRIVE_STRENGTH_MA))
|
||||
endif
|
||||
|
||||
# Use NAND
|
||||
ifeq (${USE_NAND},$(filter yes, ${USE_NAND}))
|
||||
$(info Using NAND)
|
||||
$(eval $(call add_define,USE_NAND))
|
||||
endif
|
||||
|
||||
# Enable Broadcom error logging support
|
||||
ifeq (${BCM_ELOG},yes)
|
||||
$(info Using BCM_ELOG)
|
||||
$(eval $(call add_define,BCM_ELOG))
|
||||
endif
|
||||
|
||||
# BL31 build for standalone mode
|
||||
ifeq (${STANDALONE_BL31},yes)
|
||||
RESET_TO_BL31 := 1
|
||||
$(info Using RESET_TO_BL31)
|
||||
endif
|
||||
|
||||
# BL31 force full frequency for all CPUs
|
||||
ifeq (${BL31_FORCE_CPU_FULL_FREQ},yes)
|
||||
$(info Using BL31_FORCE_CPU_FULL_FREQ)
|
||||
$(eval $(call add_define,BL31_FORCE_CPU_FULL_FREQ))
|
||||
endif
|
||||
|
||||
# Enable non-secure accesses to CCN registers
|
||||
ifeq (${BL31_CCN_NONSECURE},yes)
|
||||
$(info Using BL31_CCN_NONSECURE)
|
||||
$(eval $(call add_define,BL31_CCN_NONSECURE))
|
||||
endif
|
||||
|
||||
# Use ChiMP
|
||||
ifeq (${USE_CHIMP},yes)
|
||||
$(info Using ChiMP)
|
||||
$(eval $(call add_define,USE_CHIMP))
|
||||
endif
|
||||
|
||||
# Use PAXC
|
||||
ifeq (${USE_PAXC},yes)
|
||||
$(info Using PAXC)
|
||||
$(eval $(call add_define,USE_PAXC))
|
||||
ifeq (${CHIMPFW_USE_SIDELOAD},yes)
|
||||
$(info Using ChiMP FW sideload)
|
||||
$(eval $(call add_define,CHIMPFW_USE_SIDELOAD))
|
||||
endif
|
||||
$(eval $(call add_define,FASTBOOT_TYPE))
|
||||
$(eval $(call add_define,CHIMP_FB1_ENTRY))
|
||||
endif
|
||||
|
||||
ifeq (${DEFAULT_SWREG_CONFIG}, 1)
|
||||
$(eval $(call add_define,DEFAULT_SWREG_CONFIG))
|
||||
endif
|
||||
|
||||
ifeq (${CHIMP_ALWAYS_NEEDS_QSPI},yes)
|
||||
$(eval $(call add_define,CHIMP_ALWAYS_NEEDS_QSPI))
|
||||
endif
|
||||
|
||||
# For testing purposes, use memsys stubs. Remove once memsys is fully tested.
|
||||
USE_MEMSYS_STUBS := yes
|
||||
|
||||
# Default, use BL1_RW area
|
||||
ifneq (${BL2_USE_BL1_RW},no)
|
||||
$(eval $(call add_define,USE_BL1_RW))
|
||||
endif
|
||||
|
||||
# Default soft reset is L3
|
||||
$(eval $(call add_define,CONFIG_SOFT_RESET_L3))
|
||||
|
||||
# Enable Chip OTP driver
|
||||
DRIVER_OCOTP_ENABLE := 1
|
||||
|
||||
ifneq (${WARMBOOT_DDR_S3_SUPPORT},)
|
||||
DRIVER_SPI_ENABLE := 1
|
||||
endif
|
||||
|
||||
include plat/brcm/board/common/board_common.mk
|
||||
|
||||
SOC_DIR := brcm/board/stingray
|
||||
|
||||
PLAT_INCLUDES += -Iplat/${SOC_DIR}/include/ \
|
||||
-Iinclude/plat/brcm/common/ \
|
||||
-Iplat/brcm/common/
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \
|
||||
plat/${SOC_DIR}/aarch64/plat_helpers.S \
|
||||
drivers/ti/uart/aarch64/16550_console.S \
|
||||
plat/${SOC_DIR}/src/tz_sec.c \
|
||||
drivers/arm/tzc/tzc400.c \
|
||||
plat/${SOC_DIR}/driver/plat_emmc.c \
|
||||
plat/${SOC_DIR}/src/topology.c \
|
||||
drivers/brcm/mdio/mdio.c
|
||||
|
||||
ifeq (${USE_CHIMP},yes)
|
||||
PLAT_BL_COMMON_SOURCES += drivers/brcm/chimp.c
|
||||
endif
|
||||
|
||||
ifeq (${USE_USB},yes)
|
||||
PLAT_BL_COMMON_SOURCES += plat/${SOC_DIR}/driver/usb.c \
|
||||
plat/${SOC_DIR}/driver/usb_phy.c
|
||||
endif
|
||||
|
||||
BL2_SOURCES += plat/${SOC_DIR}/driver/ihost_pll_config.c \
|
||||
plat/${SOC_DIR}/src/bl2_setup.c \
|
||||
plat/${SOC_DIR}/driver/swreg.c
|
||||
|
||||
ifeq (${USE_DDR},yes)
|
||||
PLAT_INCLUDES += -Iplat/${SOC_DIR}/driver/ddr/soc/include
|
||||
else
|
||||
PLAT_INCLUDES += -Iplat/${SOC_DIR}/driver/ext_sram_init
|
||||
BL2_SOURCES += plat/${SOC_DIR}/driver/ext_sram_init/ext_sram_init.c
|
||||
endif
|
||||
|
||||
# Include GICv3 driver files
|
||||
include drivers/arm/gic/v3/gicv3.mk
|
||||
|
||||
BRCM_GIC_SOURCES := ${GICV3_SOURCES} \
|
||||
plat/common/plat_gicv3.c \
|
||||
plat/brcm/common/brcm_gicv3.c
|
||||
|
||||
BL31_SOURCES += \
|
||||
drivers/arm/ccn/ccn.c \
|
||||
plat/brcm/board/common/timer_sync.c \
|
||||
plat/brcm/common/brcm_ccn.c \
|
||||
plat/common/plat_psci_common.c \
|
||||
plat/${SOC_DIR}/driver/ihost_pll_config.c \
|
||||
plat/${SOC_DIR}/src/bl31_setup.c \
|
||||
plat/${SOC_DIR}/src/fsx.c \
|
||||
plat/${SOC_DIR}/src/iommu.c \
|
||||
plat/${SOC_DIR}/src/sdio.c \
|
||||
${BRCM_GIC_SOURCES}
|
||||
|
||||
ifneq (${NCSI_IO_DRIVE_STRENGTH_MA},)
|
||||
BL31_SOURCES += plat/${SOC_DIR}/src/ncsi.c
|
||||
endif
|
||||
|
||||
ifeq (${USE_PAXB},yes)
|
||||
BL31_SOURCES += plat/${SOC_DIR}/src/paxb.c
|
||||
BL31_SOURCES += plat/${SOC_DIR}/src/sr_paxb_phy.c
|
||||
endif
|
||||
|
||||
ifeq (${USE_PAXC},yes)
|
||||
BL31_SOURCES += plat/${SOC_DIR}/src/paxc.c
|
||||
endif
|
||||
|
||||
ifdef SCP_BL2
|
||||
PLAT_INCLUDES += -Iplat/brcm/common/
|
||||
|
||||
BL2_SOURCES += plat/brcm/common/brcm_mhu.c \
|
||||
plat/brcm/common/brcm_scpi.c \
|
||||
plat/${SOC_DIR}/src/scp_utils.c \
|
||||
plat/${SOC_DIR}/src/scp_cmd.c \
|
||||
drivers/brcm/scp.c
|
||||
|
||||
BL31_SOURCES += plat/brcm/common/brcm_mhu.c \
|
||||
plat/brcm/common/brcm_scpi.c \
|
||||
plat/${SOC_DIR}/src/brcm_pm_ops.c
|
||||
else
|
||||
BL31_SOURCES += plat/${SOC_DIR}/src/ihost_pm.c \
|
||||
plat/${SOC_DIR}/src/pm.c
|
||||
endif
|
||||
|
||||
ifeq (${ELOG_SUPPORT},1)
|
||||
ifeq (${ELOG_STORE_MEDIA},DDR)
|
||||
BL2_SOURCES += plat/brcm/board/common/bcm_elog_ddr.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${BL31_BOOT_PRELOADED_SCP}, 1)
|
||||
ifdef SCP_BL2
|
||||
SCP_CFG_DIR=$(dir ${SCP_BL2})
|
||||
PLAT_INCLUDES += -I${SCP_CFG_DIR}
|
||||
endif
|
||||
PLAT_INCLUDES += -Iplat/brcm/common/
|
||||
|
||||
# By default use OPTEE Assigned memory
|
||||
PRELOADED_SCP_BASE ?= 0x8E000000
|
||||
PRELOADED_SCP_SIZE ?= 0x10000
|
||||
$(eval $(call add_define,PRELOADED_SCP_BASE))
|
||||
$(eval $(call add_define,PRELOADED_SCP_SIZE))
|
||||
$(eval $(call add_define,BL31_BOOT_PRELOADED_SCP))
|
||||
BL31_SOURCES += plat/${SOC_DIR}/src/scp_utils.c \
|
||||
plat/${SOC_DIR}/src/scp_cmd.c \
|
||||
drivers/brcm/scp.c
|
||||
endif
|
||||
|
||||
# Do not execute the startup code on warm reset.
|
||||
PROGRAMMABLE_RESET_ADDRESS := 1
|
||||
|
||||
# Nitro FW, config and Crash log uses secure DDR memory
|
||||
# Inaddition to above, Nitro master and slave is also secure
|
||||
ifneq ($(NITRO_SECURE_ACCESS),)
|
||||
$(eval $(call add_define,NITRO_SECURE_ACCESS))
|
||||
$(eval $(call add_define,DDR_NITRO_SECURE_REGION_START))
|
||||
$(eval $(call add_define,DDR_NITRO_SECURE_REGION_END))
|
||||
endif
|
||||
+743
@@ -0,0 +1,743 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/sp805.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <chimp.h>
|
||||
#include <chip_id.h>
|
||||
#include <cmn_plat_util.h>
|
||||
#include <dmu.h>
|
||||
#include <emmc_api.h>
|
||||
#include <fru.h>
|
||||
#ifdef USE_GPIO
|
||||
#include <drivers/gpio.h>
|
||||
#include <iproc_gpio.h>
|
||||
#endif
|
||||
#include <platform_def.h>
|
||||
#include <sotp.h>
|
||||
#include <swreg.h>
|
||||
#include <sr_utils.h>
|
||||
#ifdef USE_DDR
|
||||
#include <ddr_init.h>
|
||||
#else
|
||||
#include <ext_sram_init.h>
|
||||
#endif
|
||||
#if DRIVER_OCOTP_ENABLE
|
||||
#include <ocotp.h>
|
||||
#endif
|
||||
#include "board_info.h"
|
||||
|
||||
#define WORD_SIZE 8
|
||||
#define SWREG_AVS_OTP_OFFSET (13 * WORD_SIZE) /* 13th row byte offset */
|
||||
#define AON_GPIO_OTP_OFFSET (28 * WORD_SIZE) /* 28th row byte offset */
|
||||
#define BYTES_TO_READ 8
|
||||
|
||||
/* OTP voltage step definitions */
|
||||
#define MVOLT_STEP_MAX 0x18 /* 1v */
|
||||
#define MVOLT_PER_STEP 10 /* 0.01mv per step */
|
||||
#define MVOLT_BASE 760 /* 0.76v */
|
||||
|
||||
#define STEP_TO_UVOLTS(step) \
|
||||
((MVOLT_BASE + (MVOLT_PER_STEP * (step))) * 1000)
|
||||
|
||||
#define GET_BITS(first, last, data) \
|
||||
((data >> first) & ((1 << (last - first + 1)) - 1))
|
||||
|
||||
/*
|
||||
* SW-REG OTP encoding:
|
||||
*
|
||||
* SWREG_bits[11:0] = OTP 13th row 12 bits[55:44]
|
||||
* SWREG_bits[11:10] - Valid Bits (0x2 - valid, if not 0x2 - Invalid)
|
||||
* SWREG_bits[9:5] - iHost03, iHost12
|
||||
* SWREG_bits[4:0] - Core VDDC
|
||||
*/
|
||||
#define SWREG_OTP_BITS_START 12 /* 44th bit in MSB 32-bits */
|
||||
#define SWREG_OTP_BITS_END 23 /* 55th bit in MSB 32-bits */
|
||||
#define SWREG_VDDC_FIELD_START 0
|
||||
#define SWREG_VDDC_FIELD_END 4
|
||||
#define SWREG_IHOST_FIELD_START 5
|
||||
#define SWREG_IHOST_FIELD_END 9
|
||||
#define SWREG_VALID_BIT_START 10
|
||||
#define SWREG_VALID_BIT_END 11
|
||||
#define SWREG_VALID_BITS 0x2
|
||||
|
||||
/*
|
||||
* Row 13 bit 56 is programmed as '1' today. It is not being used, so plan
|
||||
* is to flip this bit to '0' for B1 rev. Hence SW can leverage this bit
|
||||
* to identify Bx chip to program different sw-regulators.
|
||||
*/
|
||||
#define SPARE_BIT 24
|
||||
|
||||
#define IS_SR_B0(data) (((data) >> SPARE_BIT) & 0x1)
|
||||
|
||||
#if DRIVER_OCOTP_ENABLE
|
||||
static struct otpc_map otp_stingray_map = {
|
||||
.otpc_row_size = 2,
|
||||
.data_r_offset = {0x10, 0x5c},
|
||||
.data_w_offset = {0x2c, 0x64},
|
||||
.word_size = 8,
|
||||
.stride = 8,
|
||||
};
|
||||
#endif
|
||||
|
||||
void plat_bcm_bl2_early_platform_setup(void)
|
||||
{
|
||||
/* Select UART0 for AP via mux setting*/
|
||||
if (PLAT_BRCM_BOOT_UART_BASE == UART0_BASE_ADDR) {
|
||||
mmio_write_32(UART0_SIN_MODE_SEL_CONTROL, 1);
|
||||
mmio_write_32(UART0_SOUT_MODE_SEL_CONTROL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_NAND
|
||||
static void brcm_stingray_nand_init(void)
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned int nand_idm_reset_control = 0x68e0a800;
|
||||
|
||||
VERBOSE(" stingray nand init start.\n");
|
||||
|
||||
/* Reset NAND */
|
||||
VERBOSE(" - reset nand\n");
|
||||
val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0));
|
||||
mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val | 0x1);
|
||||
udelay(500);
|
||||
val = mmio_read_32((uintptr_t)(nand_idm_reset_control + 0x0));
|
||||
mmio_write_32((uintptr_t)(nand_idm_reset_control + 0x0), val & ~0x1);
|
||||
udelay(500);
|
||||
|
||||
VERBOSE(" stingray nand init done.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA)
|
||||
#define PCIE_RESCAL_CFG_0 0x40000130
|
||||
#define PCIE_CFG_RESCAL_RSTB_R (1 << 16)
|
||||
#define PCIE_CFG_RESCAL_PWRDNB_R (1 << 8)
|
||||
#define PCIE_RESCAL_STATUS_0 0x4000014c
|
||||
#define PCIE_STAT_PON_VALID_R (1 << 0)
|
||||
#define PCIE_RESCAL_OUTPUT_STATUS 0x40000154
|
||||
#define CDRU_PCIE_RESET_N_R (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R)
|
||||
|
||||
#ifdef EMULATION_SETUP
|
||||
static void brcm_stingray_pcie_reset(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
static void brcm_stingray_pcie_reset(void)
|
||||
{
|
||||
unsigned int data;
|
||||
int try;
|
||||
|
||||
if (bcm_chimp_is_nic_mode()) {
|
||||
INFO("NIC mode detected; PCIe reset/rescal not executed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mmio_clrbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R);
|
||||
mmio_setbits_32(CDRU_MISC_RESET_CONTROL, CDRU_PCIE_RESET_N_R);
|
||||
/* Release reset */
|
||||
mmio_setbits_32(PCIE_RESCAL_CFG_0, PCIE_CFG_RESCAL_RSTB_R);
|
||||
mdelay(1);
|
||||
/* Power UP */
|
||||
mmio_setbits_32(PCIE_RESCAL_CFG_0,
|
||||
(PCIE_CFG_RESCAL_RSTB_R | PCIE_CFG_RESCAL_PWRDNB_R));
|
||||
|
||||
try = 1000;
|
||||
do {
|
||||
udelay(1);
|
||||
data = mmio_read_32(PCIE_RESCAL_STATUS_0);
|
||||
try--;
|
||||
} while ((data & PCIE_STAT_PON_VALID_R) == 0x0 && (try > 0));
|
||||
|
||||
if (try <= 0)
|
||||
ERROR("PCIE_RESCAL_STATUS_0: 0x%x\n", data);
|
||||
|
||||
VERBOSE("PCIE_SATA_RESCAL_STATUS_0 0x%x.\n",
|
||||
mmio_read_32(PCIE_RESCAL_STATUS_0));
|
||||
VERBOSE("PCIE_SATA_RESCAL_OUTPUT_STATUS 0x%x.\n",
|
||||
mmio_read_32(PCIE_RESCAL_OUTPUT_STATUS));
|
||||
INFO("PCIE SATA Rescal Init done\n");
|
||||
}
|
||||
#endif /* EMULATION_SETUP */
|
||||
#endif /* USE_PAXB || USE_PAXC || USE_SATA */
|
||||
|
||||
#ifdef USE_PAXC
|
||||
void brcm_stingray_chimp_check_and_fastboot(void)
|
||||
{
|
||||
int fastboot_init_result;
|
||||
|
||||
if (bcm_chimp_is_nic_mode())
|
||||
/* Do not wait here */
|
||||
return;
|
||||
|
||||
#if WARMBOOT_DDR_S3_SUPPORT
|
||||
/*
|
||||
* Currently DDR shmoo parameters and QSPI boot source are
|
||||
* tied. DDR shmoo parameters are stored in QSPI, which is
|
||||
* used for warmboot.
|
||||
* Do not reset nitro for warmboot
|
||||
*/
|
||||
if (is_warmboot() && (boot_source_get() == BOOT_SOURCE_QSPI))
|
||||
return;
|
||||
#endif /* WARMBOOT_DDR_S3_SUPPORT */
|
||||
|
||||
/*
|
||||
* Not in NIC mode,
|
||||
* initiate fastboot (if enabled)
|
||||
*/
|
||||
if (FASTBOOT_TYPE == CHIMP_FASTBOOT_NITRO_RESET) {
|
||||
|
||||
VERBOSE("Bring up Nitro/ChiMP\n");
|
||||
|
||||
if (boot_source_get() == BOOT_SOURCE_QSPI)
|
||||
WARN("Nitro boots from QSPI when AP has booted from QSPI.\n");
|
||||
brcm_stingray_set_qspi_mux(0);
|
||||
VERBOSE("Nitro controls the QSPI\n");
|
||||
}
|
||||
|
||||
fastboot_init_result = bcm_chimp_initiate_fastboot(FASTBOOT_TYPE);
|
||||
if (fastboot_init_result && boot_source_get() != BOOT_SOURCE_QSPI)
|
||||
ERROR("Nitro init error %d. Status: 0x%x; bpe_mod reg: 0x%x\n"
|
||||
"fastboot register: 0x%x; handshake register 0x%x\n",
|
||||
fastboot_init_result,
|
||||
bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG),
|
||||
bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG),
|
||||
bcm_chimp_read_ctrl(CHIMP_REG_CTRL_FSTBOOT_PTR_REG),
|
||||
bcm_chimp_read(CHIMP_REG_ECO_RESERVED));
|
||||
|
||||
/*
|
||||
* CRMU watchdog kicks is an example, which is L1 reset,
|
||||
* does not clear Nitro scratch pad ram.
|
||||
* For Nitro resets: Clear the Nitro health status memory.
|
||||
*/
|
||||
bcm_chimp_write((CHIMP_REG_CHIMP_SCPAD + CHIMP_HEALTH_STATUS_OFFSET),
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_ihost_vddc_swreg(uint32_t ihost_uvolts, uint32_t vddc_uvolts)
|
||||
{
|
||||
NOTICE("ihost_uvolts: %duv, vddc_uvolts: %duv\n",
|
||||
ihost_uvolts, vddc_uvolts);
|
||||
|
||||
set_swreg(VDDC_CORE, vddc_uvolts);
|
||||
set_swreg(IHOST03, ihost_uvolts);
|
||||
set_swreg(IHOST12, ihost_uvolts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads SWREG AVS OTP bits (13th row) with ECC enabled and get voltage
|
||||
* defined in OTP if valid OTP is found
|
||||
*/
|
||||
void read_avs_otp_bits(uint32_t *ihost_uvolts, uint32_t *vddc_uvolts)
|
||||
{
|
||||
uint32_t offset = SWREG_AVS_OTP_OFFSET;
|
||||
uint32_t ihost_step, vddc_step;
|
||||
uint32_t avs_bits;
|
||||
uint32_t buf[2];
|
||||
|
||||
if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1)
|
||||
return;
|
||||
|
||||
VERBOSE("AVS OTP %d ROW: 0x%x.0x%x\n",
|
||||
offset/WORD_SIZE, buf[1], buf[0]);
|
||||
|
||||
/* get voltage readings from AVS OTP bits */
|
||||
avs_bits = GET_BITS(SWREG_OTP_BITS_START,
|
||||
SWREG_OTP_BITS_END,
|
||||
buf[1]);
|
||||
|
||||
/* check for valid otp bits */
|
||||
if (GET_BITS(SWREG_VALID_BIT_START, SWREG_VALID_BIT_END, avs_bits) !=
|
||||
SWREG_VALID_BITS) {
|
||||
WARN("Invalid AVS OTP bits at %d row\n", offset/WORD_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get ihost and vddc step value */
|
||||
vddc_step = GET_BITS(SWREG_VDDC_FIELD_START,
|
||||
SWREG_VDDC_FIELD_END,
|
||||
avs_bits);
|
||||
|
||||
ihost_step = GET_BITS(SWREG_IHOST_FIELD_START,
|
||||
SWREG_IHOST_FIELD_END,
|
||||
avs_bits);
|
||||
|
||||
if ((ihost_step > MVOLT_STEP_MAX) || (vddc_step > MVOLT_STEP_MAX)) {
|
||||
WARN("OTP entry invalid\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get voltage in micro-volts */
|
||||
*ihost_uvolts = STEP_TO_UVOLTS(ihost_step);
|
||||
*vddc_uvolts = STEP_TO_UVOLTS(vddc_step);
|
||||
}
|
||||
|
||||
/*
|
||||
* This api reads otp bits and program internal swreg's - ihos12, ihost03,
|
||||
* vddc_core and ddr_core based on different chip. External swreg's
|
||||
* programming will be done from crmu.
|
||||
*
|
||||
* For A2 chip:
|
||||
* Read OTP row 20, bit 50. This bit will be set for A2 chip. Once A2 chip is
|
||||
* found, read AVS OTP row 13, 12bits[55:44], if valid otp bits are found
|
||||
* then set ihost and vddc according to avs otp bits else set them to 0.94v
|
||||
* and 0.91v respectively. Also update the firmware after setting voltage.
|
||||
*
|
||||
* For B0 chip:
|
||||
* Read OTP row 13, bit 56. This bit will be set for B0 chip. Once B0 chip is
|
||||
* found then set ihost and vddc to 0.95v and ddr_core to 1v. No AVS OTP bits
|
||||
* are used get ihost/vddc voltages.
|
||||
*
|
||||
* For B1 chip:
|
||||
* Read AVS OTP row 13, 12bits[55:44], if valid otp bits are found then set
|
||||
* ihost and vddc according to avs otp bits else set them to 0.94v and 0.91v
|
||||
* respectively.
|
||||
*/
|
||||
void set_swreg_based_on_otp(void)
|
||||
{
|
||||
/* default voltage if no valid OTP */
|
||||
uint32_t vddc_uvolts = VDDC_CORE_DEF_VOLT;
|
||||
uint32_t ihost_uvolts = IHOST_DEF_VOLT;
|
||||
uint32_t ddrc_uvolts;
|
||||
uint32_t offset;
|
||||
uint32_t buf[2];
|
||||
|
||||
offset = SWREG_AVS_OTP_OFFSET;
|
||||
if (bcm_otpc_read(offset, &buf[0], BYTES_TO_READ, 1) == -1)
|
||||
return;
|
||||
|
||||
VERBOSE("OTP %d ROW: 0x%x.0x%x\n",
|
||||
offset/WORD_SIZE, buf[1], buf[0]);
|
||||
|
||||
if (IS_SR_B0(buf[1])) {
|
||||
/* don't read AVS OTP for B0 */
|
||||
ihost_uvolts = B0_IHOST_DEF_VOLT;
|
||||
vddc_uvolts = B0_VDDC_CORE_DEF_VOLT;
|
||||
ddrc_uvolts = B0_DDR_VDDC_DEF_VOLT;
|
||||
} else {
|
||||
read_avs_otp_bits(&ihost_uvolts, &vddc_uvolts);
|
||||
}
|
||||
|
||||
#if (IHOST_REG_TYPE == IHOST_REG_INTEGRATED) && \
|
||||
(VDDC_REG_TYPE == VDDC_REG_INTEGRATED)
|
||||
/* enable IHOST12 cluster before changing voltage */
|
||||
NOTICE("Switching on the Regulator idx: %u\n",
|
||||
SWREG_IHOST1_DIS);
|
||||
mmio_clrsetbits_32(CRMU_SWREG_CTRL_ADDR,
|
||||
BIT(SWREG_IHOST1_DIS),
|
||||
BIT(SWREG_IHOST1_REG_RESETB));
|
||||
|
||||
/* wait for regulator supply gets stable */
|
||||
while (!(mmio_read_32(CRMU_SWREG_STATUS_ADDR) &
|
||||
(1 << SWREG_IHOST1_PMU_STABLE)))
|
||||
;
|
||||
|
||||
INFO("Regulator supply got stable\n");
|
||||
|
||||
#ifndef DEFAULT_SWREG_CONFIG
|
||||
swreg_firmware_update();
|
||||
#endif
|
||||
|
||||
set_ihost_vddc_swreg(ihost_uvolts, vddc_uvolts);
|
||||
#endif
|
||||
if (IS_SR_B0(buf[1])) {
|
||||
NOTICE("ddrc_uvolts: %duv\n", ddrc_uvolts);
|
||||
set_swreg(DDR_VDDC, ddrc_uvolts);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DDR
|
||||
static struct ddr_info ddr_info;
|
||||
#endif
|
||||
#ifdef USE_FRU
|
||||
static struct fru_area_info fru_area[FRU_MAX_NR_AREAS];
|
||||
static struct fru_board_info board_info;
|
||||
static struct fru_time fru_tm;
|
||||
static uint8_t fru_tbl[BCM_MAX_FRU_LEN];
|
||||
|
||||
static void board_detect_fru(void)
|
||||
{
|
||||
uint32_t i, result;
|
||||
int ret = -1;
|
||||
|
||||
result = bcm_emmc_init(false);
|
||||
if (!result) {
|
||||
ERROR("eMMC init failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* go through eMMC boot partitions looking for FRU table */
|
||||
for (i = EMMC_BOOT_PARTITION1; i <= EMMC_BOOT_PARTITION2; i++) {
|
||||
result = emmc_partition_select(i);
|
||||
if (!result) {
|
||||
ERROR("Switching to eMMC part %u failed\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
result = emmc_read(BCM_FRU_TBL_OFFSET, (uintptr_t)fru_tbl,
|
||||
BCM_MAX_FRU_LEN, BCM_MAX_FRU_LEN);
|
||||
if (!result) {
|
||||
ERROR("Failed to read from eMMC part %u\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run sanity check and checksum to make sure valid FRU table
|
||||
* is detected
|
||||
*/
|
||||
ret = fru_validate(fru_tbl, fru_area);
|
||||
if (ret < 0) {
|
||||
WARN("FRU table not found in eMMC part %u\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse DDR information from FRU table */
|
||||
ret = fru_parse_ddr(fru_tbl, &fru_area[FRU_AREA_INTERNAL],
|
||||
&ddr_info);
|
||||
if (ret < 0) {
|
||||
WARN("No FRU DDR info found in eMMC part %u\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse board information from FRU table */
|
||||
ret = fru_parse_board(fru_tbl, &fru_area[FRU_AREA_BOARD_INFO],
|
||||
&board_info);
|
||||
if (ret < 0) {
|
||||
WARN("No FRU board info found in eMMC part %u\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if we reach here, valid FRU table is parsed */
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
WARN("FRU table missing for this board\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < BCM_MAX_NR_DDR; i++) {
|
||||
INFO("DDR channel index: %d\n", ddr_info.mcb[i].idx);
|
||||
INFO("DDR size %u GB\n", ddr_info.mcb[i].size_mb / 1024);
|
||||
INFO("DDR ref ID by SW (Not MCB Ref ID) 0x%x\n",
|
||||
ddr_info.mcb[i].ref_id);
|
||||
}
|
||||
|
||||
fru_format_time(board_info.mfg_date, &fru_tm);
|
||||
|
||||
INFO("**** FRU board information ****\n");
|
||||
INFO("Language 0x%x\n", board_info.lang);
|
||||
INFO("Manufacturing Date %u.%02u.%02u, %02u:%02u\n",
|
||||
fru_tm.year, fru_tm.month, fru_tm.day,
|
||||
fru_tm.hour, fru_tm.min);
|
||||
INFO("Manufacturing Date(Raw) 0x%x\n", board_info.mfg_date);
|
||||
INFO("Manufacturer %s\n", board_info.manufacturer);
|
||||
INFO("Product Name %s\n", board_info.product_name);
|
||||
INFO("Serial number %s\n", board_info.serial_number);
|
||||
INFO("Part number %s\n", board_info.part_number);
|
||||
INFO("File ID %s\n", board_info.file_id);
|
||||
}
|
||||
#endif /* USE_FRU */
|
||||
|
||||
#ifdef USE_GPIO
|
||||
|
||||
#define INVALID_GPIO 0xffff
|
||||
|
||||
static const int gpio_cfg_bitmap[MAX_NR_GPIOS] = {
|
||||
#ifdef BRD_DETECT_GPIO_BIT0
|
||||
BRD_DETECT_GPIO_BIT0,
|
||||
#else
|
||||
INVALID_GPIO,
|
||||
#endif
|
||||
#ifdef BRD_DETECT_GPIO_BIT1
|
||||
BRD_DETECT_GPIO_BIT1,
|
||||
#else
|
||||
INVALID_GPIO,
|
||||
#endif
|
||||
#ifdef BRD_DETECT_GPIO_BIT2
|
||||
BRD_DETECT_GPIO_BIT2,
|
||||
#else
|
||||
INVALID_GPIO,
|
||||
#endif
|
||||
#ifdef BRD_DETECT_GPIO_BIT3
|
||||
BRD_DETECT_GPIO_BIT3,
|
||||
#else
|
||||
INVALID_GPIO,
|
||||
#endif
|
||||
};
|
||||
|
||||
static uint8_t gpio_bitmap;
|
||||
|
||||
/*
|
||||
* Use an odd number to avoid potential conflict with public GPIO level
|
||||
* defines
|
||||
*/
|
||||
#define GPIO_STATE_FLOAT 15
|
||||
|
||||
/*
|
||||
* If GPIO_SUPPORT_FLOAT_DETECTION is disabled, simply return GPIO level
|
||||
*
|
||||
* If GPIO_SUPPORT_FLOAT_DETECTION is enabled, add additional test for possible
|
||||
* pin floating (unconnected) scenario. This support is assuming externally
|
||||
* applied pull up / pull down will have a stronger pull than the internal pull
|
||||
* up / pull down.
|
||||
*/
|
||||
static uint8_t gpio_get_state(int gpio)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
/* set direction to GPIO input */
|
||||
gpio_set_direction(gpio, GPIO_DIR_IN);
|
||||
|
||||
#ifndef GPIO_SUPPORT_FLOAT_DETECTION
|
||||
if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH)
|
||||
val = GPIO_LEVEL_HIGH;
|
||||
else
|
||||
val = GPIO_LEVEL_LOW;
|
||||
|
||||
return val;
|
||||
#else
|
||||
/*
|
||||
* Enable internal pull down. If GPIO level is still high, there must
|
||||
* be an external pull up
|
||||
*/
|
||||
gpio_set_pull(gpio, GPIO_PULL_DOWN);
|
||||
if (gpio_get_value(gpio) == GPIO_LEVEL_HIGH) {
|
||||
val = GPIO_LEVEL_HIGH;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable internal pull up. If GPIO level is still low, there must
|
||||
* be an external pull down
|
||||
*/
|
||||
gpio_set_pull(gpio, GPIO_PULL_UP);
|
||||
if (gpio_get_value(gpio) == GPIO_LEVEL_LOW) {
|
||||
val = GPIO_LEVEL_LOW;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* if reached here, the pin must be not connected */
|
||||
val = GPIO_STATE_FLOAT;
|
||||
|
||||
exit:
|
||||
/* make sure internall pull is disabled */
|
||||
if (gpio_get_pull(gpio) != GPIO_PULL_NONE)
|
||||
gpio_set_pull(gpio, GPIO_PULL_NONE);
|
||||
|
||||
return val;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void board_detect_gpio(void)
|
||||
{
|
||||
unsigned int i, val;
|
||||
int gpio;
|
||||
|
||||
iproc_gpio_init(IPROC_GPIO_S_BASE, IPROC_GPIO_NR,
|
||||
IPROC_IOPAD_MODE_BASE, HSLS_IOPAD_BASE);
|
||||
|
||||
gpio_bitmap = 0;
|
||||
for (i = 0; i < MAX_NR_GPIOS; i++) {
|
||||
if (gpio_cfg_bitmap[i] == INVALID_GPIO)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Construct the bitmap based on GPIO value. Floating pin
|
||||
* detection is a special case. As soon as a floating pin is
|
||||
* detected, a special value of MAX_GPIO_BITMAP_VAL is
|
||||
* assigned and we break out of the loop immediately
|
||||
*/
|
||||
gpio = gpio_cfg_bitmap[i];
|
||||
val = gpio_get_state(gpio);
|
||||
if (val == GPIO_STATE_FLOAT) {
|
||||
gpio_bitmap = MAX_GPIO_BITMAP_VAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == GPIO_LEVEL_HIGH)
|
||||
gpio_bitmap |= BIT(i);
|
||||
}
|
||||
|
||||
memcpy(&ddr_info, &gpio_ddr_info[gpio_bitmap], sizeof(ddr_info));
|
||||
INFO("Board detection GPIO bitmap = 0x%x\n", gpio_bitmap);
|
||||
}
|
||||
#endif /* USE_GPIO */
|
||||
|
||||
static void bcm_board_detect(void)
|
||||
{
|
||||
#ifdef DDR_LEGACY_MCB_SUPPORTED
|
||||
/* Loading default DDR info */
|
||||
memcpy(&ddr_info, &default_ddr_info, sizeof(ddr_info));
|
||||
#endif
|
||||
#ifdef USE_FRU
|
||||
board_detect_fru();
|
||||
#endif
|
||||
#ifdef USE_GPIO
|
||||
board_detect_gpio();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dump_persistent_regs(void)
|
||||
{
|
||||
NOTICE("pr0: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG0));
|
||||
NOTICE("pr1: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG1));
|
||||
NOTICE("pr2: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG2));
|
||||
NOTICE("pr3: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG3));
|
||||
NOTICE("pr4: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG4));
|
||||
NOTICE("pr5: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG5));
|
||||
NOTICE("pr6: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG6));
|
||||
NOTICE("pr7: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG7));
|
||||
NOTICE("pr8: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG8));
|
||||
NOTICE("pr9: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
|
||||
NOTICE("pr10: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG10));
|
||||
NOTICE("pr11: %x\n", mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG11));
|
||||
}
|
||||
|
||||
void plat_bcm_bl2_plat_arch_setup(void)
|
||||
{
|
||||
if (chip_get_rev_id_major() == CHIP_REV_MAJOR_AX) {
|
||||
if (!(sotp_mem_read(SOTP_ATF_CFG_ROW_ID, SOTP_ROW_NO_ECC) &
|
||||
SOTP_ATF_WATCHDOG_ENABLE_MASK)) {
|
||||
/*
|
||||
* Stop sp805 watchdog timer immediately.
|
||||
* It might has been set up by MCU patch earlier for
|
||||
* eMMC workaround.
|
||||
*
|
||||
* Note the watchdog timer started in CRMU has a very
|
||||
* short timeout and needs to be stopped immediately.
|
||||
* Down below we restart it with a much longer timeout
|
||||
* for BL2 and BL31
|
||||
*/
|
||||
sp805_stop(ARM_SP805_TWDG_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
#if !BRCM_DISABLE_TRUSTED_WDOG
|
||||
/*
|
||||
* start secure watchdog for BL2 and BL31.
|
||||
* Note that UART download can take a longer time,
|
||||
* so do not allow watchdog for UART download,
|
||||
* as this boot source is not a standard modus operandi.
|
||||
*/
|
||||
if (boot_source_get() != BOOT_SOURCE_UART)
|
||||
sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
|
||||
#endif
|
||||
|
||||
#ifdef BCM_ELOG
|
||||
/* Ensure logging is started out fresh in BL2. */
|
||||
mmio_write_32(BCM_ELOG_BL2_BASE, 0);
|
||||
#endif
|
||||
/*
|
||||
* In BL2, since we have very limited space to store logs, we only
|
||||
* save logs that are >= the WARNING level.
|
||||
*/
|
||||
bcm_elog_init((void *)BCM_ELOG_BL2_BASE, BCM_ELOG_BL2_SIZE,
|
||||
LOG_LEVEL_WARNING);
|
||||
|
||||
dump_persistent_regs();
|
||||
|
||||
/* Read CRMU mailbox 0 */
|
||||
NOTICE("RESET (reported by CRMU): 0x%x\n",
|
||||
mmio_read_32(CRMU_READ_MAIL_BOX0));
|
||||
|
||||
/*
|
||||
* All non-boot-source PADs are in forced input-mode at
|
||||
* reset so clear the force on non-boot-source PADs using
|
||||
* CDRU register.
|
||||
*/
|
||||
mmio_clrbits_32((uintptr_t)CDRU_CHIP_IO_PAD_CONTROL,
|
||||
(1 << CDRU_CHIP_IO_PAD_CONTROL__CDRU_IOMUX_FORCE_PAD_IN_R));
|
||||
|
||||
#if DRIVER_OCOTP_ENABLE
|
||||
bcm_otpc_init(&otp_stingray_map);
|
||||
#endif
|
||||
|
||||
set_swreg_based_on_otp();
|
||||
|
||||
#if IHOST_PLL_FREQ != 0
|
||||
bcm_set_ihost_pll_freq(0x0, IHOST_PLL_FREQ);
|
||||
#endif
|
||||
|
||||
#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
|
||||
/* The erasable unit of the eMMC is the "Erase Group";
|
||||
* Erase group is measured in write blocks which are the
|
||||
* basic writable units of the Device.
|
||||
* The size of the Erase Group is a Device specific parameter
|
||||
*/
|
||||
emmc_erase(EMMC_ERASE_START_BLOCK, EMMC_ERASE_BLOCK_COUNT,
|
||||
EMMC_ERASE_PARTITION);
|
||||
#endif
|
||||
|
||||
bcm_board_detect();
|
||||
#ifdef DRIVER_EMMC_ENABLE
|
||||
/* Initialize the card, if it is not */
|
||||
if (bcm_emmc_init(true) == 0)
|
||||
WARN("eMMC Card Initialization Failed!!!\n");
|
||||
#endif
|
||||
|
||||
#if BL2_TEST_I2C
|
||||
i2c_test();
|
||||
#endif
|
||||
|
||||
#ifdef USE_DDR
|
||||
ddr_initialize(&ddr_info);
|
||||
|
||||
ddr_secure_region_config(SECURE_DDR_BASE_ADDRESS,
|
||||
SECURE_DDR_END_ADDRESS);
|
||||
#ifdef NITRO_SECURE_ACCESS
|
||||
ddr_secure_region_config(DDR_NITRO_SECURE_REGION_START,
|
||||
DDR_NITRO_SECURE_REGION_END);
|
||||
#endif
|
||||
#else
|
||||
ext_sram_init();
|
||||
#endif
|
||||
|
||||
#if BL2_TEST_MEM
|
||||
ddr_test();
|
||||
#endif
|
||||
|
||||
#ifdef USE_NAND
|
||||
brcm_stingray_nand_init();
|
||||
#endif
|
||||
|
||||
#if defined(USE_PAXB) || defined(USE_PAXC) || defined(USE_SATA)
|
||||
brcm_stingray_pcie_reset();
|
||||
#endif
|
||||
|
||||
#ifdef USE_PAXC
|
||||
if (boot_source_get() != BOOT_SOURCE_QSPI)
|
||||
brcm_stingray_chimp_check_and_fastboot();
|
||||
#endif
|
||||
|
||||
#if ((!CLEAN_DDR || MMU_DISABLED))
|
||||
/*
|
||||
* Now DDR has been initialized. We want to copy all the logs in SRAM
|
||||
* into DDR so we will have much more space to store the logs in the
|
||||
* next boot stage
|
||||
*/
|
||||
bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE,
|
||||
MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE)
|
||||
);
|
||||
|
||||
/*
|
||||
* We are not yet at the end of BL2, but we can stop log here so we do
|
||||
* not need to add 'bcm_elog_exit' to the standard BL2 code. The
|
||||
* benefit of capturing BL2 logs after this is very minimal in a
|
||||
* production system
|
||||
* NOTE: BL2 logging must be exited before going forward to setup
|
||||
* page tables
|
||||
*/
|
||||
bcm_elog_exit();
|
||||
#endif
|
||||
}
|
||||
+1071
File diff suppressed because it is too large
Load Diff
+408
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/ccn.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/spinlock.h>
|
||||
|
||||
#include <brcm_scpi.h>
|
||||
#include <chimp.h>
|
||||
#include <cmn_plat_util.h>
|
||||
#include <plat_brcm.h>
|
||||
#include <platform_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
#include "m0_cfg.h"
|
||||
|
||||
|
||||
#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
|
||||
#define CLUSTER_PWR_STATE(state) \
|
||||
((state)->pwr_domain_state[MPIDR_AFFLVL1])
|
||||
#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL2])
|
||||
|
||||
#define VENDOR_RST_TYPE_SHIFT 4
|
||||
|
||||
#if HW_ASSISTED_COHERENCY
|
||||
/*
|
||||
* On systems where participant CPUs are cache-coherent, we can use spinlocks
|
||||
* instead of bakery locks.
|
||||
*/
|
||||
spinlock_t event_lock;
|
||||
#define event_lock_get(_lock) spin_lock(&_lock)
|
||||
#define event_lock_release(_lock) spin_unlock(&_lock)
|
||||
|
||||
#else
|
||||
/*
|
||||
* Use bakery locks for state coordination as not all participants are
|
||||
* cache coherent now.
|
||||
*/
|
||||
DEFINE_BAKERY_LOCK(event_lock);
|
||||
#define event_lock_get(_lock) bakery_lock_get(&_lock)
|
||||
#define event_lock_release(_lock) bakery_lock_release(&_lock)
|
||||
#endif
|
||||
|
||||
static int brcm_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
/*
|
||||
* SCP takes care of powering up parent power domains so we
|
||||
* only need to care about level 0
|
||||
*/
|
||||
scpi_set_brcm_power_state(mpidr, scpi_power_on, scpi_power_on,
|
||||
scpi_power_on);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler called when a power level 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. This handler would never be invoked with
|
||||
* the system power domain uninitialized as either the primary would have taken
|
||||
* care of it as part of cold boot or the first core awakened from system
|
||||
* suspend would have already initialized it.
|
||||
******************************************************************************/
|
||||
static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
|
||||
|
||||
/* Assert that the system power domain need not be initialized */
|
||||
assert(SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_RUN);
|
||||
|
||||
assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
/*
|
||||
* Perform the common cluster specific operations i.e enable coherency
|
||||
* if this cluster was off.
|
||||
*/
|
||||
if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) {
|
||||
INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
|
||||
ccn_enter_snoop_dvm_domain(1 << cluster_id);
|
||||
}
|
||||
|
||||
/* Program the gic per-cpu distributor or re-distributor interface */
|
||||
plat_brcm_gic_pcpu_init();
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
plat_brcm_gic_cpuif_enable();
|
||||
}
|
||||
|
||||
static void brcm_power_down_common(void)
|
||||
{
|
||||
unsigned int standbywfil2, standbywfi;
|
||||
uint64_t mpidr = read_mpidr_el1();
|
||||
|
||||
switch (MPIDR_AFFLVL1_VAL(mpidr)) {
|
||||
case 0x0:
|
||||
standbywfi = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI;
|
||||
standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2;
|
||||
break;
|
||||
case 0x1:
|
||||
standbywfi = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI;
|
||||
standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2;
|
||||
break;
|
||||
case 0x2:
|
||||
standbywfi = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI;
|
||||
standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2;
|
||||
break;
|
||||
case 0x3:
|
||||
standbywfi = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI;
|
||||
standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2;
|
||||
break;
|
||||
default:
|
||||
ERROR("Invalid cluster #%" PRIx64 "\n", MPIDR_AFFLVL1_VAL(mpidr));
|
||||
return;
|
||||
}
|
||||
/* Clear the WFI status bit */
|
||||
event_lock_get(event_lock);
|
||||
mmio_setbits_32(CDRU_PROC_EVENT_CLEAR,
|
||||
(1 << (standbywfi + MPIDR_AFFLVL0_VAL(mpidr))) |
|
||||
(1 << standbywfil2));
|
||||
event_lock_release(event_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to inform power down state to SCP.
|
||||
*/
|
||||
static void brcm_scp_suspend(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint32_t cluster_state = scpi_power_on;
|
||||
uint32_t system_state = scpi_power_on;
|
||||
|
||||
/* Check if power down at system power domain level is requested */
|
||||
if (SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
|
||||
system_state = scpi_power_retention;
|
||||
|
||||
/* Check if Cluster is to be turned off */
|
||||
if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
|
||||
cluster_state = scpi_power_off;
|
||||
|
||||
/*
|
||||
* Ask the SCP to power down the appropriate components depending upon
|
||||
* their state.
|
||||
*/
|
||||
scpi_set_brcm_power_state(read_mpidr_el1(),
|
||||
scpi_power_off,
|
||||
cluster_state,
|
||||
system_state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to turn off a CPU power domain and its parent power domains
|
||||
* if applicable. Since SCPI doesn't differentiate between OFF and suspend, we
|
||||
* call the suspend helper here.
|
||||
*/
|
||||
static void brcm_scp_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
brcm_scp_suspend(target_state);
|
||||
}
|
||||
|
||||
static void brcm_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr_el1());
|
||||
|
||||
assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF);
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
plat_brcm_gic_cpuif_disable();
|
||||
|
||||
/* Turn redistributor off */
|
||||
plat_brcm_gic_redistif_off();
|
||||
|
||||
/* If Cluster is to be turned off, disable coherency */
|
||||
if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF)
|
||||
ccn_exit_snoop_dvm_domain(1 << cluster_id);
|
||||
|
||||
brcm_power_down_common();
|
||||
|
||||
brcm_scp_off(target_state);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Handler called when the CPU power domain is about to enter standby.
|
||||
******************************************************************************/
|
||||
static void brcm_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
unsigned int scr;
|
||||
|
||||
assert(cpu_state == PLAT_LOCAL_STATE_RET);
|
||||
|
||||
scr = read_scr_el3();
|
||||
/*
|
||||
* Enable the Non secure interrupt to wake the CPU.
|
||||
* In GICv3 affinity routing mode, the non secure group1 interrupts use
|
||||
* the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ.
|
||||
* Enabling both the bits works for both GICv2 mode and GICv3 affinity
|
||||
* routing mode.
|
||||
*/
|
||||
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
|
||||
isb();
|
||||
dsb();
|
||||
wfi();
|
||||
|
||||
/*
|
||||
* Restore SCR to the original value, synchronisation of scr_el3 is
|
||||
* done by eret while el3_exit to save some execution cycles.
|
||||
*/
|
||||
write_scr_el3(scr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to shutdown the system via SCPI.
|
||||
*/
|
||||
static void __dead2 brcm_scp_sys_shutdown(void)
|
||||
{
|
||||
/*
|
||||
* Disable GIC CPU interface to prevent pending interrupt
|
||||
* from waking up the AP from WFI.
|
||||
*/
|
||||
plat_brcm_gic_cpuif_disable();
|
||||
|
||||
/* Flush and invalidate data cache */
|
||||
dcsw_op_all(DCCISW);
|
||||
|
||||
/* Bring Cluster out of coherency domain as its going to die */
|
||||
plat_brcm_interconnect_exit_coherency();
|
||||
|
||||
brcm_power_down_common();
|
||||
|
||||
/* Send the power down request to the SCP */
|
||||
scpi_sys_power_state(scpi_system_shutdown);
|
||||
|
||||
wfi();
|
||||
ERROR("BRCM System Off: operation not handled.\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to reset the system
|
||||
*/
|
||||
static void __dead2 brcm_scp_sys_reset(unsigned int reset_type)
|
||||
{
|
||||
/*
|
||||
* Disable GIC CPU interface to prevent pending interrupt
|
||||
* from waking up the AP from WFI.
|
||||
*/
|
||||
plat_brcm_gic_cpuif_disable();
|
||||
|
||||
/* Flush and invalidate data cache */
|
||||
dcsw_op_all(DCCISW);
|
||||
|
||||
/* Bring Cluster out of coherency domain as its going to die */
|
||||
plat_brcm_interconnect_exit_coherency();
|
||||
|
||||
brcm_power_down_common();
|
||||
|
||||
/* Send the system reset request to the SCP
|
||||
*
|
||||
* As per PSCI spec system power state could be
|
||||
* 0-> Shutdown
|
||||
* 1-> Reboot- Board level Reset
|
||||
* 2-> Reset - SoC level Reset
|
||||
*
|
||||
* Spec allocates 8 bits, 2 nibble, for this. One nibble is sufficient
|
||||
* for sending the state hence We are utilizing 2nd nibble for vendor
|
||||
* define reset type.
|
||||
*/
|
||||
scpi_sys_power_state((reset_type << VENDOR_RST_TYPE_SHIFT) |
|
||||
scpi_system_reboot);
|
||||
|
||||
wfi();
|
||||
ERROR("BRCM System Reset: operation not handled.\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 brcm_system_reset(void)
|
||||
{
|
||||
unsigned int reset_type;
|
||||
|
||||
if (bcm_chimp_is_nic_mode())
|
||||
reset_type = SOFT_RESET_L3;
|
||||
else
|
||||
reset_type = SOFT_SYS_RESET_L1;
|
||||
|
||||
brcm_scp_sys_reset(reset_type);
|
||||
}
|
||||
|
||||
static int brcm_system_reset2(int is_vendor, int reset_type,
|
||||
u_register_t cookie)
|
||||
{
|
||||
if (!is_vendor) {
|
||||
/* Architectural warm boot: only warm reset is supported */
|
||||
reset_type = SOFT_RESET_L3;
|
||||
} else {
|
||||
uint32_t boot_source = (uint32_t)cookie;
|
||||
|
||||
boot_source &= BOOT_SOURCE_MASK;
|
||||
brcm_stingray_set_straps(boot_source);
|
||||
}
|
||||
brcm_scp_sys_reset(reset_type);
|
||||
|
||||
/*
|
||||
* brcm_scp_sys_reset cannot return (it is a __dead function),
|
||||
* but brcm_system_reset2 has to return some value, even in
|
||||
* this case.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcm_validate_ns_entrypoint(uintptr_t entrypoint)
|
||||
{
|
||||
/*
|
||||
* Check if the non secure entrypoint lies within the non
|
||||
* secure DRAM.
|
||||
*/
|
||||
if ((entrypoint >= BRCM_NS_DRAM1_BASE) &&
|
||||
(entrypoint < (BRCM_NS_DRAM1_BASE + BRCM_NS_DRAM1_SIZE)))
|
||||
return PSCI_E_SUCCESS;
|
||||
#ifdef __aarch64__
|
||||
if ((entrypoint >= BRCM_DRAM2_BASE) &&
|
||||
(entrypoint < (BRCM_DRAM2_BASE + BRCM_DRAM2_SIZE)))
|
||||
return PSCI_E_SUCCESS;
|
||||
|
||||
if ((entrypoint >= BRCM_DRAM3_BASE) &&
|
||||
(entrypoint < (BRCM_DRAM3_BASE + BRCM_DRAM3_SIZE)))
|
||||
return PSCI_E_SUCCESS;
|
||||
#endif
|
||||
|
||||
return PSCI_E_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* ARM standard platform handler called to check the validity of the power state
|
||||
* parameter.
|
||||
******************************************************************************/
|
||||
static int brcm_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
int pstate = psci_get_pstate_type(power_state);
|
||||
int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
|
||||
int i;
|
||||
|
||||
assert(req_state);
|
||||
|
||||
if (pwr_lvl > PLAT_MAX_PWR_LVL)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
/* Sanity check the requested state */
|
||||
if (pstate == PSTATE_TYPE_STANDBY) {
|
||||
/*
|
||||
* It's possible to enter standby only on power level 0
|
||||
* Ignore any other power level.
|
||||
*/
|
||||
if (pwr_lvl != MPIDR_AFFLVL0)
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
req_state->pwr_domain_state[MPIDR_AFFLVL0] =
|
||||
PLAT_LOCAL_STATE_RET;
|
||||
} else {
|
||||
for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
|
||||
req_state->pwr_domain_state[i] =
|
||||
PLAT_LOCAL_STATE_OFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* We expect the 'state id' to be zero.
|
||||
*/
|
||||
if (psci_get_pstate_id(power_state))
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
|
||||
* platform will take care of registering the handlers with PSCI.
|
||||
******************************************************************************/
|
||||
plat_psci_ops_t plat_brcm_psci_pm_ops = {
|
||||
.pwr_domain_on = brcm_pwr_domain_on,
|
||||
.pwr_domain_on_finish = brcm_pwr_domain_on_finish,
|
||||
.pwr_domain_off = brcm_pwr_domain_off,
|
||||
.cpu_standby = brcm_cpu_standby,
|
||||
.system_off = brcm_scp_sys_shutdown,
|
||||
.system_reset = brcm_system_reset,
|
||||
.system_reset2 = brcm_system_reset2,
|
||||
.validate_ns_entrypoint = brcm_validate_ns_entrypoint,
|
||||
.validate_power_state = brcm_validate_power_state,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const struct plat_psci_ops **psci_ops)
|
||||
{
|
||||
*psci_ops = &plat_brcm_psci_pm_ops;
|
||||
|
||||
/* Setup mailbox with entry point. */
|
||||
mmio_write_64(CRMU_CFG_BASE + offsetof(M0CFG, core_cfg.rvbar),
|
||||
sec_entrypoint);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
#include <fsx.h>
|
||||
#include <platform_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN 0
|
||||
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON 11
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK 12
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON 13
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK 14
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO 15
|
||||
#define FS4_IDM_IO_CONTROL_DIRECT__CLK_EN 31
|
||||
|
||||
#define FS4_IDM_IO_STATUS__MEM_POWERON 0
|
||||
#define FS4_IDM_IO_STATUS__MEM_POWEROK 1
|
||||
#define FS4_IDM_IO_STATUS__MEM_ARRPOWERON 2
|
||||
#define FS4_IDM_IO_STATUS__MEM_ARRPOWEROK 3
|
||||
#define FS4_IDM_IO_STATUS__MEM_ALLOK 0xf
|
||||
|
||||
#define FS4_IDM_RESET_CONTROL__RESET 0
|
||||
|
||||
#define FSX_RINGx_BASE(__b, __i) \
|
||||
((__b) + (__i) * 0x10000)
|
||||
|
||||
#define FSX_RINGx_VERSION_NUMBER(__b, __i) \
|
||||
(FSX_RINGx_BASE(__b, __i) + 0x0)
|
||||
|
||||
#define FSX_RINGx_MSI_DEV_ID(__b, __i) \
|
||||
(FSX_RINGx_BASE(__b, __i) + 0x44)
|
||||
|
||||
#define FSX_COMM_RINGx_BASE(__b, __i) \
|
||||
((__b) + 0x200000 + (__i) * 0x100)
|
||||
|
||||
#define FSX_COMM_RINGx_CONTROL(__b, __i) \
|
||||
(FSX_COMM_RINGx_BASE(__b, __i) + 0x0)
|
||||
#define FSX_COMM_RINGx_CONTROL__AXI_ID 8
|
||||
#define FSX_COMM_RINGx_CONTROL__AXI_ID_MASK 0x1f
|
||||
#define FSX_COMM_RINGx_CONTROL__PRIORITY 4
|
||||
#define FSX_COMM_RINGx_CONTROL__PRIORITY_MASK 0x7
|
||||
#define FSX_COMM_RINGx_CONTROL__AE_GROUP 0
|
||||
#define FSX_COMM_RINGx_CONTROL__AE_GROUP_MASK 0x7
|
||||
|
||||
#define FSX_COMM_RINGx_MSI_DEV_ID(__b, __i) \
|
||||
(FSX_COMM_RINGx_BASE(__b, __i) + 0x4)
|
||||
|
||||
#define FSX_AEx_BASE(__b, __i) \
|
||||
((__b) + 0x202000 + (__i) * 0x100)
|
||||
|
||||
#define FSX_AEx_CONTROL_REGISTER(__b, __i) \
|
||||
(FSX_AEx_BASE(__b, __i) + 0x0)
|
||||
#define FSX_AEx_CONTROL_REGISTER__ACTIVE 4
|
||||
#define FSX_AEx_CONTROL_REGISTER__GROUP_ID 0
|
||||
#define FSX_AEx_CONTROL_REGISTER__GROUP_ID_MASK 0x7
|
||||
|
||||
#define FSX_COMM_RM_RING_SECURITY_SETTING 0x0
|
||||
|
||||
#define FSX_COMM_RM_SSID_CONTROL 0x4
|
||||
#define FSX_COMM_RM_SSID_CONTROL__RING_BITS 5
|
||||
#define FSX_COMM_RM_SSID_CONTROL__MASK 0x3ff
|
||||
|
||||
#define FSX_COMM_RM_CONTROL_REGISTER 0x8
|
||||
#define FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE 2
|
||||
#define FSX_COMM_RM_CONTROL_REGISTER__AE_TIMEOUT 5
|
||||
#define FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING 7
|
||||
|
||||
#define FSX_COMM_RM_TIMER_CONTROL_0 0xc
|
||||
#define FSX_COMM_RM_TIMER_CONTROL_0__FAST 16
|
||||
#define FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM 0
|
||||
|
||||
#define FSX_COMM_RM_TIMER_CONTROL_1 0x10
|
||||
#define FSX_COMM_RM_TIMER_CONTROL_1__SLOW 16
|
||||
#define FSX_COMM_RM_TIMER_CONTROL_1__IDLE 0
|
||||
|
||||
#define FSX_COMM_RM_BURST_BD_THRESHOLD 0x14
|
||||
#define FSX_COMM_RM_BURST_BD_THRESHOLD_LOW 0
|
||||
#define FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH 16
|
||||
|
||||
#define FSX_COMM_RM_BURST_LENGTH 0x18
|
||||
#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN 16
|
||||
#define FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN_MASK 0x1ff
|
||||
#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE 0
|
||||
#define FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE_MASK 0x1ff
|
||||
|
||||
#define FSX_COMM_RM_FIFO_THRESHOLD 0x1c
|
||||
#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL 16
|
||||
#define FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL_MASK 0x1ff
|
||||
#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL 0
|
||||
#define FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL_MASK 0x1f
|
||||
|
||||
#define FSX_COMM_RM_AE_TIMEOUT 0x24
|
||||
|
||||
#define FSX_COMM_RM_RING_FLUSH_TIMEOUT 0x2c
|
||||
|
||||
#define FSX_COMM_RM_MEMORY_CONFIGURATION 0x30
|
||||
#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN 12
|
||||
#define FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN 13
|
||||
#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN 14
|
||||
#define FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN 15
|
||||
|
||||
#define FSX_COMM_RM_AXI_CONTROL 0x34
|
||||
#define FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN 28
|
||||
#define FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN 24
|
||||
#define FSX_COMM_RM_AXI_CONTROL__AWQOS 20
|
||||
#define FSX_COMM_RM_AXI_CONTROL__ARQOS 16
|
||||
#define FSX_COMM_RM_AXI_CONTROL__AWPROT 12
|
||||
#define FSX_COMM_RM_AXI_CONTROL__ARPROT 8
|
||||
#define FSX_COMM_RM_AXI_CONTROL__AWCACHE 4
|
||||
#define FSX_COMM_RM_AXI_CONTROL__ARCACHE 0
|
||||
|
||||
#define FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR 0x48
|
||||
|
||||
#define FSX_COMM_RM_GROUP_PKT_EXTENSION_SUPPORT 0xc0
|
||||
|
||||
#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD 0xc8
|
||||
#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MASK 0x1ff
|
||||
#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX 16
|
||||
#define FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN 0
|
||||
|
||||
#define FSX_COMM_RM_GROUP_RING_COUNT 0xcc
|
||||
|
||||
#define FSX_COMM_RM_MAIN_HW_INIT_DONE 0x12c
|
||||
#define FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK 0x1
|
||||
|
||||
#define FSX_DMEx_BASE(__b, __i) \
|
||||
((__b) + (__i) * 0x1000)
|
||||
|
||||
#define FSX_DMEx_AXI_CONTROL(__b, __i) \
|
||||
(FSX_DMEx_BASE(__b, __i) + 0x4)
|
||||
#define FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN 28
|
||||
#define FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN 24
|
||||
#define FSX_DMEx_AXI_CONTROL__AWQOS 20
|
||||
#define FSX_DMEx_AXI_CONTROL__ARQOS 16
|
||||
#define FSX_DMEx_AXI_CONTROL__AWCACHE 4
|
||||
#define FSX_DMEx_AXI_CONTROL__ARCACHE 0
|
||||
|
||||
#define FSX_DMEx_WR_FIFO_THRESHOLD(__b, __i) \
|
||||
(FSX_DMEx_BASE(__b, __i) + 0xc)
|
||||
#define FSX_DMEx_WR_FIFO_THRESHOLD__MASK 0x3ff
|
||||
#define FSX_DMEx_WR_FIFO_THRESHOLD__MAX 10
|
||||
#define FSX_DMEx_WR_FIFO_THRESHOLD__MIN 0
|
||||
|
||||
#define FSX_DMEx_RD_FIFO_THRESHOLD(__b, __i) \
|
||||
(FSX_DMEx_BASE(__b, __i) + 0x14)
|
||||
#define FSX_DMEx_RD_FIFO_THRESHOLD__MASK 0x3ff
|
||||
#define FSX_DMEx_RD_FIFO_THRESHOLD__MAX 10
|
||||
#define FSX_DMEx_RD_FIFO_THRESHOLD__MIN 0
|
||||
|
||||
#define FS6_SUB_TOP_BASE 0x66D8F800
|
||||
#define FS6_PKI_DME_RESET 0x4
|
||||
#define PKI_DME_RESET 1
|
||||
|
||||
char *fsx_type_names[] = {
|
||||
"fs4-raid",
|
||||
"fs4-crypto",
|
||||
"fs6-pki",
|
||||
};
|
||||
|
||||
void fsx_init(eFSX_TYPE fsx_type,
|
||||
unsigned int ring_count,
|
||||
unsigned int dme_count,
|
||||
unsigned int ae_count,
|
||||
unsigned int start_stream_id,
|
||||
unsigned int msi_dev_id,
|
||||
uintptr_t idm_io_control_direct,
|
||||
uintptr_t idm_reset_control,
|
||||
uintptr_t base,
|
||||
uintptr_t dme_base)
|
||||
{
|
||||
int try;
|
||||
unsigned int i, v, data;
|
||||
uintptr_t fs4_idm_io_control_direct = idm_io_control_direct;
|
||||
uintptr_t fs4_idm_reset_control = idm_reset_control;
|
||||
uintptr_t fsx_comm_rm = (base + 0x203000);
|
||||
|
||||
VERBOSE("fsx %s init start\n", fsx_type_names[fsx_type]);
|
||||
|
||||
if (fsx_type == eFS4_RAID || fsx_type == eFS4_CRYPTO) {
|
||||
/* Enable FSx engine clock */
|
||||
VERBOSE(" - enable fsx clock\n");
|
||||
mmio_write_32(fs4_idm_io_control_direct,
|
||||
(1U << FS4_IDM_IO_CONTROL_DIRECT__CLK_EN));
|
||||
udelay(500);
|
||||
|
||||
/* Reset FSx engine */
|
||||
VERBOSE(" - reset fsx\n");
|
||||
v = mmio_read_32(fs4_idm_reset_control);
|
||||
v |= (1 << FS4_IDM_RESET_CONTROL__RESET);
|
||||
mmio_write_32(fs4_idm_reset_control, v);
|
||||
udelay(500);
|
||||
v = mmio_read_32(fs4_idm_reset_control);
|
||||
v &= ~(1 << FS4_IDM_RESET_CONTROL__RESET);
|
||||
mmio_write_32(fs4_idm_reset_control, v);
|
||||
} else {
|
||||
/*
|
||||
* Default RM and AE are out of reset,
|
||||
* So only DME Reset added here
|
||||
*/
|
||||
v = mmio_read_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET);
|
||||
v &= ~(PKI_DME_RESET);
|
||||
mmio_write_32(FS6_SUB_TOP_BASE + FS6_PKI_DME_RESET, v);
|
||||
}
|
||||
|
||||
/* Wait for HW-init done */
|
||||
VERBOSE(" - wait for HW-init done\n");
|
||||
try = 10000;
|
||||
do {
|
||||
udelay(1);
|
||||
data = mmio_read_32(fsx_comm_rm +
|
||||
FSX_COMM_RM_MAIN_HW_INIT_DONE);
|
||||
try--;
|
||||
} while (!(data & FSX_COMM_RM_MAIN_HW_INIT_DONE__MASK) && (try > 0));
|
||||
|
||||
if (try <= 0)
|
||||
ERROR("fsx_comm_rm + 0x%x: 0x%x\n",
|
||||
data, FSX_COMM_RM_MAIN_HW_INIT_DONE);
|
||||
|
||||
/* Make all rings non-secured */
|
||||
VERBOSE(" - make all rings non-secured\n");
|
||||
v = 0xffffffff;
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_SECURITY_SETTING, v);
|
||||
|
||||
/* Set start stream-id for rings to */
|
||||
VERBOSE(" - set start stream-id for rings to 0x%x\n",
|
||||
start_stream_id);
|
||||
v = start_stream_id >> FSX_COMM_RM_SSID_CONTROL__RING_BITS;
|
||||
v &= FSX_COMM_RM_SSID_CONTROL__MASK;
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_SSID_CONTROL, v);
|
||||
|
||||
/* Set timer configuration */
|
||||
VERBOSE(" - set timer configuration\n");
|
||||
v = 0x0271 << FSX_COMM_RM_TIMER_CONTROL_0__MEDIUM;
|
||||
v |= (0x0138 << FSX_COMM_RM_TIMER_CONTROL_0__FAST);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_0, v);
|
||||
v = 0x09c4 << FSX_COMM_RM_TIMER_CONTROL_1__IDLE;
|
||||
v |= (0x04e2 << FSX_COMM_RM_TIMER_CONTROL_1__SLOW);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_TIMER_CONTROL_1, v);
|
||||
v = 0x0000f424;
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_RING_FLUSH_TIMEOUT, v);
|
||||
|
||||
/* Set burst length and fifo threshold */
|
||||
VERBOSE(" - set burst length, fifo and bd threshold\n");
|
||||
v = 0x0;
|
||||
v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_DDR_ADDR_GEN);
|
||||
v |= (0x8 << FSX_COMM_RM_BURST_LENGTH__FOR_TOGGLE);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_LENGTH, v);
|
||||
v = 0x0;
|
||||
v |= (0x67 << FSX_COMM_RM_FIFO_THRESHOLD__BD_FIFO_FULL);
|
||||
v |= (0x18 << FSX_COMM_RM_FIFO_THRESHOLD__AE_FIFO_FULL);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_FIFO_THRESHOLD, v);
|
||||
v = 0x0;
|
||||
v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_LOW);
|
||||
v |= (0x8 << FSX_COMM_RM_BURST_BD_THRESHOLD_HIGH);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_BURST_BD_THRESHOLD, v);
|
||||
|
||||
/* Set memory configuration */
|
||||
VERBOSE(" - set memory configuration\n");
|
||||
v = 0x0;
|
||||
v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWERONIN);
|
||||
v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__POWEROKIN);
|
||||
v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWERONIN);
|
||||
v |= (1 << FSX_COMM_RM_MEMORY_CONFIGURATION__ARRPOWEROKIN);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_MEMORY_CONFIGURATION, v);
|
||||
|
||||
/* AXI configuration for RM */
|
||||
v = 0;
|
||||
v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__WRITE_CHANNEL_EN);
|
||||
v |= (0x1 << FSX_COMM_RM_AXI_CONTROL__READ_CHANNEL_EN);
|
||||
v |= (0xe << FSX_COMM_RM_AXI_CONTROL__AWQOS);
|
||||
v |= (0xa << FSX_COMM_RM_AXI_CONTROL__ARQOS);
|
||||
v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__AWPROT);
|
||||
v |= (0x2 << FSX_COMM_RM_AXI_CONTROL__ARPROT);
|
||||
v |= (0xf << FSX_COMM_RM_AXI_CONTROL__AWCACHE);
|
||||
v |= (0xf << FSX_COMM_RM_AXI_CONTROL__ARCACHE);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL, v);
|
||||
VERBOSE(" - set AXI control = 0x%x\n",
|
||||
mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_CONTROL));
|
||||
v = 0x0;
|
||||
v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MAX);
|
||||
v |= (0x10 << FSX_COMM_RM_AXI_READ_BURST_THRESHOLD__MIN);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD, v);
|
||||
VERBOSE(" - set AXI read burst threshold = 0x%x\n",
|
||||
mmio_read_32(fsx_comm_rm + FSX_COMM_RM_AXI_READ_BURST_THRESHOLD));
|
||||
|
||||
/* Configure group ring count for all groups */
|
||||
/* By default we schedule extended packets
|
||||
* on all AEs/DMEs in a group.
|
||||
*/
|
||||
v = (dme_count & 0xf) << 0;
|
||||
v |= (dme_count & 0xf) << 4;
|
||||
v |= (dme_count & 0xf) << 8;
|
||||
v |= (dme_count & 0xf) << 12;
|
||||
v |= (dme_count & 0xf) << 16;
|
||||
v |= (dme_count & 0xf) << 20;
|
||||
v |= (dme_count & 0xf) << 24;
|
||||
v |= (dme_count & 0xf) << 28;
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_GROUP_RING_COUNT, v);
|
||||
|
||||
/*
|
||||
* Due to HW issue spurious interrupts are getting generated.
|
||||
* To fix sw needs to clear the config status interrupts
|
||||
* before setting CONFIG_DONE.
|
||||
*/
|
||||
mmio_write_32(fsx_comm_rm +
|
||||
FSX_COMM_RM_CONFIG_INTERRUPT_STATUS_CLEAR,
|
||||
0xffffffff);
|
||||
|
||||
/* Configure RM control */
|
||||
VERBOSE(" - configure RM control\n");
|
||||
v = mmio_read_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER);
|
||||
v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__AE_LOCKING);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
|
||||
v |= (1 << FSX_COMM_RM_CONTROL_REGISTER__CONFIG_DONE);
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_CONTROL_REGISTER, v);
|
||||
|
||||
/* Configure AE timeout */
|
||||
VERBOSE(" - configure AE timeout\n");
|
||||
v = 0x00003fff;
|
||||
mmio_write_32(fsx_comm_rm + FSX_COMM_RM_AE_TIMEOUT, v);
|
||||
|
||||
/* Initialize all AEs */
|
||||
for (i = 0; i < ae_count; i++) {
|
||||
VERBOSE(" - initialize AE%d\n", i);
|
||||
v = (0x1 << FSX_AEx_CONTROL_REGISTER__ACTIVE);
|
||||
mmio_write_32(FSX_AEx_CONTROL_REGISTER(base, i), v);
|
||||
}
|
||||
|
||||
/* Initialize all DMEs */
|
||||
for (i = 0; i < dme_count; i++) {
|
||||
VERBOSE(" - initialize DME%d\n", i);
|
||||
v = 0;
|
||||
v |= (0x1 << FSX_DMEx_AXI_CONTROL__WRITE_CHANNEL_EN);
|
||||
v |= (0x1 << FSX_DMEx_AXI_CONTROL__READ_CHANNEL_EN);
|
||||
v |= (0xe << FSX_DMEx_AXI_CONTROL__AWQOS);
|
||||
v |= (0xa << FSX_DMEx_AXI_CONTROL__ARQOS);
|
||||
v |= (0xf << FSX_DMEx_AXI_CONTROL__AWCACHE);
|
||||
v |= (0xf << FSX_DMEx_AXI_CONTROL__ARCACHE);
|
||||
mmio_write_32(FSX_DMEx_AXI_CONTROL(dme_base, i), v);
|
||||
VERBOSE(" -- AXI_CONTROL = 0x%x\n",
|
||||
mmio_read_32(FSX_DMEx_AXI_CONTROL(dme_base, i)));
|
||||
v = 0;
|
||||
v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MIN);
|
||||
v |= (0x4 << FSX_DMEx_WR_FIFO_THRESHOLD__MAX);
|
||||
mmio_write_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i), v);
|
||||
VERBOSE(" -- WR_FIFO_THRESHOLD = 0x%x\n",
|
||||
mmio_read_32(FSX_DMEx_WR_FIFO_THRESHOLD(dme_base, i)));
|
||||
v = 0;
|
||||
v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MIN);
|
||||
v |= (0x4 << FSX_DMEx_RD_FIFO_THRESHOLD__MAX);
|
||||
mmio_write_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i), v);
|
||||
VERBOSE(" -- RD_FIFO_THRESHOLD = 0x%x\n",
|
||||
mmio_read_32(FSX_DMEx_RD_FIFO_THRESHOLD(dme_base, i)));
|
||||
}
|
||||
|
||||
/* Configure ring axi id and msi device id */
|
||||
for (i = 0; i < ring_count; i++) {
|
||||
VERBOSE(" - ring%d version=0x%x\n", i,
|
||||
mmio_read_32(FSX_RINGx_VERSION_NUMBER(base, i)));
|
||||
mmio_write_32(FSX_COMM_RINGx_MSI_DEV_ID(base, i),
|
||||
msi_dev_id);
|
||||
v = 0;
|
||||
v |= ((i & FSX_COMM_RINGx_CONTROL__AXI_ID_MASK) <<
|
||||
FSX_COMM_RINGx_CONTROL__AXI_ID);
|
||||
mmio_write_32(FSX_COMM_RINGx_CONTROL(base, i), v);
|
||||
}
|
||||
|
||||
INFO("fsx %s init done\n", fsx_type_names[fsx_type]);
|
||||
}
|
||||
|
||||
void fsx_meminit(const char *name,
|
||||
uintptr_t idm_io_control_direct,
|
||||
uintptr_t idm_io_status)
|
||||
{
|
||||
int try;
|
||||
unsigned int val;
|
||||
|
||||
VERBOSE("fsx %s meminit start\n", name);
|
||||
|
||||
VERBOSE(" - arrpoweron\n");
|
||||
mmio_setbits_32(idm_io_control_direct,
|
||||
BIT(FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWERON));
|
||||
while (!(mmio_read_32(idm_io_status) &
|
||||
BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWERON)))
|
||||
;
|
||||
|
||||
VERBOSE(" - arrpowerok\n");
|
||||
mmio_setbits_32(idm_io_control_direct,
|
||||
(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ARRPOWEROK));
|
||||
while (!(mmio_read_32(idm_io_status) &
|
||||
BIT(FS4_IDM_IO_STATUS__MEM_ARRPOWEROK)))
|
||||
;
|
||||
|
||||
VERBOSE(" - poweron\n");
|
||||
mmio_setbits_32(idm_io_control_direct,
|
||||
(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWERON));
|
||||
while (!(mmio_read_32(idm_io_status) &
|
||||
BIT(FS4_IDM_IO_STATUS__MEM_POWERON)))
|
||||
;
|
||||
|
||||
VERBOSE(" - powerok\n");
|
||||
mmio_setbits_32(idm_io_control_direct,
|
||||
(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_POWEROK));
|
||||
while (!(mmio_read_32(idm_io_status) &
|
||||
BIT(FS4_IDM_IO_STATUS__MEM_POWEROK)))
|
||||
;
|
||||
|
||||
/* Final check on all power bits */
|
||||
try = 10;
|
||||
do {
|
||||
val = mmio_read_32(idm_io_status);
|
||||
if (val == FS4_IDM_IO_STATUS__MEM_ALLOK)
|
||||
break;
|
||||
|
||||
/* Wait sometime */
|
||||
mdelay(1);
|
||||
|
||||
try--;
|
||||
} while (try > 0);
|
||||
|
||||
/* Remove memory isolation if things are fine. */
|
||||
if (try <= 0) {
|
||||
INFO(" - powerup failed\n");
|
||||
} else {
|
||||
VERBOSE(" - remove isolation\n");
|
||||
mmio_clrbits_32(idm_io_control_direct,
|
||||
(1 << FS4_IDM_IO_CONTROL_DIRECT__MEM_ISO));
|
||||
VERBOSE(" - powerup done\n");
|
||||
}
|
||||
|
||||
INFO("fsx %s meminit done\n", name);
|
||||
}
|
||||
|
||||
void fs4_disable_clocks(bool disable_sram,
|
||||
bool disable_crypto,
|
||||
bool disable_raid)
|
||||
{
|
||||
VERBOSE("fs4 disable clocks start\n");
|
||||
|
||||
if (disable_sram) {
|
||||
VERBOSE(" - disable sram clock\n");
|
||||
mmio_clrbits_32(FS4_SRAM_IDM_IO_CONTROL_DIRECT,
|
||||
(1 << FS4_IDM_IO_CONTROL_DIRECT__SRAM_CLK_EN));
|
||||
}
|
||||
|
||||
if (disable_crypto) {
|
||||
VERBOSE(" - disable crypto clock\n");
|
||||
mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
|
||||
CDRU_GENPLL5_CONTROL1__CHNL1_CRYPTO_AE_CLK);
|
||||
}
|
||||
|
||||
if (disable_raid) {
|
||||
VERBOSE(" - disable raid clock\n");
|
||||
mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
|
||||
CDRU_GENPLL5_CONTROL1__CHNL2_RAID_AE_CLK);
|
||||
}
|
||||
|
||||
if (disable_sram && disable_crypto && disable_raid) {
|
||||
VERBOSE(" - disable root clock\n");
|
||||
mmio_setbits_32(CDRU_GENPLL5_CONTROL1,
|
||||
CDRU_GENPLL5_CONTROL1__CHNL0_DME_CLK);
|
||||
mmio_setbits_32(CDRU_GENPLL2_CONTROL1,
|
||||
CDRU_GENPLL2_CONTROL1__CHNL6_FS4_CLK);
|
||||
}
|
||||
|
||||
INFO("fs4 disable clocks done\n");
|
||||
}
|
||||
+355
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <dmu.h>
|
||||
#include <ihost_pm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1 2
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2 1
|
||||
#define CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3 0
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET 9
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET 8
|
||||
#define CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET 7
|
||||
#define A72_CRM_SOFTRESETN_0 0x480
|
||||
#define A72_CRM_SOFTRESETN_1 0x484
|
||||
#define A72_CRM_DOMAIN_4_CONTROL 0x810
|
||||
#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT 3
|
||||
#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM 6
|
||||
#define A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O 0
|
||||
#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_3 0xB4C
|
||||
#define MEMORY_PDA_HI_SHIFT 0x0
|
||||
#define A72_CRM_PLL_PWR_ON 0x70
|
||||
#define A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT 4
|
||||
#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO 1
|
||||
#define A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL 0
|
||||
#define A72_CRM_SUBSYSTEM_MEMORY_CONTROL_2 0xB48
|
||||
#define A72_CRM_PLL_INTERRUPT_STATUS 0x8c
|
||||
#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_LOST_STATUS 8
|
||||
#define A72_CRM_PLL_INTERRUPT_STATUS__PLL0_LOCK_STATUS 9
|
||||
#define A72_CRM_INTERRUPT_ENABLE 0x4
|
||||
#define A72_CRM_INTERRUPT_ENABLE__PLL0_INT_ENABLE 4
|
||||
#define A72_CRM_PLL_INTERRUPT_ENABLE 0x88
|
||||
#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_STATUS_INT_ENB 9
|
||||
#define A72_CRM_PLL_INTERRUPT_ENABLE__PLL0_LOCK_LOST_STATUS_INT_ENB 8
|
||||
#define A72_CRM_PLL0_CFG0_CTRL 0x120
|
||||
#define A72_CRM_PLL0_CFG1_CTRL 0x124
|
||||
#define A72_CRM_PLL0_CFG2_CTRL 0x128
|
||||
#define A72_CRM_PLL0_CFG3_CTRL 0x12C
|
||||
#define A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV 0
|
||||
#define A72_CRM_CORE_CONFIG_DBGCTRL 0xD50
|
||||
#define A72_CRM_CORE_CONFIG_DBGROM_LO 0xD54
|
||||
#define A72_CRM_CORE_CONFIG_DBGROM_HI 0xD58
|
||||
#define A72_CRM_SUBSYSTEM_CONFIG_1__DBGL1RSTDISABLE 2
|
||||
#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN 0
|
||||
#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN 1
|
||||
#define A72_CRM_AXI_CLK_DESC 0x304
|
||||
#define A72_CRM_ACP_CLK_DESC 0x308
|
||||
#define A72_CRM_ATB_CLK_DESC 0x30C
|
||||
#define A72_CRM_PCLKDBG_DESC 0x310
|
||||
#define A72_CRM_CLOCK_MODE_CONTROL 0x40
|
||||
#define A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER 0
|
||||
#define A72_CRM_CLOCK_CONTROL_0 0x200
|
||||
#define A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL 0
|
||||
#define A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL 2
|
||||
#define A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL 4
|
||||
#define A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL 6
|
||||
#define A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL 8
|
||||
#define A72_CRM_CLOCK_CONTROL_1 0x204
|
||||
#define A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL 6
|
||||
#define A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL 8
|
||||
#define A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN 0
|
||||
#define A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN 1
|
||||
#define A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN 9
|
||||
#define A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN 10
|
||||
#define A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN 11
|
||||
#define A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN 12
|
||||
#define A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN 15
|
||||
#define A72_CRM_SOFTRESETN_0__L2_SOFTRESETN 3
|
||||
#define A72_CRM_SOFTRESETN_1__APB_SOFTRESETN 8
|
||||
|
||||
/* core related regs */
|
||||
#define A72_CRM_DOMAIN_0_CONTROL 0x800
|
||||
#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM 0x6
|
||||
#define A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O 0x0
|
||||
#define A72_CRM_DOMAIN_1_CONTROL 0x804
|
||||
#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM 0x6
|
||||
#define A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O 0x0
|
||||
#define A72_CRM_CORE_CONFIG_RVBA0_LO 0xD10
|
||||
#define A72_CRM_CORE_CONFIG_RVBA0_MID 0xD14
|
||||
#define A72_CRM_CORE_CONFIG_RVBA0_HI 0xD18
|
||||
#define A72_CRM_CORE_CONFIG_RVBA1_LO 0xD20
|
||||
#define A72_CRM_CORE_CONFIG_RVBA1_MID 0xD24
|
||||
#define A72_CRM_CORE_CONFIG_RVBA1_HI 0xD28
|
||||
#define A72_CRM_SUBSYSTEM_CONFIG_0 0xC80
|
||||
#define A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT 4
|
||||
#define A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN 4
|
||||
#define A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN 5
|
||||
#define A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN 0
|
||||
#define A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN 4
|
||||
#define A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN 1
|
||||
#define A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN 5
|
||||
|
||||
#define SPROC_MEMORY_BISR 0
|
||||
|
||||
static int cluster_power_status[PLAT_BRCM_CLUSTER_COUNT] = {CLUSTER_POWER_ON,
|
||||
CLUSTER_POWER_OFF,
|
||||
CLUSTER_POWER_OFF,
|
||||
CLUSTER_POWER_OFF};
|
||||
|
||||
void ihost_power_on_cluster(u_register_t mpidr)
|
||||
{
|
||||
uint32_t rst, d2xs;
|
||||
uint32_t cluster_id;
|
||||
uint32_t ihost_base;
|
||||
#if SPROC_MEMORY_BISR
|
||||
uint32_t bisr, cnt;
|
||||
#endif
|
||||
cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
uint32_t cluster0_freq_sel;
|
||||
|
||||
if (cluster_power_status[cluster_id] == CLUSTER_POWER_ON)
|
||||
return;
|
||||
|
||||
cluster_power_status[cluster_id] = CLUSTER_POWER_ON;
|
||||
INFO("enabling Cluster #%u\n", cluster_id);
|
||||
|
||||
switch (cluster_id) {
|
||||
case 1:
|
||||
rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH1_RESET);
|
||||
d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST1);
|
||||
#if SPROC_MEMORY_BISR
|
||||
bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST1;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH2_RESET);
|
||||
d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST2);
|
||||
#if SPROC_MEMORY_BISR
|
||||
bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST2;
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
rst = (1 << CDRU_MISC_RESET_CONTROL__CDRU_IH3_RESET);
|
||||
d2xs = (1 << CDRU_CCN_REGISTER_CONTROL_1__D2XS_PD_IHOST3);
|
||||
#if SPROC_MEMORY_BISR
|
||||
bisr = CRMU_BISR_PDG_MASK__CRMU_BISR_IHOST3;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ERROR("Invalid cluster :%u\n", cluster_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Releasing ihost resets */
|
||||
mmio_setbits_32(CDRU_MISC_RESET_CONTROL, rst);
|
||||
|
||||
/* calculate cluster/ihost base address */
|
||||
ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
|
||||
|
||||
/* Remove Cluster IO isolation */
|
||||
mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_4_CONTROL,
|
||||
(1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_I_O),
|
||||
(1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_DFT) |
|
||||
(1 << A72_CRM_DOMAIN_4_CONTROL__DOMAIN_4_ISO_MEM));
|
||||
|
||||
/*
|
||||
* Since BISR sequence requires that all cores of cluster should
|
||||
* have removed I/O isolation hence doing same here.
|
||||
*/
|
||||
/* Remove core0 memory IO isolations */
|
||||
mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_0_CONTROL,
|
||||
(1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_I_O),
|
||||
(1 << A72_CRM_DOMAIN_0_CONTROL__DOMAIN_0_ISO_MEM));
|
||||
|
||||
/* Remove core1 memory IO isolations */
|
||||
mmio_clrsetbits_32(ihost_base + A72_CRM_DOMAIN_1_CONTROL,
|
||||
(1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_I_O),
|
||||
(1 << A72_CRM_DOMAIN_1_CONTROL__DOMAIN_1_ISO_MEM));
|
||||
|
||||
#if SPROC_MEMORY_BISR
|
||||
mmio_setbits_32(CRMU_BISR_PDG_MASK, (1 << bisr));
|
||||
|
||||
if (!(mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW) &
|
||||
(1 << CDRU_CHIP_STRAP_DATA_LSW__BISR_BYPASS_MODE))) {
|
||||
/* BISR completion would take max 2 usec */
|
||||
cnt = 0;
|
||||
while (cnt < 2) {
|
||||
udelay(1);
|
||||
if (mmio_read_32(CRMU_CHIP_OTPC_STATUS) &
|
||||
(1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE))
|
||||
break;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if BISR is not completed, need to be checked with ASIC team */
|
||||
if (((mmio_read_32(CRMU_CHIP_OTPC_STATUS)) &
|
||||
(1 << CRMU_CHIP_OTPC_STATUS__OTP_BISR_LOAD_DONE)) == 0) {
|
||||
WARN("BISR did not completed and need to be addressed\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PLL Power up. supply is already on. Turn on PLL LDO/PWR */
|
||||
mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON,
|
||||
(1 << A72_CRM_PLL_PWR_ON__PLL0_ISO_PLLOUT) |
|
||||
(1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) |
|
||||
(1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL));
|
||||
|
||||
/* 1us in spec; Doubling it to be safe*/
|
||||
udelay(2);
|
||||
|
||||
/* Remove PLL output ISO */
|
||||
mmio_write_32(ihost_base + A72_CRM_PLL_PWR_ON,
|
||||
(1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_LDO) |
|
||||
(1 << A72_CRM_PLL_PWR_ON__PLL0_PWRON_PLL));
|
||||
|
||||
/*
|
||||
* PLL0 Configuration Control Register
|
||||
* these 4 registers drive the i_pll_ctrl[63:0] input of pll
|
||||
* (16b per register).
|
||||
* the values are derived from the spec (sections 8 and 10).
|
||||
*/
|
||||
|
||||
mmio_write_32(ihost_base + A72_CRM_PLL0_CFG0_CTRL, 0x00000000);
|
||||
mmio_write_32(ihost_base + A72_CRM_PLL0_CFG1_CTRL, 0x00008400);
|
||||
mmio_write_32(ihost_base + A72_CRM_PLL0_CFG2_CTRL, 0x00000001);
|
||||
mmio_write_32(ihost_base + A72_CRM_PLL0_CFG3_CTRL, 0x00000000);
|
||||
|
||||
/* Read the freq_sel from cluster 0, which is up already */
|
||||
cluster0_freq_sel = bcm_get_ihost_pll_freq(0);
|
||||
bcm_set_ihost_pll_freq(cluster_id, cluster0_freq_sel);
|
||||
|
||||
udelay(1);
|
||||
|
||||
/* Release clock source reset */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
|
||||
(1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN));
|
||||
|
||||
udelay(1);
|
||||
|
||||
/*
|
||||
* Integer division for clks (divider value = n+1).
|
||||
* These are the divisor of ARM PLL clock frequecy.
|
||||
*/
|
||||
mmio_write_32(ihost_base + A72_CRM_AXI_CLK_DESC, 0x00000001);
|
||||
mmio_write_32(ihost_base + A72_CRM_ACP_CLK_DESC, 0x00000001);
|
||||
mmio_write_32(ihost_base + A72_CRM_ATB_CLK_DESC, 0x00000004);
|
||||
mmio_write_32(ihost_base + A72_CRM_PCLKDBG_DESC, 0x0000000b);
|
||||
|
||||
/*
|
||||
* clock change trigger - must set to take effect after clock
|
||||
* source change
|
||||
*/
|
||||
mmio_setbits_32(ihost_base + A72_CRM_CLOCK_MODE_CONTROL,
|
||||
(1 << A72_CRM_CLOCK_MODE_CONTROL__CLK_CHANGE_TRIGGER));
|
||||
|
||||
/* turn on functional clocks */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_0,
|
||||
(3 << A72_CRM_CLOCK_CONTROL_0__ARM_HW_SW_ENABLE_SEL) |
|
||||
(3 << A72_CRM_CLOCK_CONTROL_0__AXI_HW_SW_ENABLE_SEL) |
|
||||
(3 << A72_CRM_CLOCK_CONTROL_0__ACP_HW_SW_ENABLE_SEL) |
|
||||
(3 << A72_CRM_CLOCK_CONTROL_0__ATB_HW_SW_ENABLE_SEL) |
|
||||
(3 << A72_CRM_CLOCK_CONTROL_0__PCLKDBG_HW_SW_ENA_SEL));
|
||||
|
||||
mmio_setbits_32(ihost_base + A72_CRM_CLOCK_CONTROL_1,
|
||||
(3 << A72_CRM_CLOCK_CONTROL_1__TMON_HW_SW_ENABLE_SEL) |
|
||||
(3 << A72_CRM_CLOCK_CONTROL_1__APB_HW_SW_ENABLE_SEL));
|
||||
|
||||
/* Program D2XS Power Down Registers */
|
||||
mmio_setbits_32(CDRU_CCN_REGISTER_CONTROL_1, d2xs);
|
||||
|
||||
/* Program Core Config Debug ROM Address Registers */
|
||||
/* mark valid for Debug ROM base address */
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGCTRL,
|
||||
(1 << A72_CRM_CORE_CONFIG_DBGCTRL__DBGROMADDRV));
|
||||
|
||||
/* Program Lo and HI address of coresight DBG rom address */
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_LO,
|
||||
(CORESIGHT_BASE_ADDR >> 12) & 0xffff);
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_DBGROM_HI,
|
||||
(CORESIGHT_BASE_ADDR >> 28) & 0xffff);
|
||||
|
||||
/*
|
||||
* Release soft resets of different components.
|
||||
* Order: Bus clocks --> PERIPH --> L2 --> cores
|
||||
*/
|
||||
|
||||
/* Bus clocks soft resets */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
|
||||
(1 << A72_CRM_SOFTRESETN_0__CRYSTAL26_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_0__CRM_PLL0_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_0__AXI_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_0__ACP_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_0__ATB_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_0__PCLKDBG_SOFTRESETN));
|
||||
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1,
|
||||
(1 << A72_CRM_SOFTRESETN_1__APB_SOFTRESETN));
|
||||
|
||||
/* Periph component softreset */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
|
||||
(1 << A72_CRM_SOFTRESETN_0__TMON_SOFTRESETN));
|
||||
|
||||
/* L2 softreset */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
|
||||
(1 << A72_CRM_SOFTRESETN_0__L2_SOFTRESETN));
|
||||
|
||||
/* Enable and program Satellite timer */
|
||||
ihost_enable_satellite_timer(cluster_id);
|
||||
}
|
||||
|
||||
void ihost_power_on_secondary_core(u_register_t mpidr, uint64_t rvbar)
|
||||
{
|
||||
uint32_t ihost_base;
|
||||
uint32_t coreid = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
uint32_t cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
|
||||
ihost_base = IHOST0_BASE + cluster_id * IHOST_ADDR_SPACE;
|
||||
INFO("programming core #%u\n", coreid);
|
||||
|
||||
if (coreid) {
|
||||
/* program the entry point for core1 */
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_LO,
|
||||
rvbar & 0xFFFF);
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_MID,
|
||||
(rvbar >> 16) & 0xFFFF);
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA1_HI,
|
||||
(rvbar >> 32) & 0xFFFF);
|
||||
} else {
|
||||
/* program the entry point for core */
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_LO,
|
||||
rvbar & 0xFFFF);
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_MID,
|
||||
(rvbar >> 16) & 0xFFFF);
|
||||
mmio_write_32(ihost_base + A72_CRM_CORE_CONFIG_RVBA0_HI,
|
||||
(rvbar >> 32) & 0xFFFF);
|
||||
}
|
||||
|
||||
/* Tell debug logic which processor is up */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SUBSYSTEM_CONFIG_0,
|
||||
(coreid ?
|
||||
(2 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT) :
|
||||
(1 << A72_CRM_SUBSYSTEM_CONFIG_0__DBGPWRDUP_CFG_SHIFT)));
|
||||
|
||||
/* releasing soft resets for IHOST core */
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_0,
|
||||
(coreid ?
|
||||
(1 << A72_CRM_SOFTRESETN_0__COREPOR1_SOFTRESETN) :
|
||||
(1 << A72_CRM_SOFTRESETN_0__COREPOR0_SOFTRESETN)));
|
||||
|
||||
mmio_setbits_32(ihost_base + A72_CRM_SOFTRESETN_1,
|
||||
(coreid ?
|
||||
((1 << A72_CRM_SOFTRESETN_1__CORE1_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_1__DEBUG1_SOFTRESETN)) :
|
||||
((1 << A72_CRM_SOFTRESETN_1__CORE0_SOFTRESETN) |
|
||||
(1 << A72_CRM_SOFTRESETN_1__DEBUG0_SOFTRESETN))));
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <iommu.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define SMMU_BASE 0x64000000
|
||||
#define ARM_SMMU_MAX_NUM_CNTXT_BANK 64
|
||||
#define SMMU_CTX_BANK_IDX_SECURE_CRMU 63
|
||||
#define ARM_SMMU_NUM_SECURE_MASTER 1
|
||||
#define ARM_SMMU_NSNUMCBO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \
|
||||
ARM_SMMU_NUM_SECURE_MASTER)
|
||||
#define ARM_SMMU_NSNUMSMRGO (ARM_SMMU_MAX_NUM_CNTXT_BANK - \
|
||||
ARM_SMMU_NUM_SECURE_MASTER)
|
||||
/* Reserved Banks. */
|
||||
#define SMMU_CTX_BANK_IDX (SMMU_CTX_BANK_IDX_SECURE_CRMU - \
|
||||
ARM_SMMU_NUM_SECURE_MASTER)
|
||||
#define NUM_OF_SMRS 1
|
||||
|
||||
#define STG1_WITH_STG2_BYPASS 1
|
||||
#define ARM_LPAE_PGTBL_PHYS_CRMU 0x880000000
|
||||
#define ARM_LPAE_PGTBL_PHYS 0x880200000
|
||||
#define ARM_LPAE_PGTBL_PTE_CNT 512
|
||||
#define ARM_LPAE_PTE_L1_BLOCK_SIZE 0x40000000
|
||||
#define ARM_LPAE_PTE_L1_ADDR_MASK 0x0000FFFFC0000000UL
|
||||
#define ARM_LPAE_PTE_TABLE 0x2UL
|
||||
#define ARM_LPAE_PTE_VALID 0x1UL
|
||||
#define ARM_LPAE_PTE_ATTRINDX 2
|
||||
#define ARM_LPAE_PTE_NS 5
|
||||
#define ARM_LPAE_PTE_AP 6
|
||||
#define ARM_LPAE_PTE_AP_EL1_RW 0x0
|
||||
#define ARM_LPAE_PTE_AP_EL0_RW 0x1
|
||||
#define ARM_LPAE_PTE_SH 8
|
||||
#define ARM_LPAE_PTE_SH_NON 0x0
|
||||
#define ARM_LPAE_PTE_SH_OUTER 0x2
|
||||
#define ARM_LPAE_PTE_SH_INNER 0x3
|
||||
#define ARM_LPAE_PTE_AF 10
|
||||
#define ARM_SMMU_RES_SIZE 0x80000
|
||||
|
||||
#define ARM_LPAE_PTE_NSTABLE 0x8000000000000000UL
|
||||
#define ARM_LPAE_PTE_L1_INDEX_SHIFT 30
|
||||
#define ARM_LPAE_PTE_L1_INDEX_MASK 0x1ff
|
||||
#define ARM_LPAE_PTE_L0_INDEX_SHIFT 39
|
||||
#define ARM_LPAE_PTE_L0_INDEX_MASK 0x1ff
|
||||
#define ARM_LPAE_PTE_TABLE_MASK ~(0xfffUL)
|
||||
/* Configuration registers */
|
||||
#define ARM_SMMU_GR0_sCR0 0x0
|
||||
#define sCR0_CLIENTPD (1 << 0)
|
||||
#define sCR0_GFRE (1 << 1)
|
||||
#define sCR0_GFIE (1 << 2)
|
||||
#define sCR0_GCFGFRE (1 << 4)
|
||||
#define sCR0_GCFGFIE (1 << 5)
|
||||
#define sCR0_USFCFG (1 << 10)
|
||||
#define sCR0_VMIDPNE (1 << 11)
|
||||
#define sCR0_PTM (1 << 12)
|
||||
#define sCR0_FB (1 << 13)
|
||||
#define sCR0_VMID16EN (1 << 31)
|
||||
#define sCR0_BSU_SHIFT 14
|
||||
#define sCR0_BSU_MASK 0x3
|
||||
#define ARM_SMMU_SMMU_SCR1 0x4
|
||||
#define SCR1_NSNUMCBO_MASK 0xFF
|
||||
#define SCR1_NSNUMCBO_SHIFT 0x0
|
||||
#define SCR1_NSNUMSMRGO_MASK 0xFF00
|
||||
#define SCR1_NSNUMSMRGO_SHIFT 0x8
|
||||
|
||||
/* Identification registers */
|
||||
#define ARM_SMMU_GR0_ID0 0x20
|
||||
#define ARM_SMMU_GR0_ID1 0x24
|
||||
#define ARM_SMMU_GR0_ID2 0x28
|
||||
#define ARM_SMMU_GR0_ID3 0x2c
|
||||
#define ARM_SMMU_GR0_ID4 0x30
|
||||
#define ARM_SMMU_GR0_ID5 0x34
|
||||
#define ARM_SMMU_GR0_ID6 0x38
|
||||
#define ARM_SMMU_GR0_ID7 0x3c
|
||||
#define ARM_SMMU_GR0_sGFSR 0x48
|
||||
#define ARM_SMMU_GR0_sGFSYNR0 0x50
|
||||
#define ARM_SMMU_GR0_sGFSYNR1 0x54
|
||||
#define ARM_SMMU_GR0_sGFSYNR2 0x58
|
||||
|
||||
#define ID1_PAGESIZE (1U << 31)
|
||||
#define ID1_NUMPAGENDXB_SHIFT 28
|
||||
#define ID1_NUMPAGENDXB_MASK 7
|
||||
#define ID1_NUMS2CB_SHIFT 16
|
||||
#define ID1_NUMS2CB_MASK 0xff
|
||||
#define ID1_NUMCB_SHIFT 0
|
||||
#define ID1_NUMCB_MASK 0xff
|
||||
|
||||
/* SMMU global address space */
|
||||
#define ARM_SMMU_GR0(smmu) ((smmu)->base)
|
||||
#define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift))
|
||||
|
||||
/* Stream mapping registers */
|
||||
#define ARM_SMMU_GR0_SMR(n) (0x800 + (n << 2))
|
||||
#define SMR_VALID (1U << 31)
|
||||
#define SMR_MASK_SHIFT 16
|
||||
#define SMR_ID_SHIFT 0
|
||||
|
||||
#define ARM_SMMU_GR0_S2CR(n) (0xc00 + (n << 2))
|
||||
#define S2CR_CBNDX_SHIFT 0
|
||||
#define S2CR_CBNDX_MASK 0xff
|
||||
#define S2CR_TYPE_SHIFT 16
|
||||
#define S2CR_TYPE_MASK 0x3
|
||||
|
||||
#define ARM_SMMU_GR1_CBA2R(n) (0x800 + (n << 2))
|
||||
#define CBA2R_RW64_32BIT (0 << 0)
|
||||
#define CBA2R_RW64_64BIT (1 << 0)
|
||||
#define CBA2R_VMID_SHIFT 16
|
||||
#define CBA2R_VMID_MASK 0xffff
|
||||
|
||||
#define ARM_SMMU_GR1_CBAR(n) (0x0 + (n << 2))
|
||||
#define CBAR_VMID_SHIFT 0
|
||||
#define CBAR_VMID_MASK 0xff
|
||||
#define CBAR_S1_BPSHCFG_SHIFT 8
|
||||
#define CBAR_S1_BPSHCFG_MASK 3
|
||||
#define CBAR_S1_BPSHCFG_NSH 3
|
||||
#define CBAR_S1_MEMATTR_SHIFT 12
|
||||
#define CBAR_S1_MEMATTR_MASK 0xf
|
||||
#define CBAR_S1_MEMATTR_WB 0xf
|
||||
#define CBAR_TYPE_SHIFT 16
|
||||
#define CBAR_TYPE_MASK 0x3
|
||||
#define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT)
|
||||
#define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT)
|
||||
#define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT)
|
||||
#define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT)
|
||||
#define CBAR_IRPTNDX_SHIFT 24
|
||||
#define CBAR_IRPTNDX_MASK 0xff
|
||||
|
||||
/* Translation context bank */
|
||||
#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1))
|
||||
#define ARM_SMMU_CB(smmu, n) ((n) * (1 << (smmu)->pgshift))
|
||||
|
||||
#define ARM_SMMU_CB_SCTLR 0x0
|
||||
#define ARM_SMMU_CB_ACTLR 0x4
|
||||
#define ARM_SMMU_CB_RESUME 0x8
|
||||
#define ARM_SMMU_CB_TTBCR2 0x10
|
||||
#define ARM_SMMU_CB_TTBR0 0x20
|
||||
#define ARM_SMMU_CB_TTBR1 0x28
|
||||
#define ARM_SMMU_CB_TTBCR 0x30
|
||||
#define ARM_SMMU_CB_CONTEXTIDR 0x34
|
||||
#define ARM_SMMU_CB_S1_MAIR0 0x38
|
||||
#define ARM_SMMU_CB_S1_MAIR1 0x3c
|
||||
#define ARM_SMMU_CB_PAR 0x50
|
||||
#define ARM_SMMU_CB_FSR 0x58
|
||||
#define ARM_SMMU_CB_FAR 0x60
|
||||
#define ARM_SMMU_CB_FSYNR0 0x68
|
||||
#define ARM_SMMU_CB_S1_TLBIVA 0x600
|
||||
#define ARM_SMMU_CB_S1_TLBIASID 0x610
|
||||
#define ARM_SMMU_CB_S1_TLBIVAL 0x620
|
||||
#define ARM_SMMU_CB_S2_TLBIIPAS2 0x630
|
||||
#define ARM_SMMU_CB_S2_TLBIIPAS2L 0x638
|
||||
#define ARM_SMMU_CB_ATS1PR 0x800
|
||||
#define ARM_SMMU_CB_ATSR 0x8f0
|
||||
|
||||
#define SCTLR_S1_ASIDPNE (1 << 12)
|
||||
#define SCTLR_CFCFG (1 << 7)
|
||||
#define SCTLR_CFIE (1 << 6)
|
||||
#define SCTLR_CFRE (1 << 5)
|
||||
#define SCTLR_E (1 << 4)
|
||||
#define SCTLR_AFE (1 << 2)
|
||||
#define SCTLR_TRE (1 << 1)
|
||||
#define SCTLR_M (1 << 0)
|
||||
|
||||
/* ARM LPAE configuration. */
|
||||
/**************************************************************/
|
||||
/* Register bits */
|
||||
#define ARM_32_LPAE_TCR_EAE (1 << 31)
|
||||
#define ARM_64_LPAE_S2_TCR_RES1 (1 << 31)
|
||||
|
||||
#define ARM_LPAE_TCR_EPD1 (1 << 23)
|
||||
|
||||
#define ARM_LPAE_TCR_TG0_4K (0 << 14)
|
||||
#define ARM_LPAE_TCR_TG0_64K (1 << 14)
|
||||
#define ARM_LPAE_TCR_TG0_16K (2 << 14)
|
||||
|
||||
#define ARM_LPAE_TCR_SH0_SHIFT 12
|
||||
#define ARM_LPAE_TCR_SH0_MASK 0x3
|
||||
#define ARM_LPAE_TCR_SH_NS 0
|
||||
#define ARM_LPAE_TCR_SH_OS 2
|
||||
#define ARM_LPAE_TCR_SH_IS 3
|
||||
|
||||
#define ARM_LPAE_TCR_ORGN0_SHIFT 10
|
||||
#define ARM_LPAE_TCR_IRGN0_SHIFT 8
|
||||
#define ARM_LPAE_TCR_RGN_MASK 0x3
|
||||
#define ARM_LPAE_TCR_RGN_NC 0
|
||||
#define ARM_LPAE_TCR_RGN_WBWA 1
|
||||
#define ARM_LPAE_TCR_RGN_WT 2
|
||||
#define ARM_LPAE_TCR_RGN_WB 3
|
||||
|
||||
#define ARM_LPAE_TCR_SL0_SHIFT 6
|
||||
#define ARM_LPAE_TCR_SL0_MASK 0x3
|
||||
|
||||
#define ARM_LPAE_TCR_T0SZ_SHIFT 0
|
||||
#define ARM_LPAE_TCR_SZ_MASK 0xf
|
||||
|
||||
#define ARM_LPAE_TCR_PS_SHIFT 16
|
||||
#define ARM_LPAE_TCR_PS_MASK 0x7
|
||||
|
||||
#define ARM_LPAE_TCR_IPS_SHIFT 32
|
||||
#define ARM_LPAE_TCR_IPS_MASK 0x7
|
||||
|
||||
#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL
|
||||
#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL
|
||||
#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL
|
||||
#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL
|
||||
#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL
|
||||
#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
|
||||
|
||||
#define ARM_LPAE_MAIR_ATTR_SHIFT(n) ((n) << 3)
|
||||
#define ARM_LPAE_MAIR_ATTR_MASK 0xff
|
||||
#define ARM_LPAE_MAIR_ATTR_DEVICE 0x04
|
||||
#define ARM_LPAE_MAIR_ATTR_NC 0x44
|
||||
#define ARM_LPAE_MAIR_ATTR_WBRWA 0xff
|
||||
#define ARM_LPAE_MAIR_ATTR_IDX_NC 0
|
||||
#define ARM_LPAE_MAIR_ATTR_IDX_CACHE 1
|
||||
#define ARM_LPAE_MAIR_ATTR_IDX_DEV 2
|
||||
|
||||
#define TTBRn_ASID_SHIFT 48
|
||||
#define TTBCR2_SEP_SHIFT 15
|
||||
#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
|
||||
#define TTBCR2_AS (1 << 4)
|
||||
#define TTBCR_T0SZ(ia_bits) (64 - (ia_bits))
|
||||
|
||||
#define S2CR_PRIVCFG_SHIFT 24
|
||||
#define S2CR_PRIVCFG_MASK 0x3
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
uint16_t paxc_stream_ids[] = { 0x2000 };
|
||||
|
||||
uint16_t paxc_stream_ids_mask[] = { 0x1fff };
|
||||
uint16_t crmu_stream_ids[] = { CRMU_STREAM_ID };
|
||||
uint16_t crmu_stream_ids_mask[] = { 0x0 };
|
||||
|
||||
enum arm_smmu_s2cr_type {
|
||||
S2CR_TYPE_TRANS,
|
||||
S2CR_TYPE_BYPASS,
|
||||
S2CR_TYPE_FAULT,
|
||||
};
|
||||
|
||||
enum arm_smmu_s2cr_privcfg {
|
||||
S2CR_PRIVCFG_DEFAULT,
|
||||
S2CR_PRIVCFG_DIPAN,
|
||||
S2CR_PRIVCFG_UNPRIV,
|
||||
S2CR_PRIVCFG_PRIV,
|
||||
};
|
||||
|
||||
struct arm_smmu_smr {
|
||||
uint16_t mask;
|
||||
uint16_t id;
|
||||
uint32_t valid;
|
||||
};
|
||||
|
||||
struct arm_smmu_s2cr {
|
||||
int count;
|
||||
enum arm_smmu_s2cr_type type;
|
||||
enum arm_smmu_s2cr_privcfg privcfg;
|
||||
uint8_t cbndx;
|
||||
};
|
||||
|
||||
struct arm_smmu_cfg {
|
||||
uint8_t cbndx;
|
||||
uint8_t irptndx;
|
||||
uint32_t cbar;
|
||||
};
|
||||
|
||||
struct arm_smmu_device {
|
||||
uint8_t *base;
|
||||
uint32_t streams;
|
||||
unsigned long size;
|
||||
unsigned long pgshift;
|
||||
unsigned long va_size;
|
||||
unsigned long ipa_size;
|
||||
unsigned long pa_size;
|
||||
struct arm_smmu_smr smr[NUM_OF_SMRS];
|
||||
struct arm_smmu_s2cr s2cr[NUM_OF_SMRS];
|
||||
struct arm_smmu_cfg cfg[NUM_OF_SMRS];
|
||||
uint16_t *stream_ids;
|
||||
uint16_t *stream_ids_mask;
|
||||
};
|
||||
|
||||
void arm_smmu_enable_secure_client_port(void)
|
||||
{
|
||||
uintptr_t smmu_base = SMMU_BASE;
|
||||
|
||||
mmio_clrbits_32(smmu_base, sCR0_CLIENTPD);
|
||||
}
|
||||
|
||||
void arm_smmu_reserve_secure_cntxt(void)
|
||||
{
|
||||
uintptr_t smmu_base = SMMU_BASE;
|
||||
|
||||
mmio_clrsetbits_32(smmu_base + ARM_SMMU_SMMU_SCR1,
|
||||
(SCR1_NSNUMSMRGO_MASK | SCR1_NSNUMCBO_MASK),
|
||||
((ARM_SMMU_NSNUMCBO << SCR1_NSNUMCBO_SHIFT) |
|
||||
(ARM_SMMU_NSNUMSMRGO << SCR1_NSNUMSMRGO_SHIFT)));
|
||||
}
|
||||
|
||||
static void arm_smmu_smr_cfg(struct arm_smmu_device *smmu, uint32_t index)
|
||||
{
|
||||
uint32_t idx = smmu->cfg[index].cbndx;
|
||||
struct arm_smmu_smr *smr = &smmu->smr[index];
|
||||
uint32_t reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
|
||||
|
||||
if (smr->valid)
|
||||
reg |= SMR_VALID;
|
||||
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
|
||||
ARM_SMMU_GR0_SMR(idx)), reg);
|
||||
}
|
||||
|
||||
static void arm_smmu_s2cr_cfg(struct arm_smmu_device *smmu, uint32_t index)
|
||||
{
|
||||
uint32_t idx = smmu->cfg[index].cbndx;
|
||||
struct arm_smmu_s2cr *s2cr = &smmu->s2cr[index];
|
||||
|
||||
uint32_t reg = (s2cr->type & S2CR_TYPE_MASK) << S2CR_TYPE_SHIFT |
|
||||
(s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
|
||||
(s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
|
||||
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_GR0(smmu) +
|
||||
ARM_SMMU_GR0_S2CR(idx)), reg);
|
||||
}
|
||||
|
||||
static void smmu_set_pgtbl(struct arm_smmu_device *smmu,
|
||||
enum iommu_domain dom,
|
||||
uint64_t *pg_table_base)
|
||||
{
|
||||
int i, l0_index, l1_index;
|
||||
uint64_t addr, *pte, *l0_base, *l1_base;
|
||||
uint64_t addr_space_limit;
|
||||
|
||||
if (dom == PCIE_PAXC) {
|
||||
addr_space_limit = 0xffffffffff;
|
||||
} else if (dom == DOMAIN_CRMU) {
|
||||
addr_space_limit = 0xffffffff;
|
||||
} else {
|
||||
ERROR("dom is not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
l0_base = pg_table_base;
|
||||
/* clear L0 descriptors. */
|
||||
for (i = 0; i < ARM_LPAE_PGTBL_PTE_CNT; i++)
|
||||
l0_base[i] = 0x0;
|
||||
|
||||
addr = 0x0;
|
||||
while (addr < addr_space_limit) {
|
||||
/* find L0 pte */
|
||||
l0_index = ((addr >> ARM_LPAE_PTE_L0_INDEX_SHIFT) &
|
||||
ARM_LPAE_PTE_L0_INDEX_MASK);
|
||||
l1_base = l0_base + ((l0_index + 1) * ARM_LPAE_PGTBL_PTE_CNT);
|
||||
|
||||
/* setup L0 pte if required */
|
||||
pte = l0_base + l0_index;
|
||||
if (*pte == 0x0) {
|
||||
*pte |= ((uint64_t)l1_base & ARM_LPAE_PTE_TABLE_MASK);
|
||||
if (dom == PCIE_PAXC)
|
||||
*pte |= ARM_LPAE_PTE_NSTABLE;
|
||||
*pte |= ARM_LPAE_PTE_TABLE;
|
||||
*pte |= ARM_LPAE_PTE_VALID;
|
||||
}
|
||||
|
||||
/* find L1 pte */
|
||||
l1_index = ((addr >> ARM_LPAE_PTE_L1_INDEX_SHIFT) &
|
||||
ARM_LPAE_PTE_L1_INDEX_MASK);
|
||||
pte = l1_base + l1_index;
|
||||
|
||||
/* setup L1 pte */
|
||||
*pte = 0x0;
|
||||
*pte |= (addr & ARM_LPAE_PTE_L1_ADDR_MASK);
|
||||
if (addr < 0x80000000) {
|
||||
*pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV <<
|
||||
ARM_LPAE_PTE_ATTRINDX);
|
||||
if (dom == PCIE_PAXC)
|
||||
*pte |= (1 << ARM_LPAE_PTE_NS);
|
||||
} else {
|
||||
*pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE <<
|
||||
ARM_LPAE_PTE_ATTRINDX);
|
||||
*pte |= (1 << ARM_LPAE_PTE_NS);
|
||||
}
|
||||
*pte |= (ARM_LPAE_PTE_AP_EL0_RW << ARM_LPAE_PTE_AP);
|
||||
*pte |= (ARM_LPAE_PTE_SH_INNER << ARM_LPAE_PTE_SH);
|
||||
*pte |= (1 << ARM_LPAE_PTE_AF);
|
||||
*pte |= ARM_LPAE_PTE_VALID;
|
||||
|
||||
addr += ARM_LPAE_PTE_L1_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_smmu_create_identity_map(enum iommu_domain dom)
|
||||
{
|
||||
struct arm_smmu_device iommu;
|
||||
struct arm_smmu_device *smmu = &iommu;
|
||||
uint32_t reg, reg2;
|
||||
unsigned long long reg64;
|
||||
uint32_t idx;
|
||||
uint16_t asid;
|
||||
unsigned int context_bank_index;
|
||||
unsigned long long pg_table_base;
|
||||
|
||||
smmu->base = (uint8_t *) SMMU_BASE;
|
||||
reg = mmio_read_32((uintptr_t) (ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_ID1));
|
||||
smmu->pgshift = (reg & ID1_PAGESIZE) ? 16 : 12;
|
||||
smmu->size = ARM_SMMU_RES_SIZE;
|
||||
smmu->stream_ids = NULL;
|
||||
|
||||
switch (dom) {
|
||||
case PCIE_PAXC:
|
||||
smmu->stream_ids = &paxc_stream_ids[0];
|
||||
smmu->stream_ids_mask = &paxc_stream_ids_mask[0];
|
||||
smmu->streams = ARRAY_SIZE(paxc_stream_ids);
|
||||
context_bank_index = SMMU_CTX_BANK_IDX;
|
||||
pg_table_base = ARM_LPAE_PGTBL_PHYS;
|
||||
break;
|
||||
case DOMAIN_CRMU:
|
||||
smmu->stream_ids = &crmu_stream_ids[0];
|
||||
smmu->stream_ids_mask = &crmu_stream_ids_mask[0];
|
||||
smmu->streams = ARRAY_SIZE(crmu_stream_ids);
|
||||
context_bank_index = SMMU_CTX_BANK_IDX_SECURE_CRMU;
|
||||
pg_table_base = ARM_LPAE_PGTBL_PHYS_CRMU;
|
||||
break;
|
||||
default:
|
||||
ERROR("domain not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (smmu->streams > NUM_OF_SMRS) {
|
||||
INFO("can not support more than %d sids\n", NUM_OF_SMRS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set up iommu dev. */
|
||||
for (idx = 0; idx < smmu->streams; idx++) {
|
||||
/* S2CR. */
|
||||
smmu->s2cr[idx].type = S2CR_TYPE_TRANS;
|
||||
smmu->s2cr[idx].privcfg = S2CR_PRIVCFG_DEFAULT;
|
||||
smmu->s2cr[idx].cbndx = context_bank_index;
|
||||
smmu->cfg[idx].cbndx = context_bank_index;
|
||||
smmu->cfg[idx].cbar = STG1_WITH_STG2_BYPASS << CBAR_TYPE_SHIFT;
|
||||
arm_smmu_s2cr_cfg(smmu, idx);
|
||||
|
||||
/* SMR. */
|
||||
smmu->smr[idx].mask = smmu->stream_ids_mask[idx];
|
||||
smmu->smr[idx].id = smmu->stream_ids[idx];
|
||||
smmu->smr[idx].valid = 1;
|
||||
arm_smmu_smr_cfg(smmu, idx);
|
||||
|
||||
/* CBA2R. 64-bit Translation */
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
|
||||
ARM_SMMU_GR1_CBA2R(smmu->cfg[idx].cbndx)),
|
||||
0x1);
|
||||
/* CBAR.*/
|
||||
reg = smmu->cfg[idx].cbar;
|
||||
reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
|
||||
(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
|
||||
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_GR1(smmu) +
|
||||
ARM_SMMU_GR1_CBAR(smmu->cfg[idx].cbndx)),
|
||||
reg);
|
||||
|
||||
/* TTBCR. */
|
||||
reg64 = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) |
|
||||
(ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) |
|
||||
(ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
|
||||
reg64 |= ARM_LPAE_TCR_TG0_4K;
|
||||
reg64 |= (ARM_LPAE_TCR_PS_40_BIT << ARM_LPAE_TCR_IPS_SHIFT);
|
||||
/* ias 40 bits.*/
|
||||
reg64 |= TTBCR_T0SZ(40) << ARM_LPAE_TCR_T0SZ_SHIFT;
|
||||
/* Disable speculative walks through TTBR1 */
|
||||
reg64 |= ARM_LPAE_TCR_EPD1;
|
||||
reg = (uint32_t) reg64;
|
||||
reg2 = (uint32_t) (reg64 >> 32);
|
||||
reg2 |= TTBCR2_SEP_UPSTREAM;
|
||||
reg2 |= TTBCR2_AS;
|
||||
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_TTBCR2), reg2);
|
||||
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_TTBCR), reg);
|
||||
|
||||
/* TTBR0. */
|
||||
asid = smmu->cfg[idx].cbndx;
|
||||
reg64 = pg_table_base;
|
||||
reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
|
||||
|
||||
mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_TTBR0), reg64);
|
||||
/* TTBR1. */
|
||||
reg64 = 0;
|
||||
reg64 |= (unsigned long long) asid << TTBRn_ASID_SHIFT;
|
||||
|
||||
mmio_write_64((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_TTBR1), reg64);
|
||||
/* MAIR. */
|
||||
reg = (ARM_LPAE_MAIR_ATTR_NC
|
||||
<< ARM_LPAE_MAIR_ATTR_SHIFT
|
||||
(ARM_LPAE_MAIR_ATTR_IDX_NC)) |
|
||||
(ARM_LPAE_MAIR_ATTR_WBRWA <<
|
||||
ARM_LPAE_MAIR_ATTR_SHIFT
|
||||
(ARM_LPAE_MAIR_ATTR_IDX_CACHE)) |
|
||||
(ARM_LPAE_MAIR_ATTR_DEVICE <<
|
||||
ARM_LPAE_MAIR_ATTR_SHIFT
|
||||
(ARM_LPAE_MAIR_ATTR_IDX_DEV));
|
||||
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_S1_MAIR0), reg);
|
||||
|
||||
/* MAIR1. */
|
||||
reg = 0;
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_S1_MAIR1), reg);
|
||||
/* SCTLR. */
|
||||
reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | SCTLR_M;
|
||||
/* stage 1.*/
|
||||
reg |= SCTLR_S1_ASIDPNE;
|
||||
mmio_write_32((uintptr_t) (ARM_SMMU_CB_BASE(smmu) +
|
||||
ARM_SMMU_CB(smmu, smmu->cfg[idx].cbndx) +
|
||||
ARM_SMMU_CB_SCTLR), reg);
|
||||
}
|
||||
smmu_set_pgtbl(smmu, dom, (uint64_t *)pg_table_base);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <ncsi.h>
|
||||
#include <sr_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
static const char *const io_drives[] = {
|
||||
"2mA", "4mA", "6mA", "8mA",
|
||||
"10mA", "12mA", "14mA", "16mA"
|
||||
};
|
||||
|
||||
void brcm_stingray_ncsi_init(void)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
unsigned int selx = 0;
|
||||
|
||||
#if NCSI_IO_DRIVE_STRENGTH_MA == 2
|
||||
selx = 0x0;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 4
|
||||
selx = 0x1;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 6
|
||||
selx = 0x2;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 8
|
||||
selx = 0x3;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 10
|
||||
selx = 0x4;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 12
|
||||
selx = 0x5;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 14
|
||||
selx = 0x6;
|
||||
#elif NCSI_IO_DRIVE_STRENGTH_MA == 16
|
||||
selx = 0x7;
|
||||
#else
|
||||
ERROR("Unsupported NCSI_IO_DRIVE_STRENGTH_MA. Please check it.\n");
|
||||
return;
|
||||
#endif
|
||||
INFO("ncsi io drives: %s\n", io_drives[selx]);
|
||||
|
||||
for (i = 0; i < NITRO_NCSI_IOPAD_CONTROL_NUM; i++) {
|
||||
mmio_clrsetbits_32((NITRO_NCSI_IOPAD_CONTROL_BASE + (i * 4)),
|
||||
PAD_SELX_MASK, PAD_SELX_VALUE(selx));
|
||||
}
|
||||
|
||||
INFO("ncsi init done\n");
|
||||
}
|
||||
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <paxb.h>
|
||||
#include <sr_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
#define PCIE_CORE_PWR_ARR_POWERON 0x8
|
||||
#define PCIE_CORE_PWR_ARR_POWEROK 0x4
|
||||
#define PCIE_CORE_PWR_POWERON 0x2
|
||||
#define PCIE_CORE_PWR_POWEROK 0x1
|
||||
|
||||
#define PCIE_CORE_USER_CFG (PCIE_CORE_BASE + 0x38)
|
||||
#define PCIE_PAXB_SMMU_SID_CFG (PCIE_CORE_BASE + 0x60)
|
||||
#ifdef SID_B8_D1_F1
|
||||
#define PAXB_SMMU_SID_CFG_BUS_WIDTH (0x8 << 8)
|
||||
#define PAXB_SMMU_SID_CFG_DEV_WIDTH (0x1 << 12)
|
||||
#define PAXB_SMMU_SID_CFG_FUN_WIDTH (0x1 << 16)
|
||||
#else
|
||||
#define PAXB_SMMU_SID_CFG_BUS_WIDTH (0x2 << 8)
|
||||
#define PAXB_SMMU_SID_CFG_DEV_WIDTH (0x5 << 12)
|
||||
#define PAXB_SMMU_SID_CFG_FUN_WIDTH (0x3 << 16)
|
||||
#endif
|
||||
|
||||
#define PAXB_APB_TIMEOUT_COUNT_OFFSET 0x034
|
||||
|
||||
/* allow up to 5 ms for each power switch to stabilize */
|
||||
#define PCIE_CORE_PWR_TIMEOUT_MS 5
|
||||
|
||||
/* wait 1 microsecond for PCIe core soft reset */
|
||||
#define PCIE_CORE_SOFT_RST_DELAY_US 1
|
||||
|
||||
/*
|
||||
* List of PAXB APB registers
|
||||
*/
|
||||
#define PAXB_BASE 0x48000000
|
||||
#define PAXB_BASE_OFFSET 0x4000
|
||||
#define PAXB_OFFSET(core) (PAXB_BASE + \
|
||||
(core) * PAXB_BASE_OFFSET)
|
||||
|
||||
#define PAXB_CLK_CTRL_OFFSET 0x000
|
||||
#define PAXB_EP_PERST_SRC_SEL_MASK (1 << 2)
|
||||
#define PAXB_EP_MODE_PERST_MASK (1 << 1)
|
||||
#define PAXB_RC_PCIE_RST_OUT_MASK (1 << 0)
|
||||
|
||||
#define PAXB_MAX_IMAP_WINDOWS 8
|
||||
#define PAXB_IMAP_REG_WIDTH 8
|
||||
#define PAXB_IMAP0_REG_WIDTH 4
|
||||
#define PAXB_AXUSER_REG_WIDTH 4
|
||||
|
||||
#define PAXB_CFG_IND_ADDR_OFFSET 0x120
|
||||
#define PAXB_CFG_IND_DATA_OFFSET 0x124
|
||||
#define PAXB_CFG_IND_ADDR_MASK 0x1ffc
|
||||
#define PAXB_CFG_CFG_TYPE_MASK 0x1
|
||||
|
||||
#define PAXB_EP_CFG_ADDR_OFFSET 0x1f8
|
||||
#define PAXB_EP_CFG_DATA_OFFSET 0x1fc
|
||||
#define PAXB_EP_CFG_ADDR_MASK 0xffc
|
||||
#define PAXB_EP_CFG_TYPE_MASK 0x1
|
||||
|
||||
#define PAXB_0_DEFAULT_IMAP 0xed0
|
||||
#define DEFAULT_ADDR_INVALID BIT(0)
|
||||
#define PAXB_0_DEFAULT_IMAP_AXUSER 0xed8
|
||||
#define PAXB_0_DEFAULT_IMAP_AXCACHE 0xedc
|
||||
#define IMAP_AXCACHE 0xff
|
||||
#define OARR_VALID BIT(0)
|
||||
#define IMAP_VALID BIT(0)
|
||||
|
||||
#define PAXB_IMAP0_BASE_OFFSET 0xc00
|
||||
#define PAXB_IARR0_BASE_OFFSET 0xd00
|
||||
#define PAXB_IMAP0_OFFSET(idx) (PAXB_IMAP0_BASE_OFFSET + \
|
||||
(idx) * PAXB_IMAP0_REG_WIDTH)
|
||||
#define PAXB_IMAP0_WINDOW_SIZE 0x1000
|
||||
|
||||
#define PAXB_IMAP2_OFFSET 0xcc0
|
||||
#define PAXB_IMAP0_REGS_TYPE_OFFSET 0xcd0
|
||||
#define PAXB_IARR2_LOWER_OFFSET 0xd10
|
||||
|
||||
#define PAXB_IMAP3_BASE_OFFSET 0xe08
|
||||
#define PAXB_IMAP3_OFFSET(idx) (PAXB_IMAP3_BASE_OFFSET + \
|
||||
(idx) * PAXB_IMAP_REG_WIDTH)
|
||||
|
||||
#define PAXB_IMAP3_0_AXUSER_B_OFFSET 0xe48
|
||||
#define PAXB_IMAP3_0_AXUSER_OFFSET(idx) (PAXB_IMAP3_0_AXUSER_B_OFFSET + \
|
||||
(idx) * PAXB_AXUSER_REG_WIDTH)
|
||||
|
||||
#define PAXB_IMAP4_BASE_OFFSET 0xe70
|
||||
#define PAXB_IMAP4_OFFSET(idx) (PAXB_IMAP4_BASE_OFFSET + \
|
||||
(idx) * PAXB_IMAP_REG_WIDTH)
|
||||
|
||||
#define PAXB_IMAP4_0_AXUSER_B_OFFSET 0xeb0
|
||||
#define PAXB_IMAP4_0_AXUSER_OFFSET(idx) (PAXB_IMAP4_0_AXUSER_B_OFFSET + \
|
||||
(idx) * PAXB_AXUSER_REG_WIDTH)
|
||||
|
||||
#define PAXB_CFG_LINK_STATUS_OFFSET 0xf0c
|
||||
#define PAXB_CFG_PHYLINKUP_MASK (1 << 3)
|
||||
#define PAXB_CFG_DL_ACTIVE_MASK (1 << 2)
|
||||
|
||||
#define PAXB_IMAP0_0_AXUSER_OFFSET 0xf60
|
||||
#define PAXB_IMAP2_AXUSER_OFFSET 0xfe0
|
||||
|
||||
/* cacheable write-back, allocate on both reads and writes */
|
||||
#define IMAP_ARCACHE 0x0f0
|
||||
#define IMAP_AWCACHE 0xf00
|
||||
/* normal access, nonsecure access, and data access */
|
||||
/* AWQOS:0xe and ARQOS:0xa */
|
||||
/* AWPROT:0x2 and ARPROT:0x1 */
|
||||
#define IMAP_AXUSER 0x002e002a
|
||||
|
||||
/*
|
||||
* List of NIC security and PIPEMUX related registers
|
||||
*/
|
||||
#define SR_PCIE_NIC_SECURITY_BASE 0x58100000
|
||||
#define NS3Z_PCIE_NIC_SECURITY_BASE 0x48100000
|
||||
|
||||
#define GITS_TRANSLATER 0x63c30000
|
||||
|
||||
#define VENDOR_ID 0x14e4
|
||||
#define CFG_RC_DEV_ID 0x434
|
||||
#define CFG_RC_DEV_SUBID 0x438
|
||||
#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
|
||||
#define PCI_CLASS_BRIDGE_MASK 0xffff00
|
||||
#define PCI_CLASS_BRIDGE_SHIFT 8
|
||||
#define PCI_CLASS_BRIDGE_PCI 0x0604
|
||||
|
||||
/*
|
||||
* List of PAXB RC configuration space registers
|
||||
*/
|
||||
|
||||
/* first capability list entry */
|
||||
#define PCI_CAPABILITY_LIST_OFFSET 0x34
|
||||
#define PCI_CAPABILITY_SPEED_OFFSET 0xc
|
||||
#define PCI_EP_CAPABILITY_OFFSET 0x10
|
||||
|
||||
#define CFG_RC_LINK_STATUS_CTRL_2 0x0dc
|
||||
#define CFG_RC_LINK_SPEED_SHIFT 0
|
||||
#define CFG_RC_LINK_SPEED_MASK (0xf << CFG_RC_LINK_SPEED_SHIFT)
|
||||
|
||||
#define CFG_RC_DEVICE_CAP 0x4d4
|
||||
#define CFG_RC_DEVICE_CAP_MPS_SHIFT 0
|
||||
#define CFG_RC_DEVICE_CAP_MPS_MASK (0x7 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
|
||||
/* MPS 256 bytes */
|
||||
#define CFG_RC_DEVICE_CAP_MPS_256B (0x1 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
|
||||
/* MPS 512 bytes */
|
||||
#define CFG_RC_DEVICE_CAP_MPS_512B (0x2 << CFG_RC_DEVICE_CAP_MPS_SHIFT)
|
||||
|
||||
#define CFG_RC_TL_FCIMM_NP_LIMIT 0xa10
|
||||
#define CFG_RC_TL_FCIMM_NP_VAL 0x01500000
|
||||
#define CFG_RC_TL_FCIMM_P_LIMIT 0xa14
|
||||
#define CFG_RC_TL_FCIMM_P_VAL 0x03408080
|
||||
|
||||
#define CFG_RC_LINK_CAP 0x4dc
|
||||
#define CFG_RC_LINK_CAP_SPEED_SHIFT 0
|
||||
#define CFG_RC_LINK_CAP_SPEED_MASK (0xf << CFG_RC_LINK_CAP_SPEED_SHIFT)
|
||||
#define CFG_RC_LINK_CAP_WIDTH_SHIFT 4
|
||||
#define CFG_RC_LINK_CAP_WIDTH_MASK (0x1f << CFG_RC_LINK_CAP_WIDTH_SHIFT)
|
||||
|
||||
#define CFG_LINK_CAP_RC 0x4f0
|
||||
#define CFG_RC_DL_ACTIVE_SHIFT 0
|
||||
#define CFG_RC_DL_ACTIVE_MASK (0x1 << CFG_RC_DL_ACTIVE_SHIFT)
|
||||
#define CFG_RC_SLOT_CLK_SHIFT 1
|
||||
#define CFG_RC_SLOT_CLK_MASK (0x1 << CFG_RC_SLOT_CLK_SHIFT)
|
||||
|
||||
#define CFG_ROOT_CAP_RC 0x4f8
|
||||
#define CFG_ROOT_CAP_LTR_SHIFT 1
|
||||
#define CFG_ROOT_CAP_LTR_MASK (0x1 << CFG_ROOT_CAP_LTR_SHIFT)
|
||||
|
||||
#define CFG_RC_CLKREQ_ENABLED 0x4fc
|
||||
#define CFG_RC_CLKREQ_ENABLED_SHIFT 0
|
||||
#define CFG_RC_CLKREQ_ENABLED_MASK (0x1 << CFG_RC_CLKREQ_ENABLED_SHIFT)
|
||||
|
||||
#define CFG_RC_COEFF_ADDR 0x638
|
||||
|
||||
#define CFG_RC_TL_CTRL_0 0x800
|
||||
#define RC_MEM_DW_CHK_MASK 0x03fe
|
||||
|
||||
#define CFG_RC_PDL_CTRL_4 0x1010
|
||||
#define NPH_FC_INIT_SHIFT 24
|
||||
#define NPH_FC_INIT_MASK (U(0xff) << NPH_FC_INIT_SHIFT)
|
||||
#define PD_FC_INIT_SHIFT 12
|
||||
#define PD_FC_INIT_MASK (0xffff << PD_FC_INIT_SHIFT)
|
||||
|
||||
#define CFG_RC_PDL_CTRL_5 0x1014
|
||||
#define PH_INIT_SHIFT 0
|
||||
#define PH_INIT_MASK (0xff << PH_INIT_SHIFT)
|
||||
|
||||
#define DL_STATUS_OFFSET 0x1048
|
||||
#define PHYLINKUP BIT(13)
|
||||
|
||||
#define PH_INIT 0x10
|
||||
#define PD_FC_INIT 0x100
|
||||
#define NPH_FC_INIT 0x8
|
||||
|
||||
#define SRP_PH_INIT 0x7F
|
||||
#define SRP_PD_FC_INIT 0x200
|
||||
#define SRP_NPH_FC_INIT 0x7F
|
||||
|
||||
#define CFG_ADDR_BUS_NUM_SHIFT 20
|
||||
#define CFG_ADDR_DEV_NUM_SHIFT 15
|
||||
#define CFG_ADDR_FUNC_NUM_SHIFT 12
|
||||
#define CFG_ADDR_REG_NUM_SHIFT 2
|
||||
#define CFG_ADDR_REG_NUM_MASK 0x00000ffc
|
||||
#define CFG_ADDR_CFG_TYPE_MASK 0x00000003
|
||||
|
||||
#define DL_LINK_UP_TIMEOUT_MS 1000
|
||||
|
||||
#define CFG_RETRY_STATUS 0xffff0001
|
||||
#define CRS_TIMEOUT_MS 5000
|
||||
|
||||
/* create EP config data to write */
|
||||
#define DEF_BUS_NO 1 /* default bus 1 */
|
||||
#define DEF_SLOT_NO 0 /* default slot 0 */
|
||||
#define DEF_FN_NO 0 /* default fn 0 */
|
||||
|
||||
#define EP_CONFIG_VAL(bus_no, slot, fn, where) \
|
||||
(((bus_no) << CFG_ADDR_BUS_NUM_SHIFT) | \
|
||||
((slot) << CFG_ADDR_DEV_NUM_SHIFT) | \
|
||||
((fn) << CFG_ADDR_FUNC_NUM_SHIFT) | \
|
||||
((where) & CFG_ADDR_REG_NUM_MASK) | \
|
||||
(1 & CFG_ADDR_CFG_TYPE_MASK))
|
||||
|
||||
/* PAXB security offset */
|
||||
#define PAXB_SECURITY_IDM_OFFSET 0x1c
|
||||
#define PAXB_SECURITY_APB_OFFSET 0x24
|
||||
#define PAXB_SECURITY_ECAM_OFFSET 0x3c
|
||||
|
||||
#define paxb_get_config(type) paxb_get_##type##_config()
|
||||
|
||||
static unsigned int paxb_sec_reg_offset[] = {
|
||||
0x0c, /* PAXB0 AXI */
|
||||
0x10, /* PAXB1 AXI */
|
||||
0x14, /* PAXB2 AXI */
|
||||
0x18, /* PAXB3 AXI */
|
||||
0x20, /* PAXB4 AXI */
|
||||
0x28, /* PAXB5 AXI */
|
||||
0x2c, /* PAXB6 AXI */
|
||||
0x30, /* PAXB7 AXI */
|
||||
0x24, /* PAXB APB */
|
||||
};
|
||||
|
||||
const paxb_cfg *paxb;
|
||||
|
||||
/*
|
||||
* Given a PIPEMUX strap and PCIe core index, this function returns 1 if a
|
||||
* PCIe core needs to be enabled
|
||||
*/
|
||||
int pcie_core_needs_enable(unsigned int core_idx)
|
||||
{
|
||||
if (paxb->core_needs_enable)
|
||||
return paxb->core_needs_enable(core_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcie_set_default_tx_coeff(uint32_t core_idx, uint32_t link_width)
|
||||
{
|
||||
unsigned int lanes = 0;
|
||||
uint32_t data, addr;
|
||||
|
||||
addr = CFG_RC_COEFF_ADDR;
|
||||
for (lanes = 0; lanes < link_width; lanes = lanes + 2) {
|
||||
data = paxb_rc_cfg_read(core_idx, addr);
|
||||
data &= 0xf0f0f0f0;
|
||||
data |= (7 & 0xf);
|
||||
data |= (7 & 0xf) << 8;
|
||||
data |= (7 & 0xf) << 16;
|
||||
data |= (7 & 0xf) << 24;
|
||||
|
||||
paxb_rc_cfg_write(core_idx, addr, data);
|
||||
addr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static int paxb_rc_link_init(void)
|
||||
{
|
||||
uint32_t val, link_speed;
|
||||
unsigned int link_width;
|
||||
uint32_t core_idx;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
link_width = paxb->get_link_width(core_idx);
|
||||
if (!link_width) {
|
||||
ERROR("Unsupported PIPEMUX\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
link_speed = paxb->get_link_speed();
|
||||
/* program RC's link cap reg to advertise proper link width */
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
|
||||
val &= ~CFG_RC_LINK_CAP_WIDTH_MASK;
|
||||
val |= (link_width << CFG_RC_LINK_CAP_WIDTH_SHIFT);
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
|
||||
|
||||
/* program RC's link cap reg to advertise proper link speed */
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_CAP);
|
||||
val &= ~CFG_RC_LINK_CAP_SPEED_MASK;
|
||||
val |= link_speed << CFG_RC_LINK_CAP_SPEED_SHIFT;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_LINK_CAP, val);
|
||||
|
||||
/* also need to program RC's link status control register */
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_LINK_STATUS_CTRL_2);
|
||||
val &= ~(CFG_RC_LINK_SPEED_MASK);
|
||||
val |= link_speed << CFG_RC_LINK_SPEED_SHIFT;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_LINK_STATUS_CTRL_2, val);
|
||||
|
||||
#ifdef WAR_PLX_PRESET_PARITY_FAIL
|
||||
/* WAR to avoid crash with PLX switch in GEN3*/
|
||||
/* While PRESET, PLX switch is not fixing parity so disabled */
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_REG_PHY_CTL_10);
|
||||
val &= ~(PHY_CTL_10_GEN3_MATCH_PARITY);
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_REG_PHY_CTL_10, val);
|
||||
#endif
|
||||
pcie_set_default_tx_coeff(core_idx, link_width);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PAXB_LINKUP
|
||||
static void paxb_perst_ctrl(unsigned int core_idx, bool assert)
|
||||
{
|
||||
uint32_t clk_ctrl = PAXB_OFFSET(core_idx) + PAXB_CLK_CTRL_OFFSET;
|
||||
|
||||
if (assert) {
|
||||
mmio_clrbits_32(clk_ctrl, PAXB_EP_PERST_SRC_SEL_MASK |
|
||||
PAXB_EP_MODE_PERST_MASK |
|
||||
PAXB_RC_PCIE_RST_OUT_MASK);
|
||||
udelay(250);
|
||||
} else {
|
||||
mmio_setbits_32(clk_ctrl, PAXB_RC_PCIE_RST_OUT_MASK);
|
||||
mdelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_start_link_up(void)
|
||||
{
|
||||
unsigned int core_idx;
|
||||
uint32_t val, timeout;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
/* toggle PERST */
|
||||
paxb_perst_ctrl(core_idx, true);
|
||||
paxb_perst_ctrl(core_idx, false);
|
||||
|
||||
timeout = DL_LINK_UP_TIMEOUT_MS;
|
||||
/* wait for Link up */
|
||||
do {
|
||||
val = mmio_read_32(PAXB_OFFSET(core_idx) +
|
||||
PAXB_CFG_LINK_STATUS_OFFSET);
|
||||
if (val & PAXB_CFG_DL_ACTIVE_MASK)
|
||||
break;
|
||||
|
||||
mdelay(1);
|
||||
} while (--timeout);
|
||||
|
||||
if (!timeout)
|
||||
ERROR("PAXB core %u link is down\n", core_idx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void pcie_core_soft_reset(unsigned int core_idx)
|
||||
{
|
||||
uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
|
||||
uintptr_t ctrl = (uintptr_t)(PCIE_CORE_SOFT_RST_CFG_BASE + offset);
|
||||
|
||||
/* Put PCIe core in soft reset */
|
||||
mmio_clrbits_32(ctrl, PCIE_CORE_SOFT_RST);
|
||||
|
||||
/* Wait for 1 us before pulling PCIe core out of soft reset */
|
||||
udelay(PCIE_CORE_SOFT_RST_DELAY_US);
|
||||
|
||||
mmio_setbits_32(ctrl, PCIE_CORE_SOFT_RST);
|
||||
}
|
||||
|
||||
static int pcie_core_pwron_switch(uintptr_t ctrl, uintptr_t status,
|
||||
uint32_t mask)
|
||||
{
|
||||
uint32_t val;
|
||||
unsigned int timeout = PCIE_CORE_PWR_TIMEOUT_MS;
|
||||
|
||||
/* enable switch */
|
||||
mmio_setbits_32(ctrl, mask);
|
||||
|
||||
/* now wait for it to stabilize */
|
||||
do {
|
||||
val = mmio_read_32(status);
|
||||
if ((val & mask) == mask)
|
||||
return 0;
|
||||
mdelay(1);
|
||||
} while (--timeout);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int pcie_core_pwr_seq(uintptr_t ctrl, uintptr_t status)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Enable the switch with the following sequence:
|
||||
* 1. Array weak switch output switch
|
||||
* 2. Array strong switch
|
||||
* 3. Weak switch output acknowledge
|
||||
* 4. Strong switch output acknowledge
|
||||
*/
|
||||
ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWERON);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_ARR_POWEROK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWERON);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pcie_core_pwron_switch(ctrl, status, PCIE_CORE_PWR_POWEROK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function enables PCIe core and PAXB memory buffer power, and then
|
||||
* remove the PCIe core from isolation
|
||||
*/
|
||||
static int pcie_core_pwr_init(unsigned int core_idx)
|
||||
{
|
||||
int ret;
|
||||
uint32_t offset = core_idx * PCIE_CORE_PWR_OFFSET;
|
||||
uintptr_t ctrl, status;
|
||||
|
||||
/* enable mem power to PCIe core */
|
||||
ctrl = (uintptr_t)(PCIE_CORE_MEM_PWR_BASE + offset);
|
||||
status = (uintptr_t)(PCIE_CORE_MEM_PWR_STATUS_BASE + offset);
|
||||
ret = pcie_core_pwr_seq(ctrl, status);
|
||||
if (ret) {
|
||||
ERROR("PCIe core mem power failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* now enable mem power to PAXB wrapper */
|
||||
ctrl = (uintptr_t)(PCIE_PAXB_MEM_PWR_BASE + offset);
|
||||
status = (uintptr_t)(PCIE_PAXB_MEM_PWR_STATUS_BASE + offset);
|
||||
ret = pcie_core_pwr_seq(ctrl, status);
|
||||
if (ret) {
|
||||
ERROR("PAXB mem power failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* now remove power isolation */
|
||||
ctrl = (uintptr_t)(PCIE_CORE_ISO_CFG_BASE + offset);
|
||||
mmio_clrbits_32(ctrl, PCIE_CORE_ISO | PCIE_CORE_MEM_ISO);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcie_ss_reset(void)
|
||||
{
|
||||
mmio_setbits_32(CDRU_MISC_RESET_CONTROL,
|
||||
1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function reads the PIPEMUX strap, figures out all the PCIe cores that
|
||||
* need to be enabled and enable the mem power for those cores
|
||||
*/
|
||||
static int pcie_cores_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t core_idx;
|
||||
|
||||
if (paxb->pipemux_init) {
|
||||
ret = paxb->pipemux_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* bring PCIe subsystem out of reset */
|
||||
pcie_ss_reset();
|
||||
|
||||
/* power up all PCIe cores that will be used as RC */
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
ret = pcie_core_pwr_init(core_idx);
|
||||
if (ret) {
|
||||
ERROR("PCIe core %u power up failed\n", core_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pcie_core_soft_reset(core_idx);
|
||||
|
||||
VERBOSE("PCIe core %u is powered up\n", core_idx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void paxb_rc_cfg_write(unsigned int core_idx, unsigned int where,
|
||||
uint32_t val)
|
||||
{
|
||||
mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
|
||||
(where & PAXB_CFG_IND_ADDR_MASK) |
|
||||
PAXB_CFG_CFG_TYPE_MASK);
|
||||
mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET, val);
|
||||
}
|
||||
|
||||
unsigned int paxb_rc_cfg_read(unsigned int core_idx, unsigned int where)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_ADDR_OFFSET,
|
||||
(where & PAXB_CFG_IND_ADDR_MASK) |
|
||||
PAXB_CFG_CFG_TYPE_MASK);
|
||||
val = mmio_read_32(PAXB_OFFSET(core_idx) + PAXB_CFG_IND_DATA_OFFSET);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void paxb_cfg_mps(void)
|
||||
{
|
||||
uint32_t val, core_idx, mps;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_DEVICE_CAP);
|
||||
val &= ~CFG_RC_DEVICE_CAP_MPS_MASK;
|
||||
mps = CFG_RC_DEVICE_CAP_MPS_256B;
|
||||
if (core_idx == 0 || core_idx == 1 ||
|
||||
core_idx == 6 || core_idx == 7) {
|
||||
mps = CFG_RC_DEVICE_CAP_MPS_512B;
|
||||
}
|
||||
val |= mps;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_DEVICE_CAP, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_dev_id(void)
|
||||
{
|
||||
uint32_t val, core_idx;
|
||||
uint32_t device_id;
|
||||
|
||||
device_id = paxb->device_id;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
/* Set Core in RC mode */
|
||||
mmio_setbits_32(PCIE_CORE_USER_CFG +
|
||||
(core_idx * PCIE_CORE_PWR_OFFSET), 1);
|
||||
|
||||
/* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
|
||||
val = paxb_rc_cfg_read(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET);
|
||||
val &= ~PCI_CLASS_BRIDGE_MASK;
|
||||
val |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
|
||||
paxb_rc_cfg_write(core_idx, PCI_BRIDGE_CTRL_REG_OFFSET, val);
|
||||
|
||||
val = (VENDOR_ID << 16) | device_id;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_DEV_ID, val);
|
||||
|
||||
val = (device_id << 16) | VENDOR_ID;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_DEV_SUBID, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_tgt_trn(void)
|
||||
{
|
||||
uint32_t val, core_idx;
|
||||
|
||||
/*
|
||||
* Disable all mem Rd/Wr size check so it allows target read/write
|
||||
* transactions to be more than stipulated DW. As a result, PAXB root
|
||||
* complex will not abort these read/write transcations beyond
|
||||
* stipulated limit
|
||||
*/
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_TL_CTRL_0);
|
||||
val &= ~(RC_MEM_DW_CHK_MASK);
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_TL_CTRL_0, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_pdl_ctrl(void)
|
||||
{
|
||||
uint32_t val, core_idx;
|
||||
uint32_t nph, ph, pd;
|
||||
|
||||
/* increase the credit counter to 4 for non-posted header */
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
nph = NPH_FC_INIT;
|
||||
ph = PH_INIT;
|
||||
pd = PD_FC_INIT;
|
||||
|
||||
if (core_idx == 0 || core_idx == 1 ||
|
||||
core_idx == 6 || core_idx == 7) {
|
||||
nph = SRP_NPH_FC_INIT;
|
||||
ph = SRP_PH_INIT;
|
||||
pd = SRP_PD_FC_INIT;
|
||||
}
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_4);
|
||||
val &= ~NPH_FC_INIT_MASK;
|
||||
val &= ~PD_FC_INIT_MASK;
|
||||
val = val | (nph << NPH_FC_INIT_SHIFT);
|
||||
val = val | (pd << PD_FC_INIT_SHIFT);
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_4, val);
|
||||
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_PDL_CTRL_5);
|
||||
val &= ~PH_INIT_MASK;
|
||||
val = val | (ph << PH_INIT_SHIFT);
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_PDL_CTRL_5, val);
|
||||
|
||||
/*
|
||||
* ASIC to give more optmized value after further investigation.
|
||||
* till then this is important to have to get similar
|
||||
* performance on all the slots.
|
||||
*/
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_NP_LIMIT,
|
||||
CFG_RC_TL_FCIMM_NP_VAL);
|
||||
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_TL_FCIMM_P_LIMIT,
|
||||
CFG_RC_TL_FCIMM_P_VAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_clkreq(void)
|
||||
{
|
||||
uint32_t val, core_idx;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_RC_CLKREQ_ENABLED);
|
||||
val &= ~CFG_RC_CLKREQ_ENABLED_MASK;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_CLKREQ_ENABLED, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_dl_active(bool enable)
|
||||
{
|
||||
uint32_t val, core_idx;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_LINK_CAP_RC);
|
||||
if (enable)
|
||||
val |= CFG_RC_DL_ACTIVE_MASK;
|
||||
else
|
||||
val &= ~CFG_RC_DL_ACTIVE_MASK;
|
||||
paxb_rc_cfg_write(core_idx, CFG_LINK_CAP_RC, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_LTR(int enable)
|
||||
{
|
||||
uint32_t val, core_idx;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
val = paxb_rc_cfg_read(core_idx, CFG_ROOT_CAP_RC);
|
||||
if (enable)
|
||||
val |= CFG_ROOT_CAP_LTR_MASK;
|
||||
else
|
||||
val &= ~CFG_ROOT_CAP_LTR_MASK;
|
||||
paxb_rc_cfg_write(core_idx, CFG_ROOT_CAP_RC, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_ib_regs_bypass(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < paxb->num_cores; i++) {
|
||||
if (!pcie_core_needs_enable(i))
|
||||
continue;
|
||||
|
||||
/* Configure Default IMAP window */
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP,
|
||||
DEFAULT_ADDR_INVALID);
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXUSER,
|
||||
IMAP_AXUSER);
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_0_DEFAULT_IMAP_AXCACHE,
|
||||
IMAP_AXCACHE);
|
||||
|
||||
/* Configure MSI IMAP window */
|
||||
mmio_setbits_32(PAXB_OFFSET(i) +
|
||||
PAXB_IMAP0_REGS_TYPE_OFFSET,
|
||||
0x1);
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IARR0_BASE_OFFSET,
|
||||
GITS_TRANSLATER | OARR_VALID);
|
||||
for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
|
||||
(GITS_TRANSLATER +
|
||||
(j * PAXB_IMAP0_WINDOW_SIZE)) |
|
||||
IMAP_VALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_ib_regs_init(void)
|
||||
{
|
||||
unsigned int core_idx;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
/* initialize IARR2 to zero */
|
||||
mmio_write_32(PAXB_OFFSET(core_idx) + PAXB_IARR2_LOWER_OFFSET,
|
||||
0x0);
|
||||
mmio_setbits_32(PAXB_OFFSET(core_idx) +
|
||||
PAXB_IMAP0_REGS_TYPE_OFFSET,
|
||||
0x1);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_apb_timeout(void)
|
||||
{
|
||||
unsigned int core_idx;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
/* allow unlimited timeout */
|
||||
mmio_write_32(PAXB_OFFSET(core_idx) +
|
||||
PAXB_APB_TIMEOUT_COUNT_OFFSET,
|
||||
0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_smmu_cfg(void)
|
||||
{
|
||||
unsigned int core_idx;
|
||||
uint32_t offset;
|
||||
uint32_t val;
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
|
||||
offset = core_idx * PCIE_CORE_PWR_OFFSET;
|
||||
val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
|
||||
val &= ~(0xFFF00);
|
||||
val |= (PAXB_SMMU_SID_CFG_FUN_WIDTH |
|
||||
PAXB_SMMU_SID_CFG_DEV_WIDTH |
|
||||
PAXB_SMMU_SID_CFG_BUS_WIDTH);
|
||||
mmio_write_32(PCIE_PAXB_SMMU_SID_CFG + offset, val);
|
||||
val = mmio_read_32(PCIE_PAXB_SMMU_SID_CFG + offset);
|
||||
VERBOSE("smmu cfg reg 0x%x\n", val);
|
||||
}
|
||||
}
|
||||
|
||||
static void paxb_cfg_coherency(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < paxb->num_cores; i++) {
|
||||
if (!pcie_core_needs_enable(i))
|
||||
continue;
|
||||
|
||||
#ifdef USE_DDR
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_OFFSET,
|
||||
IMAP_ARCACHE | IMAP_AWCACHE);
|
||||
#endif
|
||||
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_0_AXUSER_OFFSET,
|
||||
IMAP_AXUSER);
|
||||
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP2_AXUSER_OFFSET,
|
||||
IMAP_AXUSER);
|
||||
|
||||
for (j = 0; j < PAXB_MAX_IMAP_WINDOWS; j++) {
|
||||
#ifdef USE_DDR
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP3_OFFSET(j),
|
||||
IMAP_ARCACHE | IMAP_AWCACHE);
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP4_OFFSET(j),
|
||||
IMAP_ARCACHE | IMAP_AWCACHE);
|
||||
#endif
|
||||
/* zero out IMAP0 mapping windows for MSI/MSI-X */
|
||||
mmio_write_32(PAXB_OFFSET(i) + PAXB_IMAP0_OFFSET(j),
|
||||
0x0);
|
||||
|
||||
mmio_write_32(PAXB_OFFSET(i) +
|
||||
PAXB_IMAP3_0_AXUSER_OFFSET(j),
|
||||
IMAP_AXUSER);
|
||||
mmio_write_32(PAXB_OFFSET(i) +
|
||||
PAXB_IMAP4_0_AXUSER_OFFSET(j),
|
||||
IMAP_AXUSER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function configures all PAXB related blocks to allow non-secure access
|
||||
*/
|
||||
void paxb_ns_init(enum paxb_type type)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
switch (type) {
|
||||
case PAXB_SR:
|
||||
for (reg = 0; reg < ARRAY_SIZE(paxb_sec_reg_offset); reg++) {
|
||||
|
||||
mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE +
|
||||
paxb_sec_reg_offset[reg], 0x1);
|
||||
}
|
||||
/* Enabled all PAXB's relevant IDM blocks access in non-secure mode */
|
||||
mmio_setbits_32(SR_PCIE_NIC_SECURITY_BASE + PAXB_SECURITY_IDM_OFFSET,
|
||||
0xffff);
|
||||
break;
|
||||
case PAXB_NS3Z:
|
||||
mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
|
||||
paxb_sec_reg_offset[0], 0x1);
|
||||
mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
|
||||
PAXB_SECURITY_IDM_OFFSET, 0xffff);
|
||||
mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
|
||||
PAXB_SECURITY_APB_OFFSET, 0x7);
|
||||
mmio_setbits_32(NS3Z_PCIE_NIC_SECURITY_BASE +
|
||||
PAXB_SECURITY_ECAM_OFFSET, 0x1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int paxb_set_config(void)
|
||||
{
|
||||
paxb = paxb_get_config(sr);
|
||||
if (paxb)
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void paxb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = paxb_set_config();
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
paxb_ns_init(paxb->type);
|
||||
|
||||
ret = pcie_cores_init();
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (paxb->phy_init) {
|
||||
ret = paxb->phy_init();
|
||||
if (ret)
|
||||
return;
|
||||
}
|
||||
|
||||
paxb_cfg_dev_id();
|
||||
paxb_cfg_tgt_trn();
|
||||
paxb_cfg_pdl_ctrl();
|
||||
if (paxb->type == PAXB_SR) {
|
||||
paxb_ib_regs_init();
|
||||
paxb_cfg_coherency();
|
||||
} else
|
||||
paxb_ib_regs_bypass();
|
||||
|
||||
paxb_cfg_apb_timeout();
|
||||
paxb_smmu_cfg();
|
||||
paxb_cfg_clkreq();
|
||||
paxb_rc_link_init();
|
||||
|
||||
/* Stingray Doesn't support LTR */
|
||||
paxb_cfg_LTR(false);
|
||||
paxb_cfg_dl_active(true);
|
||||
|
||||
paxb_cfg_mps();
|
||||
|
||||
#ifdef PAXB_LINKUP
|
||||
paxb_start_link_up();
|
||||
#endif
|
||||
INFO("PAXB init done\n");
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2017 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <iommu.h>
|
||||
#include <platform_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
#define PAXC_BASE 0x60400000
|
||||
#define PAXC_AXI_CFG_PF 0x10
|
||||
#define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4)
|
||||
#define PAXC_ARPROT_PF_CFG 0x40
|
||||
#define PAXC_AWPROT_PF_CFG 0x44
|
||||
|
||||
#define PAXC_ARQOS_PF_CFG 0x48
|
||||
#define PAXC_ARQOS_VAL 0xaaaaaaaa
|
||||
|
||||
#define PAXC_AWQOS_PF_CFG 0x4c
|
||||
#define PAXC_AWQOS_VAL 0xeeeeeeee
|
||||
|
||||
#define PAXC_CFG_IND_ADDR_OFFSET 0x1f0
|
||||
#define PAXC_CFG_IND_ADDR_MASK 0xffc
|
||||
#define PAXC_CFG_IND_DATA_OFFSET 0x1f4
|
||||
|
||||
/* offsets for PAXC root complex configuration space registers */
|
||||
|
||||
#define PAXC_CFG_ID_OFFSET 0x434
|
||||
#define PAXC_RC_VENDOR_ID 0x14e4
|
||||
#define PAXC_RC_VENDOR_ID_SHIFT 16
|
||||
|
||||
#define PAXC_RC_DEVICE_ID 0xd750
|
||||
|
||||
#define PAXC_CFG_LINK_CAP_OFFSET 0x4dc
|
||||
#define PAXC_RC_LINK_CAP_SPD_SHIFT 0
|
||||
#define PAXC_RC_LINK_CAP_SPD_MASK (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT)
|
||||
#define PAXC_RC_LINK_CAP_SPD 3
|
||||
#define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4
|
||||
#define PAXC_RC_LINK_CAP_WIDTH_MASK (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT)
|
||||
#define PAXC_RC_LINK_CAP_WIDTH 16
|
||||
|
||||
/* offsets for MHB registers */
|
||||
|
||||
#define MHB_BASE 0x60401000
|
||||
#define MHB_MEM_PWR_STATUS_PAXC (MHB_BASE + 0x1c0)
|
||||
#define MHB_PWR_ARR_POWERON 0x8
|
||||
#define MHB_PWR_ARR_POWEROK 0x4
|
||||
#define MHB_PWR_POWERON 0x2
|
||||
#define MHB_PWR_POWEROK 0x1
|
||||
#define MHB_PWR_STATUS_MASK (MHB_PWR_ARR_POWERON | \
|
||||
MHB_PWR_ARR_POWEROK | \
|
||||
MHB_PWR_POWERON | \
|
||||
MHB_PWR_POWEROK)
|
||||
|
||||
/* max number of PFs from Nitro that PAXC sees */
|
||||
#define MAX_NR_NITRO_PF 8
|
||||
|
||||
#ifdef EMULATION_SETUP
|
||||
static void paxc_reg_dump(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
/* total number of PAXC registers */
|
||||
#define NR_PAXC_REGS 53
|
||||
static void paxc_reg_dump(void)
|
||||
{
|
||||
uint32_t idx, offset = 0;
|
||||
|
||||
VERBOSE("PAXC register dump start\n");
|
||||
for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4)
|
||||
VERBOSE("offset: 0x%x val: 0x%x\n", offset,
|
||||
mmio_read_32(PAXC_BASE + offset));
|
||||
VERBOSE("PAXC register dump end\n");
|
||||
}
|
||||
#endif /* EMULATION_SETUP */
|
||||
|
||||
#ifdef EMULATION_SETUP
|
||||
static void mhb_reg_dump(void)
|
||||
{
|
||||
}
|
||||
#else
|
||||
#define NR_MHB_REGS 227
|
||||
static void mhb_reg_dump(void)
|
||||
{
|
||||
uint32_t idx, offset = 0;
|
||||
|
||||
VERBOSE("MHB register dump start\n");
|
||||
for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4)
|
||||
VERBOSE("offset: 0x%x val: 0x%x\n", offset,
|
||||
mmio_read_32(MHB_BASE + offset));
|
||||
VERBOSE("MHB register dump end\n");
|
||||
}
|
||||
#endif /* EMULATION_SETUP */
|
||||
|
||||
static void paxc_rc_cfg_write(uint32_t where, uint32_t val)
|
||||
{
|
||||
mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
|
||||
where & PAXC_CFG_IND_ADDR_MASK);
|
||||
mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val);
|
||||
}
|
||||
|
||||
static uint32_t paxc_rc_cfg_read(uint32_t where)
|
||||
{
|
||||
mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
|
||||
where & PAXC_CFG_IND_ADDR_MASK);
|
||||
return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to program PAXC root complex link capability register
|
||||
*/
|
||||
static void paxc_cfg_link_cap(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET);
|
||||
val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK);
|
||||
val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) |
|
||||
(PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT);
|
||||
paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to program PAXC root complex vendor ID and device ID
|
||||
*/
|
||||
static void paxc_cfg_id(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) |
|
||||
PAXC_RC_DEVICE_ID;
|
||||
paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val);
|
||||
}
|
||||
|
||||
void paxc_init(void)
|
||||
{
|
||||
unsigned int pf_index;
|
||||
unsigned int val;
|
||||
|
||||
val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC);
|
||||
if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) {
|
||||
INFO("PAXC not powered\n");
|
||||
return;
|
||||
}
|
||||
|
||||
paxc_cfg_id();
|
||||
paxc_cfg_link_cap();
|
||||
|
||||
paxc_reg_dump();
|
||||
mhb_reg_dump();
|
||||
|
||||
#ifdef USE_DDR
|
||||
/*
|
||||
* Set AWCACHE and ARCACHE to 0xff (Cacheable write-back,
|
||||
* allocate on both reads and writes) per
|
||||
* recommendation from the ASIC team
|
||||
*/
|
||||
val = 0xff;
|
||||
#else
|
||||
/* disable IO cache if non-DDR memory is used, e.g., external SRAM */
|
||||
val = 0x0;
|
||||
#endif
|
||||
for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++)
|
||||
mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index),
|
||||
val);
|
||||
|
||||
/*
|
||||
* Set ARPROT and AWPROT to enable non-secure access from
|
||||
* PAXC to all PFs, PF0 to PF7
|
||||
*/
|
||||
mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222);
|
||||
mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222);
|
||||
|
||||
mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL);
|
||||
mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL);
|
||||
|
||||
INFO("PAXC init done\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* These defines do not match the regfile but they are renamed in a way such
|
||||
* that they are much more readible
|
||||
*/
|
||||
|
||||
#define MHB_NIC_SECURITY_BASE 0x60500000
|
||||
#define MHB_NIC_PAXC_AXI_NS 0x0008
|
||||
#define MHB_NIC_IDM_NS 0x000c
|
||||
#define MHB_NIC_MHB_APB_NS 0x0010
|
||||
#define MHB_NIC_NITRO_AXI_NS 0x0014
|
||||
#define MHB_NIC_PCIE_AXI_NS 0x0018
|
||||
#define MHB_NIC_PAXC_APB_NS 0x001c
|
||||
#define MHB_NIC_EP_APB_NS 0x0020
|
||||
|
||||
#define MHB_NIC_PAXC_APB_S_IDM_SHIFT 5
|
||||
#define MHB_NIC_EP_APB_S_IDM_SHIFT 4
|
||||
#define MHB_NIC_MHB_APB_S_IDM_SHIFT 3
|
||||
#define MHB_NIC_PAXC_AXI_S_IDM_SHIFT 2
|
||||
#define MHB_NIC_PCIE_AXI_S_IDM_SHIFT 1
|
||||
#define MHB_NIC_NITRO_AXI_S_IDM_SHIFT 0
|
||||
|
||||
#define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000
|
||||
|
||||
#define NITRO_NIC_SECURITY_3_SHIFT 0x14
|
||||
#define NITRO_NIC_SECURITY_4_SHIFT 0x18
|
||||
#define NITRO_NIC_SECURITY_5_SHIFT 0x1c
|
||||
#define NITRO_NIC_SECURITY_6_SHIFT 0x20
|
||||
|
||||
void paxc_mhb_ns_init(void)
|
||||
{
|
||||
unsigned int val;
|
||||
uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE;
|
||||
#ifndef NITRO_SECURE_ACCESS
|
||||
uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE;
|
||||
#endif /* NITRO_SECURE_ACCESS */
|
||||
|
||||
/* set PAXC AXI to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS);
|
||||
val |= 0x1;
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val);
|
||||
|
||||
/* set various MHB IDM interfaces to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS);
|
||||
val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT);
|
||||
val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT);
|
||||
val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT);
|
||||
val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT);
|
||||
val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT);
|
||||
val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT);
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val);
|
||||
|
||||
/* set MHB APB to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS);
|
||||
val |= 0x1;
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val);
|
||||
|
||||
/* set Nitro AXI to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS);
|
||||
val |= 0x1;
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val);
|
||||
|
||||
/* set PCIe AXI to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS);
|
||||
val |= 0x1;
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val);
|
||||
|
||||
/* set PAXC APB to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS);
|
||||
val |= 0x1;
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val);
|
||||
|
||||
/* set EP APB to allow non-secure access */
|
||||
val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS);
|
||||
val |= 0x1;
|
||||
mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val);
|
||||
|
||||
#ifndef NITRO_SECURE_ACCESS
|
||||
/* Set NIC400 to allow non-secure access */
|
||||
mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1);
|
||||
mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1);
|
||||
mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1);
|
||||
mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1);
|
||||
#endif /* NITRO_SECURE_ACCESS */
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2015 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/ccn.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/spinlock.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#ifdef USE_PAXC
|
||||
#include <chimp.h>
|
||||
#endif
|
||||
#include <cmn_plat_util.h>
|
||||
#include <ihost_pm.h>
|
||||
#include <plat_brcm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static uint64_t plat_sec_entrypoint;
|
||||
|
||||
/*******************************************************************************
|
||||
* SR handler called when a power domain is about to be turned on. The
|
||||
* mpidr determines the CPU to be turned on.
|
||||
******************************************************************************/
|
||||
static int brcm_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
int cpuid;
|
||||
|
||||
cpuid = plat_brcm_calc_core_pos(mpidr);
|
||||
INFO("mpidr :%lu, cpuid:%d\n", mpidr, cpuid);
|
||||
|
||||
#ifdef USE_SINGLE_CLUSTER
|
||||
if (cpuid > 1)
|
||||
return PSCI_E_INTERN_FAIL;
|
||||
#endif
|
||||
|
||||
ihost_power_on_cluster(mpidr);
|
||||
|
||||
ihost_power_on_secondary_core(mpidr, plat_sec_entrypoint);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* SR 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.
|
||||
******************************************************************************/
|
||||
static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr());
|
||||
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
|
||||
PLAT_LOCAL_STATE_OFF) {
|
||||
INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id);
|
||||
ccn_enter_snoop_dvm_domain(1 << cluster_id);
|
||||
}
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
plat_brcm_gic_pcpu_init();
|
||||
|
||||
/* Program the gic per-cpu distributor or re-distributor interface */
|
||||
plat_brcm_gic_cpuif_enable();
|
||||
|
||||
INFO("Gic Initialization done for this affinity instance\n");
|
||||
}
|
||||
|
||||
static void __dead2 brcm_system_reset(void)
|
||||
{
|
||||
uint32_t reset_type = SOFT_SYS_RESET_L1;
|
||||
|
||||
#ifdef USE_PAXC
|
||||
if (bcm_chimp_is_nic_mode())
|
||||
reset_type = SOFT_RESET_L3;
|
||||
#endif
|
||||
INFO("System rebooting - L%d...\n", reset_type);
|
||||
|
||||
plat_soft_reset(reset_type);
|
||||
|
||||
/* Prevent the function to return due to the attribute */
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
static int brcm_system_reset2(int is_vendor, int reset_type,
|
||||
u_register_t cookie)
|
||||
{
|
||||
INFO("System rebooting - L%d...\n", reset_type);
|
||||
|
||||
plat_soft_reset(reset_type);
|
||||
|
||||
/*
|
||||
* plat_soft_reset cannot return (it is a __dead function),
|
||||
* but brcm_system_reset2 has to return some value, even in
|
||||
* this case.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard
|
||||
* platform will take care of registering the handlers with PSCI.
|
||||
******************************************************************************/
|
||||
const plat_psci_ops_t plat_brcm_psci_pm_ops = {
|
||||
.pwr_domain_on = brcm_pwr_domain_on,
|
||||
.pwr_domain_on_finish = brcm_pwr_domain_on_finish,
|
||||
.system_reset = brcm_system_reset,
|
||||
.system_reset2 = brcm_system_reset2
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
*psci_ops = &plat_brcm_psci_pm_ops;
|
||||
plat_sec_entrypoint = sec_entrypoint;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <scp.h>
|
||||
#include <scp_cmd.h>
|
||||
|
||||
#include "m0_ipc.h"
|
||||
|
||||
/*
|
||||
* Reads a response from CRMU MAILBOX
|
||||
* Assumes that access has been granted and locked.
|
||||
* Note that this is just a temporary implementation until
|
||||
* channels are introduced
|
||||
*/
|
||||
static void scp_read_response(crmu_response_t *resp)
|
||||
{
|
||||
uint32_t code;
|
||||
|
||||
code = mmio_read_32(CRMU_MAIL_BOX0);
|
||||
resp->completed = code & MCU_IPC_CMD_DONE_MASK;
|
||||
resp->cmd = code & SCP_CMD_MASK;
|
||||
resp->ret = (code & MCU_IPC_CMD_REPLY_MASK) >> MCU_IPC_CMD_REPLY_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a command to SCP and wait for timeout us.
|
||||
* Return: 0 on success
|
||||
* -1 if there was no proper reply from SCP
|
||||
* >0 if there was a response from MCU, but
|
||||
* command completed with an error.
|
||||
*/
|
||||
int scp_send_cmd(uint32_t cmd, uint32_t param, uint32_t timeout)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
mmio_write_32(CRMU_MAIL_BOX0, cmd);
|
||||
mmio_write_32(CRMU_MAIL_BOX1, param);
|
||||
do {
|
||||
crmu_response_t scp_resp;
|
||||
|
||||
udelay(1);
|
||||
scp_read_response(&scp_resp);
|
||||
if (scp_resp.completed &&
|
||||
(scp_resp.cmd == cmd)) {
|
||||
/* This command has completed */
|
||||
ret = scp_resp.ret;
|
||||
break;
|
||||
}
|
||||
} while (--timeout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
|
||||
#include <bcm_elog_ddr.h>
|
||||
#include <brcm_mhu.h>
|
||||
#include <brcm_scpi.h>
|
||||
#include <chimp.h>
|
||||
#include <cmn_plat_util.h>
|
||||
#include <ddr_init.h>
|
||||
#include <scp.h>
|
||||
#include <scp_cmd.h>
|
||||
#include <scp_utils.h>
|
||||
|
||||
#include "m0_cfg.h"
|
||||
#include "m0_ipc.h"
|
||||
|
||||
#ifdef BCM_ELOG
|
||||
static void prepare_elog(void)
|
||||
{
|
||||
#if (CLEAN_DDR && !defined(MMU_DISABLED))
|
||||
/*
|
||||
* Now DDR has been initialized. We want to copy all the logs in SRAM
|
||||
* into DDR so we will have much more space to store the logs in the
|
||||
* next boot stage
|
||||
*/
|
||||
bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE,
|
||||
MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE)
|
||||
);
|
||||
|
||||
/*
|
||||
* We are almost at the end of BL2, and we can stop log here so we do
|
||||
* not need to add 'bcm_elog_exit' to the standard BL2 code. The
|
||||
* benefit of capturing BL2 logs after this is very minimal in a
|
||||
* production system.
|
||||
*/
|
||||
bcm_elog_exit();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Notify CRMU that now it should pull logs from DDR instead of from
|
||||
* FS4 SRAM.
|
||||
*/
|
||||
SCP_WRITE_CFG(flash_log.can_use_ddr, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_crmu_alive(void)
|
||||
{
|
||||
return (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, SCP_CMD_DEFAULT_TIMEOUT_US)
|
||||
== 0);
|
||||
}
|
||||
|
||||
bool bcm_scp_issue_sys_reset(void)
|
||||
{
|
||||
return (scp_send_cmd(MCU_IPC_MCU_CMD_L1_RESET, 0,
|
||||
SCP_CMD_DEFAULT_TIMEOUT_US));
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that this is just a temporary implementation until
|
||||
* channels are introduced
|
||||
*/
|
||||
|
||||
int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
|
||||
{
|
||||
int scp_patch_activated, scp_patch_version;
|
||||
#ifndef EMULATION_SETUP
|
||||
uint8_t active_ch_bitmap, i;
|
||||
#endif
|
||||
uint32_t reset_state = 0;
|
||||
uint32_t mcu_ap_init_param = 0;
|
||||
|
||||
/*
|
||||
* First check if SCP patch has already been loaded
|
||||
* Send NOP command and see if there is a valid response
|
||||
*/
|
||||
scp_patch_activated =
|
||||
(scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0,
|
||||
SCP_CMD_DEFAULT_TIMEOUT_US) == 0);
|
||||
if (scp_patch_activated) {
|
||||
INFO("SCP Patch is already active.\n");
|
||||
|
||||
reset_state = SCP_READ_CFG(board_cfg.reset_state);
|
||||
mcu_ap_init_param = SCP_READ_CFG(board_cfg.mcu_init_param);
|
||||
|
||||
/* Clear reset state, it's been already read */
|
||||
SCP_WRITE_CFG(board_cfg.reset_state, 0);
|
||||
|
||||
if (mcu_ap_init_param & MCU_PATCH_LOADED_BY_NITRO) {
|
||||
/*
|
||||
* Reset "MCU_PATCH_LOADED_BY_NITRO" flag, but
|
||||
* Preserve any other flags we don't deal with here
|
||||
*/
|
||||
INFO("AP booted by Nitro\n");
|
||||
SCP_WRITE_CFG(
|
||||
board_cfg.mcu_init_param,
|
||||
mcu_ap_init_param &
|
||||
~MCU_PATCH_LOADED_BY_NITRO
|
||||
);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* MCU Patch not loaded, so load it.
|
||||
* MCU patch stamps critical points in REG9 (debug test-point)
|
||||
* Display its last content here. This helps to locate
|
||||
* where crash occurred if a CRMU watchdog kicked in.
|
||||
*/
|
||||
int ret;
|
||||
|
||||
INFO("MCU Patch Point: 0x%x\n",
|
||||
mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9));
|
||||
|
||||
ret = download_scp_patch((void *)scp_bl2_image_info->image_base,
|
||||
scp_bl2_image_info->image_size);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
VERBOSE("SCP Patch loaded OK.\n");
|
||||
|
||||
ret = scp_send_cmd(MCU_IPC_MCU_CMD_INIT,
|
||||
MCU_PATCH_LOADED_BY_AP,
|
||||
SCP_CMD_SCP_BOOT_TIMEOUT_US);
|
||||
if (ret) {
|
||||
ERROR("SCP Patch could not initialize; error %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
INFO("SCP Patch successfully initialized.\n");
|
||||
}
|
||||
|
||||
scp_patch_version = scp_send_cmd(MCU_IPC_MCU_CMD_GET_FW_VERSION, 0,
|
||||
SCP_CMD_DEFAULT_TIMEOUT_US);
|
||||
INFO("SCP Patch version :0x%x\n", scp_patch_version);
|
||||
|
||||
/* Next block just reports current AVS voltages (if applicable) */
|
||||
{
|
||||
uint16_t vcore_mv, ihost03_mv, ihost12_mv;
|
||||
|
||||
vcore_mv = SCP_READ_CFG16(vcore.millivolts) +
|
||||
SCP_READ_CFG8(vcore.avs_cfg.additive_margin);
|
||||
ihost03_mv = SCP_READ_CFG16(ihost03.millivolts) +
|
||||
SCP_READ_CFG8(ihost03.avs_cfg.additive_margin);
|
||||
ihost12_mv = SCP_READ_CFG16(ihost12.millivolts) +
|
||||
SCP_READ_CFG8(ihost12.avs_cfg.additive_margin);
|
||||
|
||||
if (vcore_mv || ihost03_mv || ihost12_mv) {
|
||||
INFO("AVS voltages from cfg (including margin)\n");
|
||||
if (vcore_mv > 0)
|
||||
INFO("%s\tVCORE: %dmv\n",
|
||||
SCP_READ_CFG8(vcore.avs_cfg.avs_set) ?
|
||||
"*" : "n/a", vcore_mv);
|
||||
if (ihost03_mv > 0)
|
||||
INFO("%s\tIHOST03: %dmv\n",
|
||||
SCP_READ_CFG8(ihost03.avs_cfg.avs_set) ?
|
||||
"*" : "n/a", ihost03_mv);
|
||||
if (ihost12_mv > 0)
|
||||
INFO("%s\tIHOST12: %dmv\n",
|
||||
SCP_READ_CFG8(ihost12.avs_cfg.avs_set) ?
|
||||
"*" : "n/a", ihost12_mv);
|
||||
} else {
|
||||
INFO("AVS settings not applicable\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if (CLEAN_DDR && !defined(MMU_DISABLED) && !defined(EMULATION_SETUP))
|
||||
/* This will clean the DDR and enable ECC if set */
|
||||
check_ddr_clean();
|
||||
#endif
|
||||
|
||||
#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
|
||||
elog_init_ddr_log();
|
||||
#endif
|
||||
|
||||
#ifdef BCM_ELOG
|
||||
/* Prepare ELOG to use DDR */
|
||||
prepare_elog();
|
||||
#endif
|
||||
|
||||
#ifndef EMULATION_SETUP
|
||||
/* Ask ddr_init to save obtained DDR information into DDR */
|
||||
ddr_info_save();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Configure TMON DDR address.
|
||||
* This cfg is common for all cases
|
||||
*/
|
||||
SCP_WRITE_CFG(tmon_cfg.ddr_desc, TMON_SHARED_DDR_ADDRESS);
|
||||
|
||||
if (reset_state == SOFT_RESET_L3 && !mcu_ap_init_param) {
|
||||
INFO("SCP configuration after L3 RESET done.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bcm_chimp_is_nic_mode())
|
||||
/* Configure AP WDT to not reset the NIC interface */
|
||||
SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
|
||||
|
||||
#if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR)
|
||||
/* When AP WDog triggers perform L3 reset if DDR err logging enabled */
|
||||
SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3);
|
||||
#endif
|
||||
|
||||
#ifndef EMULATION_SETUP
|
||||
|
||||
#ifdef DDR_SCRUB_ENA
|
||||
ddr_scrub_enable();
|
||||
#endif
|
||||
/* Fill the Active channel information */
|
||||
active_ch_bitmap = get_active_ddr_channel();
|
||||
for (i = 0; i < MAX_NR_DDR_CH; i++)
|
||||
SCP_WRITE_CFG(ddr_cfg.ddr_cfg[i],
|
||||
(active_ch_bitmap & BIT(i)) ? 1 : 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <sdio.h>
|
||||
#include <sr_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
const SDIO_CFG sr_sdio0_cfg = {
|
||||
.cfg_base = SR_IPROC_SDIO0_CFG_BASE,
|
||||
.sid_base = SR_IPROC_SDIO0_SID_BASE,
|
||||
.io_ctrl_base = SR_IPROC_SDIO0_IOCTRL_BASE,
|
||||
.pad_base = SR_IPROC_SDIO0_PAD_BASE,
|
||||
};
|
||||
const SDIO_CFG sr_sdio1_cfg = {
|
||||
.cfg_base = SR_IPROC_SDIO1_CFG_BASE,
|
||||
.sid_base = SR_IPROC_SDIO1_SID_BASE,
|
||||
.io_ctrl_base = SR_IPROC_SDIO1_IOCTRL_BASE,
|
||||
.pad_base = SR_IPROC_SDIO1_PAD_BASE,
|
||||
};
|
||||
|
||||
void brcm_stingray_sdio_init(void)
|
||||
{
|
||||
unsigned int val;
|
||||
const SDIO_CFG *sdio0_cfg, *sdio1_cfg;
|
||||
|
||||
sdio0_cfg = &sr_sdio0_cfg;
|
||||
sdio1_cfg = &sr_sdio1_cfg;
|
||||
|
||||
INFO("set sdio0 caps\n");
|
||||
/* SDIO0 CAPS0 */
|
||||
val = SDIO0_CAP0_CFG;
|
||||
INFO("caps0 0x%x\n", val);
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP0, val);
|
||||
|
||||
/* SDIO0 CAPS1 */
|
||||
val = SDIO0_CAP1_CFG;
|
||||
INFO("caps1 0x%x\n", val);
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_CAP1, val);
|
||||
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
|
||||
SDIO_PRESETVAL0);
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
|
||||
SDIO_PRESETVAL1);
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
|
||||
SDIO_PRESETVAL2);
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
|
||||
SDIO_PRESETVAL3);
|
||||
mmio_write_32(sdio0_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
|
||||
SDIO_PRESETVAL4);
|
||||
|
||||
val = SR_SID_VAL(0x3, 0x0, 0x2) << SDIO_SID_SHIFT;
|
||||
mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
|
||||
mmio_write_32(sdio0_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
|
||||
|
||||
val = mmio_read_32(sdio0_cfg->io_ctrl_base);
|
||||
val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
|
||||
val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
|
||||
mmio_write_32(sdio0_cfg->io_ctrl_base, val);
|
||||
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CLK,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA0,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA1,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA2,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA3,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA4,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA5,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA6,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_DATA7,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio0_cfg->pad_base + PAD_SDIO_CMD,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
|
||||
INFO("set sdio1 caps\n");
|
||||
|
||||
/* SDIO1 CAPS0 */
|
||||
val = SDIO1_CAP0_CFG;
|
||||
INFO("caps0 0x%x\n", val);
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP0, val);
|
||||
/* SDIO1 CAPS1 */
|
||||
val = SDIO1_CAP1_CFG;
|
||||
INFO("caps1 0x%x\n", val);
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_CAP1, val);
|
||||
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_0,
|
||||
SDIO_PRESETVAL0);
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_1,
|
||||
SDIO_PRESETVAL1);
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_2,
|
||||
SDIO_PRESETVAL2);
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_3,
|
||||
SDIO_PRESETVAL3);
|
||||
mmio_write_32(sdio1_cfg->cfg_base + ICFG_SDIO_STRAPSTATUS_4,
|
||||
SDIO_PRESETVAL4);
|
||||
|
||||
val = SR_SID_VAL(0x3, 0x0, 0x3) << SDIO_SID_SHIFT;
|
||||
mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_ARADDR, val);
|
||||
mmio_write_32(sdio1_cfg->sid_base + ICFG_SDIO_SID_AWADDR, val);
|
||||
|
||||
val = mmio_read_32(sdio1_cfg->io_ctrl_base);
|
||||
val &= ~(0xff << 23); /* Clear ARCACHE and AWCACHE */
|
||||
val |= (0xb7 << 23); /* Set ARCACHE and AWCACHE */
|
||||
mmio_write_32(sdio1_cfg->io_ctrl_base, val);
|
||||
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CLK,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA0,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA1,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA2,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA3,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA4,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA5,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA6,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_DATA7,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
mmio_clrsetbits_32(sdio1_cfg->pad_base + PAD_SDIO_CMD,
|
||||
PAD_SDIO_MASK, PAD_SDIO_VALUE);
|
||||
|
||||
INFO("sdio init done\n");
|
||||
}
|
||||
+806
@@ -0,0 +1,806 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <paxb.h>
|
||||
#include <sr_def.h>
|
||||
#include <sr_utils.h>
|
||||
|
||||
/* total number of PCIe Phys */
|
||||
#define NUM_OF_PCIE_SERDES 8
|
||||
|
||||
#define CFG_RC_PMI_ADDR 0x1130
|
||||
#define PMI_RX_TERM_SEQ ((0x1 << 27) | (0x1ff << 16) | (0xd090))
|
||||
#define PMI_RX_TERM_VAL 0x4c00
|
||||
#define PMI_PLL_CTRL_4 0xd0b4
|
||||
#define PMI_SERDES_CLK_ENABLE (1 << 12)
|
||||
|
||||
#define WAR_PLX_PRESET_PARITY_FAIL
|
||||
|
||||
#define CFG_RC_REG_PHY_CTL_10 0x1838
|
||||
#define PHY_CTL_10_GEN3_MATCH_PARITY (1 << 15)
|
||||
|
||||
#define PMI_X8_CORE0_7_PATCH_SEQ ((0x1 << 27) | (0x1ff << 16) | (0xd2a5))
|
||||
#define PMI_X8_CORE0_7_PATCH_VAL 0xd864
|
||||
|
||||
#define PMI_ADDR_BCAST(addr) ((0x1 << 27) | (0x1ff << 16) | (addr))
|
||||
#define PMI_ADDR_LANE0(addr) ((0x1 << 27) | (addr))
|
||||
#define PMI_ADDR_LANE1(addr) ((0x1 << 27) | (0x1 << 16) | (addr))
|
||||
|
||||
#define MERLIN16_PCIE_BLK2_PWRMGMT_7 ((0x1 << 27) | (0x1ff << 16) | 0x1208)
|
||||
#define MERLIN16_PCIE_BLK2_PWRMGMT_8 ((0x1 << 27) | (0x1ff << 16) | 0x1209)
|
||||
#define MERLIN16_AMS_TX_CTRL_5 ((0x1 << 27) | (0x1ff << 16) | 0xd0a5)
|
||||
#define MERLIN16_AMS_TX_CTRL_5_VAL \
|
||||
((1 << 13) | (1 << 12) | (1 << 11) | (1 << 10))
|
||||
#define MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL 0x96
|
||||
#define MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL 0x12c
|
||||
|
||||
#define CFG_RC_PMI_WDATA 0x1134
|
||||
#define CFG_RC_WCMD_SHIFT 31
|
||||
#define CFG_RC_WCMD_MASK ((uint32_t)1U << CFG_RC_WCMD_SHIFT)
|
||||
#define CFG_RC_RCMD_SHIFT 30
|
||||
#define CFG_RC_RCMD_MASK ((uint32_t)1U << CFG_RC_RCMD_SHIFT)
|
||||
#define CFG_RC_RWCMD_MASK (CFG_RC_RCMD_MASK | CFG_RC_WCMD_MASK)
|
||||
#define CFG_RC_PMI_RDATA 0x1138
|
||||
#define CFG_RC_RACK_SHIFT 31
|
||||
#define CFG_RC_RACK_MASK ((uint32_t)1U << CFG_RC_RACK_SHIFT)
|
||||
|
||||
/* allow up to 5 ms for PMI write to finish */
|
||||
#define PMI_TIMEOUT_MS 5
|
||||
|
||||
/* in 2x8 RC mode, one needs to patch up Serdes 3 and 7 for link to come up */
|
||||
#define SERDES_PATCH_PIPEMUX_INDEX 0x3
|
||||
#define SERDES_PATCH_INDEX 0x8
|
||||
|
||||
#define DSC_UC_CTRL 0xd00d
|
||||
#define DSC_UC_CTRL_RDY_CMD (1 << 7)
|
||||
#define LANE_DBG_RST_CTRL 0xd164
|
||||
#define UC_A_CLK_CTRL0 0xd200
|
||||
#define UC_A_RST_CTRL0 0xd201
|
||||
#define UC_A_AHB_CTRL0 0xd202
|
||||
#define UC_A_AHB_STAT0 0xd203
|
||||
#define UC_A_AHB_WADDR_LSW 0xd204
|
||||
#define UC_A_AHB_WADDR_MSW 0xd205
|
||||
#define UC_A_AHB_WDATA_LSW 0xd206
|
||||
#define UC_A_AHB_WDATA_MSW 0xd207
|
||||
#define UC_A_AHB_RADDR_LSW 0xd208
|
||||
#define UC_A_AHB_RADDR_MSW 0xd209
|
||||
#define UC_A_AHB_RDATA_LSW 0xd20a
|
||||
#define UC_A_AHB_RDATA_MSW 0xd20b
|
||||
#define UC_VERSION_NUM 0xd230
|
||||
#define DSC_SM_CTL22 0xd267
|
||||
#define UC_DBG1 0xd251
|
||||
|
||||
#define LOAD_UC_CHECK 0
|
||||
#define UC_RAM_INIT_TIMEOUT 100
|
||||
#define UC_RAM_CONTROL 0xd225
|
||||
#define UC_INIT_TIMEOUT 100
|
||||
#define SIZE_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
#define SZ_4 4
|
||||
#define GET_2_BYTES(p, i) ((uint16_t)p[i] | (uint16_t)p[i+1] << 8)
|
||||
|
||||
/*
|
||||
* List of PCIe LCPLL related registers
|
||||
*
|
||||
* LCPLL channel 0 provides the Serdes pad clock when running in RC mode
|
||||
*/
|
||||
#define PCIE_LCPLL_BASE 0x40000000
|
||||
|
||||
#define PCIE_LCPLL_CTRL0_OFFSET 0x00
|
||||
#define PCIE_LCPLL_RESETB_SHIFT 31
|
||||
#define PCIE_LCPLL_RESETB_MASK BIT(PCIE_LCPLL_RESETB_SHIFT)
|
||||
#define PCIE_LCPLL_P_RESETB_SHIFT 30
|
||||
#define PCIE_LCPLL_P_RESETB_MASK BIT(PCIE_LCPLL_P_RESETB_SHIFT)
|
||||
|
||||
#define PCIE_LCPLL_CTRL3_OFFSET 0x0c
|
||||
#define PCIE_LCPLL_EN_CTRL_SHIFT 16
|
||||
#define PCIE_LCPLL_CM_ENA 0x1a
|
||||
#define PCIE_LCPLL_CM_BUF_ENA 0x18
|
||||
#define PCIE_LCPLL_D2C2_ENA 0x2
|
||||
#define PCIE_LCPLL_REF_CLK_SHIFT 1
|
||||
#define PCIE_LCPLL_REF_CLK_MASK BIT(PCIE_LCPLL_REF_CLK_SHIFT)
|
||||
#define PCIE_LCPLL_CTRL13_OFFSET 0x34
|
||||
#define PCIE_LCPLL_D2C2_CTRL_SHIFT 16
|
||||
#define PCIE_LCPLL_D2C2_TERM_DISC 0xe0
|
||||
|
||||
#define PCIE_LCPLL_STATUS_OFFSET 0x40
|
||||
#define PCIE_LCPLL_LOCK_SHIFT 12
|
||||
#define PCIE_LCPLL_LOCK_MASK BIT(PCIE_LCPLL_LOCK_SHIFT)
|
||||
|
||||
#define PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG 0x114
|
||||
#define PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG 0x11c
|
||||
|
||||
/* wait 500 microseconds for PCIe LCPLL to power up */
|
||||
#define PCIE_LCPLL_DELAY_US 500
|
||||
|
||||
/* allow up to 5 ms for PCIe LCPLL VCO to lock */
|
||||
#define PCIE_LCPLL_TIMEOUT_MS 5
|
||||
|
||||
#define PCIE_PIPE_MUX_CONFIGURATION_CFG 0x4000010c
|
||||
|
||||
#define PCIE_PIPEMUX_SHIFT 19
|
||||
#define PCIE_PIPEMUX_MASK 0xf
|
||||
|
||||
/* keep track of PIPEMUX index to use */
|
||||
static unsigned int pipemux_idx;
|
||||
|
||||
/*
|
||||
* PCIe PIPEMUX lookup table
|
||||
*
|
||||
* Each array index represents a PIPEMUX strap setting
|
||||
* The array element represents a bitmap where a set bit means the PCIe core
|
||||
* needs to be enabled as RC
|
||||
*/
|
||||
static uint8_t pipemux_table[] = {
|
||||
/* PIPEMUX = 0, EP 1x16 */
|
||||
0x00,
|
||||
/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
|
||||
0x80,
|
||||
/* PIPEMUX = 2, EP 4x4 */
|
||||
0x00,
|
||||
/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
|
||||
0x81,
|
||||
/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
|
||||
0xc3,
|
||||
/* PIPEMUX = 5, RC 8x2, all 8 cores */
|
||||
0xff,
|
||||
/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
|
||||
0xcd,
|
||||
/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
|
||||
0xfd,
|
||||
/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
|
||||
0xf0,
|
||||
/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
|
||||
0xc0,
|
||||
/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
|
||||
0x42,
|
||||
/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
|
||||
0x3c,
|
||||
/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
|
||||
0xfc,
|
||||
/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
|
||||
0x4c,
|
||||
};
|
||||
|
||||
/*
|
||||
* Return 1 if pipemux strap is supported
|
||||
*/
|
||||
static int pipemux_strap_is_valid(uint32_t pipemux)
|
||||
{
|
||||
if (pipemux < ARRAY_SIZE(pipemux_table))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the PCIe PIPEMUX from strap
|
||||
*/
|
||||
static uint32_t pipemux_strap_read(void)
|
||||
{
|
||||
uint32_t pipemux;
|
||||
|
||||
pipemux = mmio_read_32(PCIE_PIPE_MUX_CONFIGURATION_CFG);
|
||||
pipemux &= PCIE_PIPEMUX_MASK;
|
||||
if (pipemux == PCIE_PIPEMUX_MASK) {
|
||||
/* read the PCIe PIPEMUX strap setting */
|
||||
pipemux = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW);
|
||||
pipemux >>= PCIE_PIPEMUX_SHIFT;
|
||||
pipemux &= PCIE_PIPEMUX_MASK;
|
||||
}
|
||||
|
||||
return pipemux;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the PIPEMUX index (set for each boot)
|
||||
*/
|
||||
static void pipemux_save_index(unsigned int idx)
|
||||
{
|
||||
pipemux_idx = idx;
|
||||
}
|
||||
|
||||
static int paxb_sr_core_needs_enable(unsigned int core_idx)
|
||||
{
|
||||
return !!((pipemux_table[pipemux_idx] >> core_idx) & 0x1);
|
||||
}
|
||||
|
||||
static int pipemux_sr_init(void)
|
||||
{
|
||||
uint32_t pipemux;
|
||||
|
||||
/* read the PCIe PIPEMUX strap setting */
|
||||
pipemux = pipemux_strap_read();
|
||||
if (!pipemux_strap_is_valid(pipemux)) {
|
||||
ERROR("Invalid PCIe PIPEMUX strap %u\n", pipemux);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* no PCIe RC is needed */
|
||||
if (!pipemux_table[pipemux]) {
|
||||
WARN("PIPEMUX indicates no PCIe RC required\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* save the PIPEMUX strap */
|
||||
pipemux_save_index(pipemux);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* PCIe RC serdes link width
|
||||
*
|
||||
* The array is first organized in rows as indexed by the PIPEMUX setting.
|
||||
* Within each row, eight lane width entries are specified -- one entry
|
||||
* per PCIe core, from 0 to 7.
|
||||
*
|
||||
* Note: The EP lanes/cores are not mapped in this table! EP cores are
|
||||
* controlled and thus configured by Nitro.
|
||||
*/
|
||||
static uint8_t link_width_table[][NUM_OF_SR_PCIE_CORES] = {
|
||||
/* PIPEMUX = 0, EP 1x16 */
|
||||
{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
|
||||
{0, 0, 0, 0, 0, 0, 0, 8},
|
||||
/* PIPEMUX = 2, EP 4x4 */
|
||||
{0, 0, 0, 0, 0, 0, 0, 0},
|
||||
/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
|
||||
{8, 0, 0, 0, 0, 0, 0, 8},
|
||||
/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
|
||||
{4, 4, 0, 0, 0, 0, 4, 4},
|
||||
/* PIPEMUX = 5, RC 8x2, all 8 cores */
|
||||
{2, 2, 2, 2, 2, 2, 2, 2},
|
||||
/* PIPEMUX = 6, RC 3x4 (cores 0, 6, 7), RC 2x2 (cores 2, 3) */
|
||||
{4, 0, 2, 2, 0, 0, 4, 4},
|
||||
/* PIPEMUX = 7, RC 1x4 (core 0), RC 6x2 (cores 2, 3, 4, 5, 6, 7 */
|
||||
{4, 0, 2, 2, 2, 2, 2, 2},
|
||||
/* PIPEMUX = 8, EP 1x8 + RC 4x2 (cores 4, 5, 6, 7) */
|
||||
{0, 0, 0, 0, 2, 2, 2, 2},
|
||||
/* PIPEMUX = 9, EP 1x8 + RC 2x4 (cores 6, 7) */
|
||||
{0, 0, 0, 0, 0, 0, 4, 4},
|
||||
/* PIPEMUX = 10, EP 2x4 + RC 2x4 (cores 1, 6) */
|
||||
{0, 4, 0, 0, 0, 0, 4, 0},
|
||||
/* PIPEMUX = 11, EP 2x4 + RC 4x2 (cores 2, 3, 4, 5) */
|
||||
{0, 0, 2, 2, 2, 2, 0, 0},
|
||||
/* PIPEMUX = 12, EP 1x4 + RC 6x2 (cores 2, 3, 4, 5, 6, 7) */
|
||||
{0, 0, 2, 2, 2, 2, 2, 2},
|
||||
/* PIPEMUX = 13, EP 2x4 + RC 1x4 (core 6) + RC 2x2 (cores 2, 3) */
|
||||
{0, 0, 2, 2, 0, 0, 4, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* function for writes to the Serdes registers through the PMI interface
|
||||
*/
|
||||
static int paxb_pmi_write(unsigned int core_idx, uint32_t pmi, uint32_t val)
|
||||
{
|
||||
uint32_t status;
|
||||
unsigned int timeout = PMI_TIMEOUT_MS;
|
||||
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
|
||||
|
||||
val &= ~CFG_RC_RWCMD_MASK;
|
||||
val |= CFG_RC_WCMD_MASK;
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, val);
|
||||
|
||||
do {
|
||||
status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_WDATA);
|
||||
|
||||
/* wait for write command bit to clear */
|
||||
if ((status & CFG_RC_WCMD_MASK) == 0)
|
||||
return 0;
|
||||
} while (--timeout);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* function for reads from the Serdes registers through the PMI interface
|
||||
*/
|
||||
static int paxb_pmi_read(unsigned int core_idx, uint32_t pmi, uint32_t *val)
|
||||
{
|
||||
uint32_t status;
|
||||
unsigned int timeout = PMI_TIMEOUT_MS;
|
||||
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_PMI_ADDR, pmi);
|
||||
|
||||
paxb_rc_cfg_write(core_idx, CFG_RC_PMI_WDATA, CFG_RC_RCMD_MASK);
|
||||
|
||||
do {
|
||||
status = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
|
||||
|
||||
/* wait for read ack bit set */
|
||||
if ((status & CFG_RC_RACK_MASK)) {
|
||||
*val = paxb_rc_cfg_read(core_idx, CFG_RC_PMI_RDATA);
|
||||
return 0;
|
||||
}
|
||||
} while (--timeout);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOARD_PCIE_EXT_CLK
|
||||
/*
|
||||
* PCIe Override clock lookup table
|
||||
*
|
||||
* Each array index represents pcie override clock has been done
|
||||
* by CFW or not.
|
||||
*/
|
||||
static uint8_t pcie_override_clk_table[] = {
|
||||
/* PIPEMUX = 0, EP 1x16 */
|
||||
0x0,
|
||||
/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
|
||||
0x1,
|
||||
/* PIPEMUX = 2, EP 4x4 */
|
||||
0x0,
|
||||
/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 5, RC 8x2, all 8 cores */
|
||||
0x0,
|
||||
/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
|
||||
0x0,
|
||||
/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
|
||||
0x0,
|
||||
/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
|
||||
0x0,
|
||||
/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
|
||||
0x0,
|
||||
};
|
||||
|
||||
/*
|
||||
* Bring up LCPLL channel 0 reference clock for PCIe serdes used in RC mode
|
||||
*/
|
||||
static int pcie_lcpll_init(void)
|
||||
{
|
||||
uintptr_t reg;
|
||||
unsigned int timeout = PCIE_LCPLL_TIMEOUT_MS;
|
||||
uint32_t val;
|
||||
|
||||
if (pcie_override_clk_table[pipemux_idx]) {
|
||||
/*
|
||||
* Check rc_mode_override again to avoid halt
|
||||
* because of cfw uninitialized lcpll.
|
||||
*/
|
||||
reg = (uintptr_t)(PCIE_LCPLL_BASE +
|
||||
PCIE_PIPE_MUX_RC_MODE_OVERRIDE_CFG);
|
||||
val = mmio_read_32(reg);
|
||||
if (val & 0x1)
|
||||
return 0;
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* power on PCIe LCPLL and its LDO */
|
||||
reg = (uintptr_t)CRMU_AON_CTRL1;
|
||||
mmio_setbits_32(reg, CRMU_PCIE_LCPLL_PWR_ON_MASK |
|
||||
CRMU_PCIE_LCPLL_PWRON_LDO_MASK);
|
||||
udelay(PCIE_LCPLL_DELAY_US);
|
||||
|
||||
/* remove isolation */
|
||||
mmio_clrbits_32(reg, CRMU_PCIE_LCPLL_ISO_IN_MASK);
|
||||
udelay(PCIE_LCPLL_DELAY_US);
|
||||
|
||||
/* disconnect termination */
|
||||
reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL13_OFFSET);
|
||||
mmio_setbits_32(reg, PCIE_LCPLL_D2C2_TERM_DISC <<
|
||||
PCIE_LCPLL_D2C2_CTRL_SHIFT);
|
||||
|
||||
/* enable CML buf1/2 and D2C2 */
|
||||
reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET);
|
||||
mmio_setbits_32(reg, PCIE_LCPLL_CM_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
|
||||
|
||||
/* select diff clock mux out as ref clock */
|
||||
mmio_clrbits_32(reg, PCIE_LCPLL_REF_CLK_MASK);
|
||||
|
||||
/* delay for 500 microseconds per ASIC spec for PCIe LCPLL */
|
||||
udelay(PCIE_LCPLL_DELAY_US);
|
||||
|
||||
/* now bring PCIe LCPLL out of reset */
|
||||
reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL0_OFFSET);
|
||||
mmio_setbits_32(reg, PCIE_LCPLL_RESETB_MASK);
|
||||
|
||||
/* wait for PLL to lock */
|
||||
reg = (uintptr_t)(PCIE_LCPLL_BASE + PCIE_LCPLL_STATUS_OFFSET);
|
||||
do {
|
||||
val = mmio_read_32(reg);
|
||||
if ((val & PCIE_LCPLL_LOCK_MASK) == PCIE_LCPLL_LOCK_MASK) {
|
||||
/* now bring the post divider out of reset */
|
||||
reg = (uintptr_t)(PCIE_LCPLL_BASE +
|
||||
PCIE_LCPLL_CTRL0_OFFSET);
|
||||
mmio_setbits_32(reg, PCIE_LCPLL_P_RESETB_MASK);
|
||||
VERBOSE("PCIe LCPLL locked\n");
|
||||
return 0;
|
||||
}
|
||||
mdelay(1);
|
||||
} while (--timeout);
|
||||
|
||||
ERROR("PCIe LCPLL failed to lock\n");
|
||||
return -EIO;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Bring up EXT CLK reference clock for PCIe serdes used in RC mode
|
||||
* XTAL_BYPASS (3 << 0)
|
||||
* INTR_LC_REF (5 << 0)
|
||||
* PD_CML_LC_REF_OUT (1 << 4)
|
||||
* PD_CML_REF_CH_OUT (1 << 8)
|
||||
* CLK_MASTER_SEL (1 << 11)
|
||||
* CLK_MASTER_CTRL_A (1 << 12)
|
||||
* CLK_MASTER_CTRL_B (2 << 14)
|
||||
*/
|
||||
static const uint16_t pcie_ext_clk[][NUM_OF_PCIE_SERDES] = {
|
||||
/* PIPEMUX = 0, EP 1x16 */
|
||||
{0},
|
||||
/* PIPEMUX = 1, EP 1x8 + RC 1x8, core 7 */
|
||||
{0},
|
||||
/* PIPEMUX = 2, EP 4x4 */
|
||||
{0},
|
||||
/* PIPEMUX = 3, RC 2x8, cores 0, 7 */
|
||||
{0x8803, 0x9115, 0x9115, 0x1115, 0x8803, 0x9115, 0x9115, 0x1115},
|
||||
/* PIPEMUX = 4, RC 4x4, cores 0, 1, 6, 7 */
|
||||
{0x8803, 0x1115, 0x8915, 0x1115, 0x8803, 0x1115, 0x8915, 0x1115,},
|
||||
/* PIPEMUX = 5, RC 8x2, all 8 cores */
|
||||
{0x0803, 0x0915, 0x0915, 0x0915, 0x0803, 0x0915, 0x0915, 0x0915,},
|
||||
/* PIPEMUX = 6, RC 3x4 + 2x2, cores 0, 2, 3, 6, 7 */
|
||||
{0},
|
||||
/* PIPEMUX = 7, RC 1x4 + 6x2, cores 0, 2, 3, 4, 5, 6, 7 */
|
||||
{0},
|
||||
/* PIPEMUX = 8, EP 1x8 + RC 4x2, cores 4, 5, 6, 7 */
|
||||
{0},
|
||||
/* PIPEMUX = 9, EP 1x8 + RC 2x4, cores 6, 7 */
|
||||
{0},
|
||||
/* PIPEMUX = 10, EP 2x4 + RC 2x4, cores 1, 6 */
|
||||
{0},
|
||||
/* PIPEMUX = 11, EP 2x4 + RC 4x2, cores 2, 3, 4, 5 */
|
||||
{0},
|
||||
/* PIPEMUX = 12, EP 1x4 + RC 6x2, cores 2, 3, 4, 5, 6, 7 */
|
||||
{0},
|
||||
/* PIPEMUX = 13, RC 2x4 + RC 1x4 + 2x2, cores 2, 3, 6 */
|
||||
{0},
|
||||
};
|
||||
|
||||
static void pcie_ext_clk_init(void)
|
||||
{
|
||||
unsigned int serdes;
|
||||
uint32_t val;
|
||||
|
||||
for (serdes = 0; serdes < NUM_OF_PCIE_SERDES; serdes++) {
|
||||
val = pcie_ext_clk[pipemux_idx][serdes];
|
||||
if (!val)
|
||||
return;
|
||||
mmio_write_32(PCIE_CORE_RESERVED_CFG +
|
||||
serdes * PCIE_CORE_PWR_OFFSET, val);
|
||||
}
|
||||
/* disable CML buf1/2 and enable D2C2 */
|
||||
mmio_clrsetbits_32((PCIE_LCPLL_BASE + PCIE_LCPLL_CTRL3_OFFSET),
|
||||
PCIE_LCPLL_CM_BUF_ENA << PCIE_LCPLL_EN_CTRL_SHIFT,
|
||||
PCIE_LCPLL_D2C2_ENA << PCIE_LCPLL_EN_CTRL_SHIFT);
|
||||
mmio_write_32(PCIE_LCPLL_BASE + PCIE_TX_CLKMASTER_CTRL_OVERRIDE_CFG, 1);
|
||||
INFO("Overriding Clocking - using REF clock from PAD...\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static int load_uc(unsigned int core_idx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int paxb_serdes_gate_clock(unsigned int core_idx, int gate_clk)
|
||||
{
|
||||
unsigned int link_width, serdes, nr_serdes;
|
||||
uintptr_t pmi_base;
|
||||
unsigned int rdata;
|
||||
uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
|
||||
|
||||
link_width = paxb->get_link_width(core_idx);
|
||||
if (!link_width) {
|
||||
ERROR("Unsupported PIPEMUX\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
nr_serdes = link_width / 2;
|
||||
pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
|
||||
|
||||
for (serdes = 0; serdes < nr_serdes; serdes++) {
|
||||
mmio_write_32(pmi_base, serdes);
|
||||
paxb_pmi_read(core_idx, PMI_ADDR_LANE0(PMI_PLL_CTRL_4), &rdata);
|
||||
if (!gate_clk)
|
||||
rdata |= PMI_SERDES_CLK_ENABLE;
|
||||
else
|
||||
rdata &= ~PMI_SERDES_CLK_ENABLE;
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(PMI_PLL_CTRL_4), rdata);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int paxb_gen3_serdes_init(unsigned int core_idx, uint32_t nSerdes)
|
||||
{
|
||||
uint32_t rdata;
|
||||
int serdes;
|
||||
uintptr_t pmi_base;
|
||||
unsigned int timeout;
|
||||
unsigned int reg_d230, reg_d267;
|
||||
|
||||
|
||||
pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE +
|
||||
(core_idx * PCIE_CORE_PWR_OFFSET));
|
||||
|
||||
for (serdes = 0; serdes < nSerdes; serdes++) {
|
||||
/* select the PMI interface */
|
||||
mmio_write_32(pmi_base, serdes);
|
||||
|
||||
/* Clock enable */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_CLK_CTRL0),
|
||||
0x3);
|
||||
|
||||
/* Release reset of master */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
|
||||
0x1);
|
||||
|
||||
/* clearing PRAM memory */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
|
||||
0x100);
|
||||
|
||||
timeout = UC_RAM_INIT_TIMEOUT;
|
||||
do {
|
||||
paxb_pmi_read(core_idx,
|
||||
PMI_ADDR_LANE0(UC_A_AHB_STAT0),
|
||||
&rdata);
|
||||
} while ((rdata & 0x01) == 0 && timeout--);
|
||||
|
||||
if (!timeout)
|
||||
return -EIO;
|
||||
|
||||
timeout = UC_RAM_INIT_TIMEOUT;
|
||||
do {
|
||||
paxb_pmi_read(core_idx,
|
||||
PMI_ADDR_LANE1(UC_A_AHB_STAT0),
|
||||
&rdata);
|
||||
} while ((rdata & 0x01) == 0 && timeout--);
|
||||
|
||||
if (!timeout)
|
||||
return -EIO;
|
||||
|
||||
/* clearing PRAM memory */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_AHB_CTRL0),
|
||||
0);
|
||||
|
||||
/* to identify 2 lane serdes */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_DBG1), 0x1);
|
||||
|
||||
/* De-Assert Pram & master resets */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
|
||||
0x9);
|
||||
|
||||
if (load_uc(core_idx))
|
||||
return -EIO;
|
||||
|
||||
/* UC UC ready for command */
|
||||
paxb_pmi_read(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
|
||||
&rdata);
|
||||
rdata |= DSC_UC_CTRL_RDY_CMD;
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_LANE0(DSC_UC_CTRL),
|
||||
rdata);
|
||||
|
||||
paxb_pmi_read(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
|
||||
&rdata);
|
||||
rdata |= DSC_UC_CTRL_RDY_CMD;
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_LANE1(DSC_UC_CTRL),
|
||||
rdata);
|
||||
|
||||
/* Lane reset */
|
||||
paxb_pmi_write(core_idx,
|
||||
PMI_ADDR_BCAST(LANE_DBG_RST_CTRL), 0x3);
|
||||
|
||||
/* De-Assert Core and Master resets */
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(UC_A_RST_CTRL0),
|
||||
0x3);
|
||||
|
||||
timeout = UC_INIT_TIMEOUT;
|
||||
while (timeout--) {
|
||||
paxb_pmi_read(core_idx,
|
||||
PMI_ADDR_LANE0(UC_VERSION_NUM),
|
||||
®_d230);
|
||||
paxb_pmi_read(core_idx,
|
||||
PMI_ADDR_LANE0(DSC_SM_CTL22),
|
||||
®_d267);
|
||||
|
||||
if (((reg_d230 & 0xffff) != 0) &
|
||||
((reg_d267 & 0xc000) == 0xc000)) {
|
||||
break;
|
||||
}
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
return -EIO;
|
||||
|
||||
timeout = UC_INIT_TIMEOUT;
|
||||
while (timeout--) {
|
||||
paxb_pmi_read(core_idx,
|
||||
PMI_ADDR_LANE1(UC_VERSION_NUM),
|
||||
®_d230);
|
||||
paxb_pmi_read(core_idx,
|
||||
PMI_ADDR_LANE1(DSC_SM_CTL22),
|
||||
®_d267);
|
||||
|
||||
if (((reg_d230 & 0xffff) != 0) &
|
||||
((reg_d267 & 0xc000) == 0xc000)) {
|
||||
break;
|
||||
}
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcie_serdes_requires_patch(unsigned int serdes_idx)
|
||||
{
|
||||
if (pipemux_idx != SERDES_PATCH_PIPEMUX_INDEX)
|
||||
return 0;
|
||||
|
||||
return !!((SERDES_PATCH_INDEX >> serdes_idx) & 0x1);
|
||||
}
|
||||
|
||||
static void pcie_tx_coeff_p7(unsigned int core_idx)
|
||||
{
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11b), 0x00aa);
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11c), 0x1155);
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11d), 0x2449);
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd11e), 0x000f);
|
||||
paxb_pmi_write(core_idx, PMI_ADDR_BCAST(0xd307), 0x0001);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int paxb_sr_get_rc_link_width(unsigned int core_idx)
|
||||
{
|
||||
return link_width_table[pipemux_idx][core_idx];
|
||||
}
|
||||
|
||||
static uint32_t paxb_sr_get_rc_link_speed(void)
|
||||
{
|
||||
return GEN3_LINK_SPEED;
|
||||
}
|
||||
|
||||
|
||||
static int paxb_serdes_init(unsigned int core_idx, unsigned int nr_serdes)
|
||||
{
|
||||
uint32_t core_offset = core_idx * PCIE_CORE_PWR_OFFSET;
|
||||
unsigned int serdes;
|
||||
uintptr_t pmi_base;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Each serdes has a x2 link width
|
||||
*
|
||||
* Use PAXB to patch the serdes for proper RX termination through the
|
||||
* PMI interface
|
||||
*/
|
||||
pmi_base = (uintptr_t)(PCIE_CORE_PMI_CFG_BASE + core_offset);
|
||||
for (serdes = 0; serdes < nr_serdes; serdes++) {
|
||||
/* select the PMI interface */
|
||||
mmio_write_32(pmi_base, serdes);
|
||||
|
||||
/* patch Serdes for RX termination */
|
||||
ret = paxb_pmi_write(core_idx, PMI_RX_TERM_SEQ,
|
||||
PMI_RX_TERM_VAL);
|
||||
if (ret)
|
||||
goto err_pmi;
|
||||
|
||||
ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_7,
|
||||
MERLIN16_PCIE_BLK2_PWRMGMT_7_VAL);
|
||||
if (ret)
|
||||
goto err_pmi;
|
||||
|
||||
ret = paxb_pmi_write(core_idx, MERLIN16_PCIE_BLK2_PWRMGMT_8,
|
||||
MERLIN16_PCIE_BLK2_PWRMGMT_8_VAL);
|
||||
if (ret)
|
||||
goto err_pmi;
|
||||
|
||||
ret = paxb_pmi_write(core_idx, MERLIN16_AMS_TX_CTRL_5,
|
||||
MERLIN16_AMS_TX_CTRL_5_VAL);
|
||||
if (ret)
|
||||
goto err_pmi;
|
||||
|
||||
pcie_tx_coeff_p7(core_idx);
|
||||
|
||||
if (pcie_serdes_requires_patch(serdes)) {
|
||||
if (((core_idx == 0) || (core_idx == 7))) {
|
||||
ret = paxb_pmi_write(core_idx,
|
||||
PMI_X8_CORE0_7_PATCH_SEQ,
|
||||
PMI_X8_CORE0_7_PATCH_VAL);
|
||||
if (ret)
|
||||
goto err_pmi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_pmi:
|
||||
ERROR("PCIe PMI write failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int paxb_sr_phy_init(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned int core_idx;
|
||||
|
||||
#ifndef BOARD_PCIE_EXT_CLK
|
||||
ret = pcie_lcpll_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
#else
|
||||
pcie_ext_clk_init();
|
||||
#endif
|
||||
|
||||
for (core_idx = 0; core_idx < paxb->num_cores; core_idx++) {
|
||||
if (!pcie_core_needs_enable(core_idx))
|
||||
continue;
|
||||
unsigned int link_width;
|
||||
|
||||
paxb_serdes_gate_clock(core_idx, 0);
|
||||
|
||||
link_width = paxb->get_link_width(core_idx);
|
||||
if (!link_width) {
|
||||
ERROR("Unsupported PIPEMUX\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = paxb_serdes_init(core_idx, link_width / 2);
|
||||
if (ret) {
|
||||
ERROR("PCIe serdes initialization failed for core %u\n",
|
||||
core_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = paxb_gen3_serdes_init(core_idx, link_width / 2);
|
||||
if (ret) {
|
||||
ERROR("PCIe GEN3 serdes initialization failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const paxb_cfg sr_paxb_cfg = {
|
||||
.type = PAXB_SR,
|
||||
.device_id = SR_B0_DEVICE_ID,
|
||||
.pipemux_init = pipemux_sr_init,
|
||||
.phy_init = paxb_sr_phy_init,
|
||||
.core_needs_enable = paxb_sr_core_needs_enable,
|
||||
.num_cores = NUM_OF_SR_PCIE_CORES,
|
||||
.get_link_width = paxb_sr_get_rc_link_width,
|
||||
.get_link_speed = paxb_sr_get_rc_link_speed,
|
||||
};
|
||||
|
||||
const paxb_cfg *paxb_get_sr_config(void)
|
||||
{
|
||||
return &sr_paxb_cfg;
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include <plat_brcm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* On Stingray, the system power level is the highest power level.
|
||||
* The first entry in the power domain descriptor specifies the
|
||||
* number of system power domains i.e. 1.
|
||||
*/
|
||||
#define SR_PWR_DOMAINS_AT_MAX_PWR_LVL 1
|
||||
|
||||
/*
|
||||
* The Stingray power domain tree descriptor. The cluster power domains
|
||||
* are arranged so that when the PSCI generic code creates the power
|
||||
* domain tree, the indices of the CPU power domain nodes it allocates
|
||||
* match the linear indices returned by plat_core_pos_by_mpidr()
|
||||
* i.e. CLUSTER0 CPUs are allocated indices from 0 to 1 and the higher
|
||||
* indices for other Cluster CPUs.
|
||||
*/
|
||||
const unsigned char sr_power_domain_tree_desc[] = {
|
||||
/* No of root nodes */
|
||||
SR_PWR_DOMAINS_AT_MAX_PWR_LVL,
|
||||
/* No of children for the root node */
|
||||
BRCM_CLUSTER_COUNT,
|
||||
/* No of children for the first cluster node */
|
||||
PLATFORM_CLUSTER0_CORE_COUNT,
|
||||
/* No of children for the second cluster node */
|
||||
PLATFORM_CLUSTER1_CORE_COUNT,
|
||||
/* No of children for the third cluster node */
|
||||
PLATFORM_CLUSTER2_CORE_COUNT,
|
||||
/* No of children for the fourth cluster node */
|
||||
PLATFORM_CLUSTER3_CORE_COUNT,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the Stingray topology tree information.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return sr_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
return plat_brcm_calc_core_pos(mpidr);
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - 2020, Broadcom
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/tzc400.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <cmn_sec.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* Trust Zone controllers
|
||||
*/
|
||||
#define TZC400_FS_SRAM_ROOT 0x66d84000
|
||||
|
||||
/*
|
||||
* TZPC Master configure registers
|
||||
*/
|
||||
|
||||
/* TZPC_TZPCDECPROT0set */
|
||||
#define TZPC0_MASTER_NS_BASE 0x68b40804
|
||||
#define TZPC0_SATA3_BIT 5
|
||||
#define TZPC0_SATA2_BIT 4
|
||||
#define TZPC0_SATA1_BIT 3
|
||||
#define TZPC0_SATA0_BIT 2
|
||||
#define TZPC0_USB3H1_BIT 1
|
||||
#define TZPC0_USB3H0_BIT 0
|
||||
#define TZPC0_MASTER_SEC_DEFAULT 0
|
||||
|
||||
/* TZPC_TZPCDECPROT1set */
|
||||
#define TZPC1_MASTER_NS_BASE 0x68b40810
|
||||
#define TZPC1_SDIO1_BIT 6
|
||||
#define TZPC1_SDIO0_BIT 5
|
||||
#define TZPC1_AUDIO0_BIT 4
|
||||
#define TZPC1_USB2D_BIT 3
|
||||
#define TZPC1_USB2H1_BIT 2
|
||||
#define TZPC1_USB2H0_BIT 1
|
||||
#define TZPC1_AMAC0_BIT 0
|
||||
#define TZPC1_MASTER_SEC_DEFAULT 0
|
||||
|
||||
|
||||
struct tz_sec_desc {
|
||||
uintptr_t addr;
|
||||
uint32_t val;
|
||||
};
|
||||
|
||||
static const struct tz_sec_desc tz_master_defaults[] = {
|
||||
{ TZPC0_MASTER_NS_BASE, TZPC0_MASTER_SEC_DEFAULT },
|
||||
{ TZPC1_MASTER_NS_BASE, TZPC1_MASTER_SEC_DEFAULT }
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the TrustZone Controller for SRAM partitioning.
|
||||
*/
|
||||
static void bcm_tzc_setup(void)
|
||||
{
|
||||
VERBOSE("Configuring SRAM TrustZone Controller\n");
|
||||
|
||||
/* Init the TZASC controller */
|
||||
tzc400_init(TZC400_FS_SRAM_ROOT);
|
||||
|
||||
/*
|
||||
* Close the entire SRAM space
|
||||
* Region 0 covers the entire SRAM space
|
||||
* None of the NS device can access it.
|
||||
*/
|
||||
tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
|
||||
|
||||
/* Do raise an exception if a NS device tries to access secure memory */
|
||||
tzc400_set_action(TZC_ACTION_ERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure TZ Master as NS_MASTER or SECURE_MASTER
|
||||
* To set a Master to non-secure, use *_SET registers
|
||||
* To set a Master to secure, use *_CLR registers (set + 0x4 address)
|
||||
*/
|
||||
static void tz_master_set(uint32_t base, uint32_t value, uint32_t ns)
|
||||
{
|
||||
if (ns == SECURE_MASTER) {
|
||||
mmio_write_32(base + 4, value);
|
||||
} else {
|
||||
mmio_write_32(base, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the secure environment for sdio.
|
||||
*/
|
||||
void plat_tz_sdio_ns_master_set(uint32_t ns)
|
||||
{
|
||||
tz_master_set(TZPC1_MASTER_NS_BASE,
|
||||
1 << TZPC1_SDIO0_BIT,
|
||||
ns);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the secure environment for usb.
|
||||
*/
|
||||
void plat_tz_usb_ns_master_set(uint32_t ns)
|
||||
{
|
||||
tz_master_set(TZPC1_MASTER_NS_BASE,
|
||||
1 << TZPC1_USB2H0_BIT,
|
||||
ns);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set masters to default configuration.
|
||||
*
|
||||
* DMA security settings are programmed into the PL-330 controller and
|
||||
* are not set by iProc TZPC registers.
|
||||
* DMA always comes up as secure master (*NS bit is 0).
|
||||
*
|
||||
* Because the default reset values of TZPC are 0 (== Secure),
|
||||
* ARM Verilog code makes all masters, including PCIe, come up as
|
||||
* secure.
|
||||
* However, SOTP has a bit called SOTP_ALLMASTER_NS that overrides
|
||||
* TZPC and makes all masters non-secure for AB devices.
|
||||
*
|
||||
* Hence we first set all the TZPC bits to program all masters,
|
||||
* including PCIe, as non-secure, then set the CLEAR_ALLMASTER_NS bit
|
||||
* so that the SOTP_ALLMASTER_NS cannot override TZPC.
|
||||
* now security settings for each masters come from TZPC
|
||||
* (which makes all masters other than DMA as non-secure).
|
||||
*
|
||||
* During the boot, all masters other than DMA Ctrlr + list
|
||||
* are non-secure in an AB Prod/AB Dev/AB Pending device.
|
||||
*
|
||||
*/
|
||||
void plat_tz_master_default_cfg(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Configure default secure and non-secure TZ Masters */
|
||||
for (i = 0; i < ARRAY_SIZE(tz_master_defaults); i++) {
|
||||
tz_master_set(tz_master_defaults[i].addr,
|
||||
tz_master_defaults[i].val,
|
||||
SECURE_MASTER);
|
||||
tz_master_set(tz_master_defaults[i].addr,
|
||||
~tz_master_defaults[i].val,
|
||||
NS_MASTER);
|
||||
}
|
||||
|
||||
/* Clear all master NS */
|
||||
mmio_setbits_32(SOTP_CHIP_CTRL,
|
||||
1 << SOTP_CLEAR_SYSCTRL_ALL_MASTER_NS);
|
||||
|
||||
/* Initialize TZ controller and Set SRAM to secure */
|
||||
bcm_tzc_setup();
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, 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[] = {
|
||||
#ifdef SCP_BL2_BASE
|
||||
/* Fill SCP_BL2 related information if it exists */
|
||||
{
|
||||
.image_id = SCP_BL2_IMAGE_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, 0),
|
||||
.image_info.image_base = SCP_BL2_BASE,
|
||||
.image_info.image_max_size = PLAT_MAX_SCP_BL2_SIZE,
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
#endif /* SCP_BL2_BASE */
|
||||
|
||||
/* Fill BL31 related information */
|
||||
{
|
||||
.image_id = BL31_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | EXECUTABLE | EP_FIRST_EXE),
|
||||
.ep_info.pc = BL31_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
#if DEBUG
|
||||
.ep_info.args.arg3 = BRCM_BL31_PLAT_PARAM_VAL,
|
||||
#endif
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
|
||||
.image_info.image_base = BL31_BASE,
|
||||
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
|
||||
|
||||
#ifdef BL32_BASE
|
||||
.next_handoff_image_id = BL32_IMAGE_ID,
|
||||
#else
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
#endif
|
||||
},
|
||||
|
||||
#ifdef BL32_BASE
|
||||
/* 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_info.pc = BL32_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
|
||||
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
},
|
||||
#endif /* BL32_BASE */
|
||||
|
||||
/* 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),
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
.ep_info.pc = PRELOADED_BL33_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
|
||||
#else
|
||||
.ep_info.pc = PLAT_BRCM_NS_IMAGE_OFFSET,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = PLAT_BRCM_NS_IMAGE_OFFSET,
|
||||
.image_info.image_max_size = BRCM_DRAM1_SIZE,
|
||||
#endif /* PRELOADED_BL33_BASE */
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.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/arm/sp804_delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <bcm_console.h>
|
||||
#include <platform_def.h>
|
||||
#include <plat/brcm/common/plat_brcm.h>
|
||||
|
||||
/* Data structure which holds the extents of the trusted SRAM for BL2 */
|
||||
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
|
||||
|
||||
/* Weak definitions may be overridden in specific BRCM platform */
|
||||
#pragma weak plat_bcm_bl2_platform_setup
|
||||
#pragma weak plat_bcm_bl2_plat_arch_setup
|
||||
#pragma weak plat_bcm_security_setup
|
||||
#pragma weak plat_bcm_bl2_plat_handle_scp_bl2
|
||||
#pragma weak plat_bcm_bl2_early_platform_setup
|
||||
|
||||
void plat_bcm_bl2_early_platform_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_bcm_bl2_platform_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_bcm_bl2_plat_arch_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_bcm_security_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bcm_bl2_early_platform_setup(uintptr_t tb_fw_config,
|
||||
meminfo_t *mem_layout)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
bcm_console_boot_init();
|
||||
|
||||
/* Setup the BL2 memory layout */
|
||||
bl2_tzram_layout = *mem_layout;
|
||||
|
||||
/* Initialise the IO layer and register platform IO devices */
|
||||
plat_brcm_io_setup();
|
||||
|
||||
/* Log HW reset event */
|
||||
INFO("RESET: 0x%x\n",
|
||||
mmio_read_32(CRMU_RESET_EVENT_LOG));
|
||||
}
|
||||
|
||||
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* SoC specific setup */
|
||||
plat_bcm_bl2_early_platform_setup();
|
||||
|
||||
/* Initialize delay timer driver using SP804 dual timer 0 */
|
||||
sp804_timer_init(SP804_TIMER0_BASE,
|
||||
SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV);
|
||||
|
||||
/* BRCM platforms generic setup */
|
||||
bcm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform Broadcom platform setup.
|
||||
*/
|
||||
void bcm_bl2_platform_setup(void)
|
||||
{
|
||||
/* Initialize the secure environment */
|
||||
plat_bcm_security_setup();
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
bcm_bl2_platform_setup();
|
||||
plat_bcm_bl2_platform_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform the very early platform specific architectural setup here. At the
|
||||
* moment this is only initializes the mmu in a quick and dirty way.
|
||||
******************************************************************************/
|
||||
void bcm_bl2_plat_arch_setup(void)
|
||||
{
|
||||
#ifndef MMU_DISABLED
|
||||
if (!(read_sctlr_el1() & SCTLR_M_BIT)) {
|
||||
const mmap_region_t bl_regions[] = {
|
||||
MAP_REGION_FLAT(bl2_tzram_layout.total_base,
|
||||
bl2_tzram_layout.total_size,
|
||||
MT_MEMORY | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(BL_CODE_BASE,
|
||||
BL_CODE_END - BL_CODE_BASE,
|
||||
MT_CODE | MT_SECURE),
|
||||
MAP_REGION_FLAT(BL_RO_DATA_BASE,
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE,
|
||||
MT_RO_DATA | MT_SECURE),
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
|
||||
BL_COHERENT_RAM_END -
|
||||
BL_COHERENT_RAM_BASE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
|
||||
setup_page_tables(bl_regions, plat_brcm_get_mmap());
|
||||
enable_mmu_el1(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void bl2_plat_arch_setup(void)
|
||||
{
|
||||
#ifdef ENA_MMU_BEFORE_DDR_INIT
|
||||
/*
|
||||
* Once MMU is enabled before DDR, MEMORY TESTS
|
||||
* get affected as read/write transaction might occures from
|
||||
* caches. So For running memory test, one should not set this
|
||||
* flag.
|
||||
*/
|
||||
bcm_bl2_plat_arch_setup();
|
||||
plat_bcm_bl2_plat_arch_setup();
|
||||
#else
|
||||
plat_bcm_bl2_plat_arch_setup();
|
||||
bcm_bl2_plat_arch_setup();
|
||||
#endif
|
||||
}
|
||||
|
||||
int bcm_bl2_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);
|
||||
|
||||
assert(bl_mem_params);
|
||||
|
||||
switch (image_id) {
|
||||
case BL32_IMAGE_ID:
|
||||
bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl32_entry();
|
||||
break;
|
||||
|
||||
case BL33_IMAGE_ID:
|
||||
/* BL33 expects to receive the primary CPU MPID (through r0) */
|
||||
bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
|
||||
bl_mem_params->ep_info.spsr = brcm_get_spsr_for_bl33_entry();
|
||||
break;
|
||||
|
||||
#ifdef SCP_BL2_BASE
|
||||
case SCP_BL2_IMAGE_ID:
|
||||
/* The subsequent handling of SCP_BL2 is platform specific */
|
||||
err = bcm_bl2_handle_scp_bl2(&bl_mem_params->image_info);
|
||||
if (err)
|
||||
WARN("Failure in platform-specific handling of SCP_BL2 image.\n");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Do nothing in default case */
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function can be used by the platforms to update/use image
|
||||
* information for given `image_id`.
|
||||
******************************************************************************/
|
||||
int bcm_bl2_plat_handle_post_image_load(unsigned int image_id)
|
||||
{
|
||||
return bcm_bl2_handle_post_image_load(image_id);
|
||||
}
|
||||
|
||||
int bl2_plat_handle_post_image_load(unsigned int image_id)
|
||||
{
|
||||
return bcm_bl2_plat_handle_post_image_load(image_id);
|
||||
}
|
||||
|
||||
#ifdef SCP_BL2_BASE
|
||||
int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bcm_bl2_handle_scp_bl2(image_info_t *scp_bl2_image_info)
|
||||
{
|
||||
return plat_bcm_bl2_plat_handle_scp_bl2(scp_bl2_image_info);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/sp804_delay_timer.h>
|
||||
#include <lib/utils.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <bcm_console.h>
|
||||
#include <plat_brcm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#ifdef BL33_SHARED_DDR_BASE
|
||||
struct bl33_info *bl33_info = (struct bl33_info *)BL33_SHARED_DDR_BASE;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Placeholder variables for copying the arguments that have been passed to
|
||||
* BL31 from BL2.
|
||||
*/
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
|
||||
/* Weak definitions may be overridden in specific BRCM platform */
|
||||
#pragma weak plat_bcm_bl31_early_platform_setup
|
||||
#pragma weak plat_brcm_pwrc_setup
|
||||
#pragma weak plat_brcm_security_setup
|
||||
|
||||
void plat_brcm_security_setup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void plat_brcm_pwrc_setup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void plat_bcm_bl31_early_platform_setup(void *from_bl2,
|
||||
bl_params_t *plat_params_from_bl2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
|
||||
assert(sec_state_is_valid(type));
|
||||
next_image_info = (type == NON_SECURE)
|
||||
? &bl33_image_ep_info : &bl32_image_ep_info;
|
||||
/*
|
||||
* None of the images on the ARM development platforms can have 0x0
|
||||
* as the entrypoint
|
||||
*/
|
||||
if (next_image_info->pc)
|
||||
return next_image_info;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 early platform setup common to ARM standard platforms.
|
||||
* Here is an opportunity to copy parameters passed by the calling EL (S-EL1
|
||||
* in BL2 & EL3 in BL1) before they are lost (potentially). This needs to be
|
||||
* done before the MMU is initialized so that the memory layout can be used
|
||||
* while creating page tables. BL2 has flushed this information to memory, so
|
||||
* we are guaranteed to pick up good data.
|
||||
******************************************************************************/
|
||||
void __init brcm_bl31_early_platform_setup(void *from_bl2,
|
||||
uintptr_t soc_fw_config,
|
||||
uintptr_t hw_config,
|
||||
void *plat_params_from_bl2)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
bcm_console_boot_init();
|
||||
|
||||
/* Initialize delay timer driver using SP804 dual timer 0 */
|
||||
sp804_timer_init(SP804_TIMER0_BASE,
|
||||
SP804_TIMER0_CLKMULT, SP804_TIMER0_CLKDIV);
|
||||
|
||||
#if RESET_TO_BL31
|
||||
/* There are no parameters from BL2 if BL31 is a reset vector */
|
||||
assert(from_bl2 == NULL);
|
||||
assert(plat_params_from_bl2 == NULL);
|
||||
|
||||
# ifdef BL32_BASE
|
||||
/* Populate entry point information for BL32 */
|
||||
SET_PARAM_HEAD(&bl32_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
bl32_image_ep_info.spsr = brcm_get_spsr_for_bl32_entry();
|
||||
# endif /* BL32_BASE */
|
||||
|
||||
/* Populate entry point information for BL33 */
|
||||
SET_PARAM_HEAD(&bl33_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
|
||||
bl33_image_ep_info.spsr = brcm_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
# if ARM_LINUX_KERNEL_AS_BL33
|
||||
/*
|
||||
* According to the file ``Documentation/arm64/booting.txt`` of the
|
||||
* Linux kernel tree, Linux expects the physical address of the device
|
||||
* tree blob (DTB) in x0, while x1-x3 are reserved for future use and
|
||||
* must be 0.
|
||||
*/
|
||||
bl33_image_ep_info.args.arg0 = (u_register_t)PRELOADED_DTB_BASE;
|
||||
bl33_image_ep_info.args.arg1 = 0U;
|
||||
bl33_image_ep_info.args.arg2 = 0U;
|
||||
bl33_image_ep_info.args.arg3 = 0U;
|
||||
# endif
|
||||
|
||||
#else /* RESET_TO_BL31 */
|
||||
|
||||
/*
|
||||
* In debug builds, we pass a special value in 'plat_params_from_bl2'
|
||||
* to verify platform parameters from BL2 to BL31.
|
||||
* In release builds, it's not used.
|
||||
*/
|
||||
assert(((unsigned long long)plat_params_from_bl2) ==
|
||||
BRCM_BL31_PLAT_PARAM_VAL);
|
||||
|
||||
/*
|
||||
* Check params passed from BL2 should not be NULL
|
||||
*/
|
||||
bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
|
||||
|
||||
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 and BL32 (if present), entry point information.
|
||||
* They are stored in Secure RAM, in BL2's address space.
|
||||
*/
|
||||
while (bl_params != NULL) {
|
||||
if (bl_params->image_id == BL32_IMAGE_ID &&
|
||||
bl_params->image_info->h.attr != IMAGE_ATTRIB_SKIP_LOADING)
|
||||
bl32_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
if (bl_params->image_id == BL33_IMAGE_ID)
|
||||
bl33_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
bl_params = bl_params->next_params_info;
|
||||
}
|
||||
|
||||
if (bl33_image_ep_info.pc == 0U)
|
||||
panic();
|
||||
#endif /* RESET_TO_BL31 */
|
||||
|
||||
#ifdef BL33_SHARED_DDR_BASE
|
||||
/* Pass information to BL33 thorugh x0 */
|
||||
bl33_image_ep_info.args.arg0 = (u_register_t)BL33_SHARED_DDR_BASE;
|
||||
bl33_image_ep_info.args.arg1 = 0ULL;
|
||||
bl33_image_ep_info.args.arg2 = 0ULL;
|
||||
bl33_image_ep_info.args.arg3 = 0ULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
#ifdef BL31_LOG_LEVEL
|
||||
SET_LOG_LEVEL(BL31_LOG_LEVEL);
|
||||
#endif
|
||||
|
||||
brcm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
|
||||
|
||||
plat_bcm_bl31_early_platform_setup((void *)arg0, (void *)arg3);
|
||||
|
||||
#ifdef DRIVER_CC_ENABLE
|
||||
/*
|
||||
* Initialize Interconnect for this cluster during cold boot.
|
||||
* No need for locks as no other CPU is active.
|
||||
*/
|
||||
plat_brcm_interconnect_init();
|
||||
|
||||
/*
|
||||
* Enable Interconnect coherency for the primary CPU's cluster.
|
||||
* Earlier bootloader stages might already do this (e.g. Trusted
|
||||
* Firmware's BL1 does it) but we can't assume so. There is no harm in
|
||||
* executing this code twice anyway.
|
||||
* Platform specific PSCI code will enable coherency for other
|
||||
* clusters.
|
||||
*/
|
||||
plat_brcm_interconnect_enter_coherency();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 platform setup common to ARM standard platforms
|
||||
******************************************************************************/
|
||||
void brcm_bl31_platform_setup(void)
|
||||
{
|
||||
/* Initialize the GIC driver, cpu and distributor interfaces */
|
||||
plat_brcm_gic_driver_init();
|
||||
plat_brcm_gic_init();
|
||||
|
||||
/* Initialize power controller before setting up topology */
|
||||
plat_brcm_pwrc_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 platform runtime setup prior to BL31 exit common to ARM
|
||||
* standard platforms
|
||||
* Perform BL31 platform setup
|
||||
******************************************************************************/
|
||||
void brcm_bl31_plat_runtime_setup(void)
|
||||
{
|
||||
console_switch_state(CONSOLE_FLAG_RUNTIME);
|
||||
|
||||
/* Initialize the runtime console */
|
||||
bcm_console_runtime_init();
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
brcm_bl31_platform_setup();
|
||||
|
||||
/* Initialize the secure environment */
|
||||
plat_brcm_security_setup();
|
||||
}
|
||||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
brcm_bl31_plat_runtime_setup();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform the very early platform specific architectural setup shared between
|
||||
* ARM standard platforms. This only does basic initialization. Later
|
||||
* architectural setup (bl31_arch_setup()) does not do anything platform
|
||||
* specific.
|
||||
******************************************************************************/
|
||||
void __init brcm_bl31_plat_arch_setup(void)
|
||||
{
|
||||
#ifndef MMU_DISABLED
|
||||
const mmap_region_t bl_regions[] = {
|
||||
MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
|
||||
MT_MEMORY | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
|
||||
MT_CODE | MT_SECURE),
|
||||
MAP_REGION_FLAT(BL_RO_DATA_BASE,
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE,
|
||||
MT_RO_DATA | MT_SECURE),
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
|
||||
setup_page_tables(bl_regions, plat_brcm_get_mmap());
|
||||
|
||||
enable_mmu_el3(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init bl31_plat_arch_setup(void)
|
||||
{
|
||||
brcm_bl31_plat_arch_setup();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <drivers/arm/ccn.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
static const unsigned char master_to_rn_id_map[] = {
|
||||
PLAT_BRCM_CLUSTER_TO_CCN_ID_MAP
|
||||
};
|
||||
|
||||
static const ccn_desc_t bcm_ccn_desc = {
|
||||
.periphbase = PLAT_BRCM_CCN_BASE,
|
||||
.num_masters = ARRAY_SIZE(master_to_rn_id_map),
|
||||
.master_to_rn_id_map = master_to_rn_id_map
|
||||
};
|
||||
|
||||
void plat_brcm_interconnect_init(void)
|
||||
{
|
||||
ccn_init(&bcm_ccn_desc);
|
||||
}
|
||||
|
||||
void plat_brcm_interconnect_enter_coherency(void)
|
||||
{
|
||||
ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
|
||||
}
|
||||
|
||||
void plat_brcm_interconnect_exit_coherency(void)
|
||||
{
|
||||
ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <plat_brcm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* Weak definitions may be overridden in specific BRCM platform */
|
||||
#pragma weak plat_get_ns_image_entrypoint
|
||||
#pragma weak plat_brcm_get_mmap
|
||||
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
return PRELOADED_BL33_BASE;
|
||||
#else
|
||||
return PLAT_BRCM_NS_IMAGE_OFFSET;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t brcm_get_spsr_for_bl32_entry(void)
|
||||
{
|
||||
/*
|
||||
* The Secure Payload Dispatcher service is responsible for
|
||||
* setting the SPSR prior to entry into the BL32 image.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t brcm_get_spsr_for_bl33_entry(void)
|
||||
{
|
||||
unsigned int mode;
|
||||
uint32_t spsr;
|
||||
|
||||
/* Figure out what mode we enter the non-secure world in */
|
||||
mode = el_implemented(2) ? MODE_EL2 : MODE_EL1;
|
||||
|
||||
/*
|
||||
* TODO: Consider the possibility of specifying the SPSR in
|
||||
* the FIP ToC and allowing the platform to have a say as
|
||||
* well.
|
||||
*/
|
||||
spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
return spsr;
|
||||
}
|
||||
|
||||
const mmap_region_t *plat_brcm_get_mmap(void)
|
||||
{
|
||||
return plat_brcm_mmap;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* The GICv3 driver only needs to be initialized in EL3 */
|
||||
static uintptr_t brcm_rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
||||
|
||||
static const interrupt_prop_t brcm_interrupt_props[] = {
|
||||
/* G1S interrupts */
|
||||
PLAT_BRCM_G1S_IRQ_PROPS(INTR_GROUP1S),
|
||||
/* G0 interrupts */
|
||||
PLAT_BRCM_G0_IRQ_PROPS(INTR_GROUP0)
|
||||
};
|
||||
|
||||
/*
|
||||
* MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
|
||||
* to core position.
|
||||
*
|
||||
* Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
|
||||
* values read from GICR_TYPER don't have an MT field. To reuse the same
|
||||
* translation used for CPUs, we insert MT bit read from the PE's MPIDR into
|
||||
* that read from GICR_TYPER.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
* - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
|
||||
* - No CPUs implemented in the system use affinity level 3.
|
||||
*/
|
||||
static unsigned int brcm_gicv3_mpidr_hash(u_register_t mpidr)
|
||||
{
|
||||
mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
|
||||
return plat_core_pos_by_mpidr(mpidr);
|
||||
}
|
||||
|
||||
static const gicv3_driver_data_t brcm_gic_data = {
|
||||
.gicd_base = PLAT_BRCM_GICD_BASE,
|
||||
.gicr_base = PLAT_BRCM_GICR_BASE,
|
||||
.interrupt_props = brcm_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(brcm_interrupt_props),
|
||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
||||
.rdistif_base_addrs = brcm_rdistif_base_addrs,
|
||||
.mpidr_to_core_pos = brcm_gicv3_mpidr_hash
|
||||
};
|
||||
|
||||
void plat_brcm_gic_driver_init(void)
|
||||
{
|
||||
/* TODO Check if this is required to be initialized here
|
||||
* after getting initialized in EL3, should we re-init this here
|
||||
* in S-EL1
|
||||
*/
|
||||
gicv3_driver_init(&brcm_gic_data);
|
||||
}
|
||||
|
||||
void plat_brcm_gic_init(void)
|
||||
{
|
||||
gicv3_distif_init();
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void plat_brcm_gic_cpuif_enable(void)
|
||||
{
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void plat_brcm_gic_cpuif_disable(void)
|
||||
{
|
||||
gicv3_cpuif_disable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void plat_brcm_gic_pcpu_init(void)
|
||||
{
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void plat_brcm_gic_redistif_on(void)
|
||||
{
|
||||
gicv3_rdistif_on(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void plat_brcm_gic_redistif_off(void)
|
||||
{
|
||||
gicv3_rdistif_off(plat_my_core_pos());
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, 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>
|
||||
|
||||
#pragma weak plat_flush_next_bl_params
|
||||
#pragma weak plat_get_bl_image_load_info
|
||||
#pragma weak plat_get_next_bl_params
|
||||
|
||||
/*******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
struct bl_load_info *plat_get_bl_image_load_info(void)
|
||||
{
|
||||
return get_bl_load_info_from_mem_params_desc();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the list of executable images.
|
||||
******************************************************************************/
|
||||
struct bl_params *plat_get_next_bl_params(void)
|
||||
{
|
||||
bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc();
|
||||
|
||||
populate_next_bl_params_config(next_bl_params);
|
||||
return next_bl_params;
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/io/io_driver.h>
|
||||
#include <drivers/io/io_fip.h>
|
||||
#include <drivers/io/io_memmap.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <tools_share/firmware_image_package.h>
|
||||
|
||||
#include <cmn_plat_def.h>
|
||||
#include <cmn_plat_util.h>
|
||||
#include <plat_brcm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* IO devices */
|
||||
static const io_dev_connector_t *fip_dev_con;
|
||||
static uintptr_t fip_dev_handle;
|
||||
static const io_dev_connector_t *memmap_dev_con;
|
||||
static uintptr_t memmap_dev_handle;
|
||||
|
||||
static const io_block_spec_t fip_block_spec = {
|
||||
.offset = PLAT_BRCM_FIP_BASE,
|
||||
.length = PLAT_BRCM_FIP_MAX_SIZE
|
||||
};
|
||||
|
||||
static const io_block_spec_t qspi_fip_block_spec = {
|
||||
.offset = PLAT_BRCM_FIP_QSPI_BASE,
|
||||
.length = PLAT_BRCM_FIP_MAX_SIZE
|
||||
};
|
||||
|
||||
static const io_block_spec_t nand_fip_block_spec = {
|
||||
.offset = PLAT_BRCM_FIP_NAND_BASE,
|
||||
.length = PLAT_BRCM_FIP_MAX_SIZE
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl2_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t scp_bl2_uuid_spec = {
|
||||
.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl31_uuid_spec = {
|
||||
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_extra1_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_extra2_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl33_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t tb_fw_config_uuid_spec = {
|
||||
.uuid = UUID_TB_FW_CONFIG,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t hw_config_uuid_spec = {
|
||||
.uuid = UUID_HW_CONFIG,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t soc_fw_config_uuid_spec = {
|
||||
.uuid = UUID_SOC_FW_CONFIG,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t tos_fw_config_uuid_spec = {
|
||||
.uuid = UUID_TOS_FW_CONFIG,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t nt_fw_config_uuid_spec = {
|
||||
.uuid = UUID_NT_FW_CONFIG,
|
||||
};
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FW_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_SCP_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_SOC_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_SCP_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_SOC_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
|
||||
};
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
static int open_fip(const uintptr_t spec);
|
||||
static int open_memmap(const uintptr_t spec);
|
||||
static int open_qspi(const uintptr_t spec);
|
||||
static int open_nand(const uintptr_t spec);
|
||||
|
||||
struct plat_io_policy {
|
||||
uintptr_t *dev_handle;
|
||||
uintptr_t image_spec;
|
||||
int (*check)(const uintptr_t spec);
|
||||
};
|
||||
|
||||
/* By default, BRCM platforms load images from the FIP */
|
||||
static const struct plat_io_policy policies[] = {
|
||||
[FIP_IMAGE_ID] = {
|
||||
&memmap_dev_handle,
|
||||
(uintptr_t)&fip_block_spec,
|
||||
open_memmap
|
||||
},
|
||||
[BL2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl2_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SCP_BL2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&scp_bl2_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL31_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl31_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_EXTRA1_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_extra1_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_EXTRA2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_extra2_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL33_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl33_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TB_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tb_fw_config_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[HW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&hw_config_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&soc_fw_config_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TOS_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tos_fw_config_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[NT_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&nt_fw_config_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[TRUSTED_BOOT_FW_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tb_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&trusted_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SCP_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&scp_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&soc_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_OS_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tos_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[NON_TRUSTED_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&nt_fw_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SCP_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&scp_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&soc_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&tos_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&nt_fw_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
};
|
||||
|
||||
/* By default, BRCM platforms load images from the FIP */
|
||||
static const struct plat_io_policy boot_source_policies[] = {
|
||||
[BOOT_SOURCE_QSPI] = {
|
||||
&memmap_dev_handle,
|
||||
(uintptr_t)&qspi_fip_block_spec,
|
||||
open_qspi
|
||||
},
|
||||
[BOOT_SOURCE_NAND] = {
|
||||
&memmap_dev_handle,
|
||||
(uintptr_t)&nand_fip_block_spec,
|
||||
open_nand
|
||||
},
|
||||
};
|
||||
|
||||
/* Weak definitions may be overridden in specific brcm platform */
|
||||
#pragma weak plat_brcm_io_setup
|
||||
#pragma weak plat_brcm_process_flags
|
||||
|
||||
static int open_fip(const uintptr_t spec)
|
||||
{
|
||||
int result;
|
||||
uintptr_t local_image_handle;
|
||||
|
||||
/* See if a Firmware Image Package is available */
|
||||
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
|
||||
if (result == 0) {
|
||||
result = io_open(fip_dev_handle, spec, &local_image_handle);
|
||||
if (result == 0) {
|
||||
VERBOSE("Using FIP\n");
|
||||
io_close(local_image_handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int open_memmap(const uintptr_t spec)
|
||||
{
|
||||
int result;
|
||||
uintptr_t local_image_handle;
|
||||
|
||||
result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
|
||||
if (result == 0) {
|
||||
result = io_open(memmap_dev_handle, spec, &local_image_handle);
|
||||
if (result == 0) {
|
||||
VERBOSE("Using Memmap\n");
|
||||
io_close(local_image_handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int open_qspi(const uintptr_t spec)
|
||||
{
|
||||
return open_memmap(spec);
|
||||
}
|
||||
|
||||
static int open_nand(const uintptr_t spec)
|
||||
{
|
||||
return open_memmap(spec);
|
||||
}
|
||||
|
||||
|
||||
void brcm_io_setup(void)
|
||||
{
|
||||
int io_result;
|
||||
uint32_t boot_source;
|
||||
|
||||
io_result = register_io_dev_fip(&fip_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
io_result = register_io_dev_memmap(&memmap_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
/* Open connections to devices and cache the handles */
|
||||
io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
|
||||
&fip_dev_handle);
|
||||
assert(io_result == 0);
|
||||
|
||||
boot_source = boot_source_get();
|
||||
switch (boot_source) {
|
||||
case BOOT_SOURCE_QSPI:
|
||||
case BOOT_SOURCE_NAND:
|
||||
default:
|
||||
io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
|
||||
&memmap_dev_handle);
|
||||
break;
|
||||
}
|
||||
assert(io_result == 0);
|
||||
|
||||
/* Ignore improbable errors in release builds */
|
||||
(void)io_result;
|
||||
}
|
||||
|
||||
void plat_brcm_io_setup(void)
|
||||
{
|
||||
brcm_io_setup();
|
||||
}
|
||||
|
||||
void plat_brcm_process_flags(uint16_t plat_toc_flags __unused)
|
||||
{
|
||||
WARN("%s not implemented\n", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an IO device handle and specification which can be used to access
|
||||
* an image. Use this to enforce platform load policy
|
||||
*/
|
||||
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
|
||||
uintptr_t *image_spec)
|
||||
{
|
||||
int result;
|
||||
const struct plat_io_policy *policy;
|
||||
uint32_t boot_source;
|
||||
uint16_t lcl_plat_toc_flg;
|
||||
|
||||
assert(image_id < ARRAY_SIZE(policies));
|
||||
|
||||
boot_source = boot_source_get();
|
||||
if (image_id == FIP_IMAGE_ID)
|
||||
policy = &boot_source_policies[boot_source];
|
||||
else
|
||||
policy = &policies[image_id];
|
||||
|
||||
result = policy->check(policy->image_spec);
|
||||
if (result == 0) {
|
||||
*image_spec = policy->image_spec;
|
||||
*dev_handle = *(policy->dev_handle);
|
||||
|
||||
if (image_id == TRUSTED_BOOT_FW_CERT_ID) {
|
||||
/*
|
||||
* Process the header flags to perform
|
||||
* such custom actions as speeding up PLL.
|
||||
* CERT seems to be the first image accessed
|
||||
* by BL1 so this is where we process the flags.
|
||||
*/
|
||||
fip_dev_get_plat_toc_flag((io_dev_info_t *)fip_dev_handle,
|
||||
&lcl_plat_toc_flg);
|
||||
plat_brcm_process_flags(lcl_plat_toc_flg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
|
||||
#include <brcm_mhu.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "m0_ipc.h"
|
||||
|
||||
#define PLAT_MHU_INTR_REG AP_TO_SCP_MAILBOX1
|
||||
|
||||
/* SCP MHU secure channel registers */
|
||||
#define SCP_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG11
|
||||
#define SCP_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG11
|
||||
#define SCP_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG11
|
||||
|
||||
/* CPU MHU secure channel registers */
|
||||
#define CPU_INTR_S_STAT CRMU_IHOST_SW_PERSISTENT_REG10
|
||||
#define CPU_INTR_S_SET CRMU_IHOST_SW_PERSISTENT_REG10
|
||||
#define CPU_INTR_S_CLEAR CRMU_IHOST_SW_PERSISTENT_REG10
|
||||
|
||||
static DEFINE_BAKERY_LOCK(bcm_lock);
|
||||
|
||||
/*
|
||||
* Slot 31 is reserved because the MHU hardware uses this register bit to
|
||||
* indicate a non-secure access attempt. The total number of available slots is
|
||||
* therefore 31 [30:0].
|
||||
*/
|
||||
#define MHU_MAX_SLOT_ID 30
|
||||
|
||||
void mhu_secure_message_start(unsigned int slot_id)
|
||||
{
|
||||
int iter = 1000000;
|
||||
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
|
||||
bakery_lock_get(&bcm_lock);
|
||||
/* Make sure any previous command has finished */
|
||||
do {
|
||||
if (!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
|
||||
(1 << slot_id)))
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
|
||||
} while (--iter);
|
||||
|
||||
assert(iter != 0);
|
||||
}
|
||||
|
||||
void mhu_secure_message_send(unsigned int slot_id)
|
||||
{
|
||||
uint32_t response, iter = 1000000;
|
||||
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
assert(!(mmio_read_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT) &
|
||||
(1 << slot_id)));
|
||||
|
||||
/* Send command to SCP */
|
||||
mmio_setbits_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
|
||||
mmio_write_32(CRMU_MAIL_BOX0, MCU_IPC_MCU_CMD_SCPI);
|
||||
mmio_write_32(PLAT_BRCM_MHU_BASE + PLAT_MHU_INTR_REG, 0x1);
|
||||
|
||||
/* Wait until IPC transport acknowledges reception of SCP command */
|
||||
do {
|
||||
response = mmio_read_32(CRMU_MAIL_BOX0);
|
||||
if ((response & ~MCU_IPC_CMD_REPLY_MASK) ==
|
||||
(MCU_IPC_CMD_DONE_MASK | MCU_IPC_MCU_CMD_SCPI))
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
|
||||
} while (--iter);
|
||||
|
||||
assert(iter != 0);
|
||||
}
|
||||
|
||||
uint32_t mhu_secure_message_wait(void)
|
||||
{
|
||||
/* Wait for response from SCP */
|
||||
uint32_t response, iter = 1000000;
|
||||
|
||||
do {
|
||||
response = mmio_read_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT);
|
||||
if (!response)
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
} while (--iter);
|
||||
assert(iter != 0);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void mhu_secure_message_end(unsigned int slot_id)
|
||||
{
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
|
||||
/*
|
||||
* Clear any response we got by writing one in the relevant slot bit to
|
||||
* the CLEAR register
|
||||
*/
|
||||
mmio_clrbits_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
|
||||
bakery_lock_release(&bcm_lock);
|
||||
}
|
||||
|
||||
void mhu_secure_init(void)
|
||||
{
|
||||
bakery_lock_init(&bcm_lock);
|
||||
|
||||
/*
|
||||
* The STAT register resets to zero. Ensure it is in the expected state,
|
||||
* as a stale or garbage value would make us think it's a message we've
|
||||
* already sent.
|
||||
*/
|
||||
mmio_write_32(PLAT_BRCM_MHU_BASE + CPU_INTR_S_STAT, 0);
|
||||
mmio_write_32(PLAT_BRCM_MHU_BASE + SCP_INTR_S_STAT, 0);
|
||||
}
|
||||
|
||||
void plat_brcm_pwrc_setup(void)
|
||||
{
|
||||
mhu_secure_init();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef BRCM_MHU_H
|
||||
#define BRCM_MHU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void mhu_secure_message_start(unsigned int slot_id);
|
||||
void mhu_secure_message_send(unsigned int slot_id);
|
||||
uint32_t mhu_secure_message_wait(void);
|
||||
void mhu_secure_message_end(unsigned int slot_id);
|
||||
|
||||
void mhu_secure_init(void);
|
||||
|
||||
#endif /* BRCM_MHU_H */
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/utils.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <brcm_mhu.h>
|
||||
#include <brcm_scpi.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define SCPI_SHARED_MEM_SCP_TO_AP (PLAT_SCP_COM_SHARED_MEM_BASE)
|
||||
#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SCP_COM_SHARED_MEM_BASE \
|
||||
+ 0x100)
|
||||
|
||||
/* Header and payload addresses for commands from AP to SCP */
|
||||
#define SCPI_CMD_HEADER_AP_TO_SCP \
|
||||
((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
|
||||
#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
|
||||
((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
|
||||
|
||||
/* Header and payload addresses for responses from SCP to AP */
|
||||
#define SCPI_RES_HEADER_SCP_TO_AP \
|
||||
((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP)
|
||||
#define SCPI_RES_PAYLOAD_SCP_TO_AP \
|
||||
((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t)))
|
||||
|
||||
/* ID of the MHU slot used for the SCPI protocol */
|
||||
#define SCPI_MHU_SLOT_ID 0
|
||||
|
||||
static void scpi_secure_message_start(void)
|
||||
{
|
||||
mhu_secure_message_start(SCPI_MHU_SLOT_ID);
|
||||
}
|
||||
|
||||
static void scpi_secure_message_send(size_t payload_size)
|
||||
{
|
||||
/*
|
||||
* Ensure that any write to the SCPI payload area is seen by SCP before
|
||||
* we write to the MHU register. If these 2 writes were reordered by
|
||||
* the CPU then SCP would read stale payload data
|
||||
*/
|
||||
dmbst();
|
||||
|
||||
mhu_secure_message_send(SCPI_MHU_SLOT_ID);
|
||||
}
|
||||
|
||||
static void scpi_secure_message_receive(scpi_cmd_t *cmd)
|
||||
{
|
||||
uint32_t mhu_status;
|
||||
|
||||
assert(cmd != NULL);
|
||||
|
||||
mhu_status = mhu_secure_message_wait();
|
||||
|
||||
/* Expect an SCPI message, reject any other protocol */
|
||||
if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
|
||||
ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
|
||||
mhu_status);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that any read to the SCPI payload area is done after reading
|
||||
* the MHU register. If these 2 reads were reordered then the CPU would
|
||||
* read invalid payload data
|
||||
*/
|
||||
dmbld();
|
||||
|
||||
memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
|
||||
}
|
||||
|
||||
static void scpi_secure_message_end(void)
|
||||
{
|
||||
mhu_secure_message_end(SCPI_MHU_SLOT_ID);
|
||||
}
|
||||
|
||||
int scpi_wait_ready(void)
|
||||
{
|
||||
scpi_cmd_t scpi_cmd;
|
||||
|
||||
VERBOSE("Waiting for SCP_READY command...\n");
|
||||
|
||||
/* Get a message from the SCP */
|
||||
scpi_secure_message_start();
|
||||
scpi_secure_message_receive(&scpi_cmd);
|
||||
scpi_secure_message_end();
|
||||
|
||||
/* We are expecting 'SCP Ready', produce correct error if it's not */
|
||||
scpi_status_t status = SCP_OK;
|
||||
|
||||
if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
|
||||
ERROR("Unexpected SCP command: expected #%u, received #%u\n",
|
||||
SCPI_CMD_SCP_READY, scpi_cmd.id);
|
||||
status = SCP_E_SUPPORT;
|
||||
} else if (scpi_cmd.size != 0) {
|
||||
ERROR("SCP_READY cmd has incorrect size: expected 0, got %u\n",
|
||||
scpi_cmd.size);
|
||||
status = SCP_E_SIZE;
|
||||
}
|
||||
|
||||
VERBOSE("Sending response for SCP_READY command\n");
|
||||
|
||||
/*
|
||||
* Send our response back to SCP.
|
||||
* We are using the same SCPI header, just update the status field.
|
||||
*/
|
||||
scpi_cmd.status = status;
|
||||
scpi_secure_message_start();
|
||||
memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
|
||||
scpi_secure_message_send(0);
|
||||
scpi_secure_message_end();
|
||||
|
||||
return status == SCP_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
void scpi_set_brcm_power_state(unsigned int mpidr,
|
||||
scpi_power_state_t cpu_state, scpi_power_state_t cluster_state,
|
||||
scpi_power_state_t brcm_state)
|
||||
{
|
||||
scpi_cmd_t *cmd;
|
||||
uint32_t state = 0;
|
||||
uint32_t *payload_addr;
|
||||
|
||||
#if ARM_PLAT_MT
|
||||
/*
|
||||
* The current SCPI driver only caters for single-threaded platforms.
|
||||
* Hence we ignore the thread ID (which is always 0) for such platforms.
|
||||
*/
|
||||
state |= (mpidr >> MPIDR_AFF1_SHIFT) & 0x0f; /* CPU ID */
|
||||
state |= ((mpidr >> MPIDR_AFF2_SHIFT) & 0x0f) << 4; /* Cluster ID */
|
||||
#else
|
||||
state |= mpidr & 0x0f; /* CPU ID */
|
||||
state |= (mpidr & 0xf00) >> 4; /* Cluster ID */
|
||||
#endif /* ARM_PLAT_MT */
|
||||
|
||||
state |= cpu_state << 8;
|
||||
state |= cluster_state << 12;
|
||||
state |= brcm_state << 16;
|
||||
|
||||
scpi_secure_message_start();
|
||||
|
||||
/* Populate the command header */
|
||||
cmd = SCPI_CMD_HEADER_AP_TO_SCP;
|
||||
cmd->id = SCPI_CMD_SET_POWER_STATE;
|
||||
cmd->set = SCPI_SET_NORMAL;
|
||||
cmd->sender = 0;
|
||||
cmd->size = sizeof(state);
|
||||
/* Populate the command payload */
|
||||
payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
|
||||
*payload_addr = state;
|
||||
scpi_secure_message_send(sizeof(state));
|
||||
|
||||
/*
|
||||
* SCP does not reply to this command in order to avoid MHU interrupts
|
||||
* from the sender, which could interfere with its power state request.
|
||||
*/
|
||||
scpi_secure_message_end();
|
||||
}
|
||||
|
||||
/*
|
||||
* Query and obtain power state from SCP.
|
||||
*
|
||||
* In response to the query, SCP returns power states of all CPUs in all
|
||||
* clusters of the system. The returned response is then filtered based on the
|
||||
* supplied MPIDR. Power states of requested cluster and CPUs within are updated
|
||||
* via. supplied non-NULL pointer arguments.
|
||||
*
|
||||
* Returns 0 on success, or -1 on errors.
|
||||
*/
|
||||
int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
|
||||
unsigned int *cluster_state_p)
|
||||
{
|
||||
scpi_cmd_t *cmd;
|
||||
scpi_cmd_t response;
|
||||
int power_state, cpu, cluster, rc = -1;
|
||||
|
||||
/*
|
||||
* Extract CPU and cluster membership of the given MPIDR. SCPI caters
|
||||
* for only up to 0xf clusters, and 8 CPUs per cluster
|
||||
*/
|
||||
cpu = mpidr & MPIDR_AFFLVL_MASK;
|
||||
cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
if (cpu >= 8 || cluster >= 0xf)
|
||||
return -1;
|
||||
|
||||
scpi_secure_message_start();
|
||||
|
||||
/* Populate request headers */
|
||||
zeromem(SCPI_CMD_HEADER_AP_TO_SCP, sizeof(*cmd));
|
||||
cmd = SCPI_CMD_HEADER_AP_TO_SCP;
|
||||
cmd->id = SCPI_CMD_GET_POWER_STATE;
|
||||
|
||||
/*
|
||||
* Send message and wait for SCP's response
|
||||
*/
|
||||
scpi_secure_message_send(0);
|
||||
scpi_secure_message_receive(&response);
|
||||
|
||||
if (response.status != SCP_OK)
|
||||
goto exit;
|
||||
|
||||
/* Validate SCP response */
|
||||
if (!CHECK_RESPONSE(response, cluster))
|
||||
goto exit;
|
||||
|
||||
/* Extract power states for required cluster */
|
||||
power_state = *(((uint16_t *) SCPI_RES_PAYLOAD_SCP_TO_AP) + cluster);
|
||||
if (CLUSTER_ID(power_state) != cluster)
|
||||
goto exit;
|
||||
|
||||
/* Update power state via. pointers */
|
||||
if (cluster_state_p)
|
||||
*cluster_state_p = CLUSTER_POWER_STATE(power_state);
|
||||
if (cpu_state_p)
|
||||
*cpu_state_p = CPU_POWER_STATE(power_state);
|
||||
rc = 0;
|
||||
|
||||
exit:
|
||||
scpi_secure_message_end();
|
||||
return rc;
|
||||
}
|
||||
|
||||
uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
|
||||
{
|
||||
scpi_cmd_t *cmd;
|
||||
uint8_t *payload_addr;
|
||||
|
||||
scpi_secure_message_start();
|
||||
|
||||
/* Populate the command header */
|
||||
cmd = SCPI_CMD_HEADER_AP_TO_SCP;
|
||||
cmd->id = SCPI_CMD_SYS_POWER_STATE;
|
||||
cmd->set = 0;
|
||||
cmd->sender = 0;
|
||||
cmd->size = sizeof(*payload_addr);
|
||||
/* Populate the command payload */
|
||||
payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
|
||||
*payload_addr = system_state & 0xff;
|
||||
scpi_secure_message_send(sizeof(*payload_addr));
|
||||
|
||||
scpi_secure_message_end();
|
||||
|
||||
return SCP_OK;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef BRCM_SCPI_H
|
||||
#define BRCM_SCPI_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* An SCPI command consists of a header and a payload.
|
||||
* The following structure describes the header. It is 64-bit long.
|
||||
*/
|
||||
typedef struct {
|
||||
/* Command ID */
|
||||
uint32_t id : 7;
|
||||
/* Set ID. Identifies whether this is a standard or extended command. */
|
||||
uint32_t set : 1;
|
||||
/* Sender ID to match a reply. The value is sender specific. */
|
||||
uint32_t sender : 8;
|
||||
/* Size of the payload in bytes (0 - 511) */
|
||||
uint32_t size : 9;
|
||||
uint32_t reserved : 7;
|
||||
/*
|
||||
* Status indicating the success of a command.
|
||||
* See the enum below.
|
||||
*/
|
||||
uint32_t status;
|
||||
} scpi_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
SCPI_SET_NORMAL = 0, /* Normal SCPI commands */
|
||||
SCPI_SET_EXTENDED /* Extended SCPI commands */
|
||||
} scpi_set_t;
|
||||
|
||||
enum {
|
||||
SCP_OK = 0, /* Success */
|
||||
SCP_E_PARAM, /* Invalid parameter(s) */
|
||||
SCP_E_ALIGN, /* Invalid alignment */
|
||||
SCP_E_SIZE, /* Invalid size */
|
||||
SCP_E_HANDLER, /* Invalid handler or callback */
|
||||
SCP_E_ACCESS, /* Invalid access or permission denied */
|
||||
SCP_E_RANGE, /* Value out of range */
|
||||
SCP_E_TIMEOUT, /* Time out has ocurred */
|
||||
SCP_E_NOMEM, /* Invalid memory area or pointer */
|
||||
SCP_E_PWRSTATE, /* Invalid power state */
|
||||
SCP_E_SUPPORT, /* Feature not supported or disabled */
|
||||
SCPI_E_DEVICE, /* Device error */
|
||||
SCPI_E_BUSY, /* Device is busy */
|
||||
};
|
||||
|
||||
typedef uint32_t scpi_status_t;
|
||||
typedef enum {
|
||||
SCPI_CMD_SCP_READY = 0x01,
|
||||
SCPI_CMD_SET_POWER_STATE = 0x03,
|
||||
SCPI_CMD_GET_POWER_STATE = 0x04,
|
||||
SCPI_CMD_SYS_POWER_STATE = 0x05
|
||||
} scpi_command_t;
|
||||
|
||||
/*
|
||||
* Macros to parse SCP response to GET_POWER_STATE command
|
||||
*
|
||||
* [3:0] : cluster ID
|
||||
* [7:4] : cluster state: 0 = on; 3 = off; rest are reserved
|
||||
* [15:8]: on/off state for individual CPUs in the cluster
|
||||
*
|
||||
* Payload is in little-endian
|
||||
*/
|
||||
#define CLUSTER_ID(_resp) ((_resp) & 0xf)
|
||||
#define CLUSTER_POWER_STATE(_resp) (((_resp) >> 4) & 0xf)
|
||||
|
||||
/* Result is a bit mask of CPU on/off states in the cluster */
|
||||
#define CPU_POWER_STATE(_resp) (((_resp) >> 8) & 0xff)
|
||||
|
||||
/*
|
||||
* For GET_POWER_STATE, SCP returns the power states of every cluster. The
|
||||
* size of response depends on the number of clusters in the system. The
|
||||
* SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is
|
||||
* large enough to contain power states of a given cluster
|
||||
*/
|
||||
#define CHECK_RESPONSE(_resp, _clus) (_resp.size >= (((_clus) + 1) * 2))
|
||||
|
||||
typedef enum {
|
||||
scpi_power_on = 0,
|
||||
scpi_power_retention = 1,
|
||||
scpi_power_off = 3,
|
||||
} scpi_power_state_t;
|
||||
|
||||
typedef enum {
|
||||
scpi_system_shutdown = 0,
|
||||
scpi_system_reboot = 1,
|
||||
scpi_system_reset = 2
|
||||
} scpi_system_state_t;
|
||||
|
||||
extern int scpi_wait_ready(void);
|
||||
extern void scpi_set_brcm_power_state(unsigned int mpidr,
|
||||
scpi_power_state_t cpu_state,
|
||||
scpi_power_state_t cluster_state,
|
||||
scpi_power_state_t css_state);
|
||||
int scpi_get_brcm_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
|
||||
unsigned int *cluster_state_p);
|
||||
uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
|
||||
|
||||
#endif /* BRCM_SCPI_H */
|
||||
Reference in New Issue
Block a user