Commit f29d1e0c authored by Sheetal Tigadoli's avatar Sheetal Tigadoli
Browse files

Add BL2 support for Broadcom stingray platform



Change-Id: I5daa3f2b4b9d85cb857547a588571a9aa8ad05c2
Signed-off-by: default avatarSheetal Tigadoli <sheetal.tigadoli@broadcom.com>
parent 9a40c0fb
/*
* 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;
}
/*
* 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 */
...@@ -14,3 +14,9 @@ include plat/brcm/board/stingray/bcm958742t.mk ...@@ -14,3 +14,9 @@ include plat/brcm/board/stingray/bcm958742t.mk
ifneq (${BL33_OVERRIDE_LOAD_ADDR},) ifneq (${BL33_OVERRIDE_LOAD_ADDR},)
$(eval $(call add_define_val,BL33_OVERRIDE_LOAD_ADDR,0xFF000000)) $(eval $(call add_define_val,BL33_OVERRIDE_LOAD_ADDR,0xFF000000))
endif 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
/*
* 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
/*
* 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__);
}
/*
* 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
/*
* 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;
}
/*
* 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
/*
* 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
...@@ -12,10 +12,8 @@ ...@@ -12,10 +12,8 @@
#include <plat/common/common_def.h> #include <plat/common/common_def.h>
#include <brcm_def.h> #include <brcm_def.h>
#include <cmn_plat_def.h>
#include "sr_def.h" #include "sr_def.h"
#include <cmn_plat_def.h>
/* /*
* Most platform porting definitions provided by included headers * Most platform porting definitions provided by included headers
......
/*
* 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
/*
* 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
/*
* 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
/*
* 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
/*
* 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
...@@ -4,6 +4,19 @@ ...@@ -4,6 +4,19 @@
# SPDX-License-Identifier: BSD-3-Clause # 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 # Enable workaround for ERRATA_A72_859971
ERRATA_A72_859971 := 1 ERRATA_A72_859971 := 1
...@@ -16,16 +29,42 @@ ARM_BL31_IN_DRAM := 1 ...@@ -16,16 +29,42 @@ ARM_BL31_IN_DRAM := 1
USE_CRMU_SRAM := yes USE_CRMU_SRAM := 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 # Use single cluster
ifeq (${USE_SINGLE_CLUSTER},yes) ifeq (${USE_SINGLE_CLUSTER},yes)
$(info Using Single Cluster) $(info Using Single Cluster)
$(eval $(call add_define,USE_SINGLE_CLUSTER)) $(eval $(call add_define,USE_SINGLE_CLUSTER))
endif endif
# Use DDR
ifeq (${USE_DDR},yes)
$(info Using DDR)
$(eval $(call add_define,USE_DDR))
endif
ifeq (${BOARD_CFG},) ifeq (${BOARD_CFG},)
BOARD_CFG := bcm958742k BOARD_CFG := bcm958742k
endif 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 # BL31 build for standalone mode
ifeq (${STANDALONE_BL31},yes) ifeq (${STANDALONE_BL31},yes)
RESET_TO_BL31 := 1 RESET_TO_BL31 := 1
...@@ -43,6 +82,9 @@ endif ...@@ -43,6 +82,9 @@ endif
# Default soft reset is L3 # Default soft reset is L3
$(eval $(call add_define,CONFIG_SOFT_RESET_L3)) $(eval $(call add_define,CONFIG_SOFT_RESET_L3))
# Enable Chip OTP driver
DRIVER_OCOTP_ENABLE := 1
include plat/brcm/board/common/board_common.mk include plat/brcm/board/common/board_common.mk
SOC_DIR := brcm/board/stingray SOC_DIR := brcm/board/stingray
...@@ -58,6 +100,17 @@ PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \ ...@@ -58,6 +100,17 @@ PLAT_BL_COMMON_SOURCES += lib/cpus/aarch64/cortex_a72.S \
drivers/arm/tzc/tzc400.c \ drivers/arm/tzc/tzc400.c \
plat/${SOC_DIR}/src/topology.c plat/${SOC_DIR}/src/topology.c
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 GICv3 driver files
include drivers/arm/gic/v3/gicv3.mk include drivers/arm/gic/v3/gicv3.mk
...@@ -77,6 +130,12 @@ BL31_SOURCES += \ ...@@ -77,6 +130,12 @@ BL31_SOURCES += \
ifdef SCP_BL2 ifdef SCP_BL2
PLAT_INCLUDES += -Iplat/brcm/common/ 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 \ BL31_SOURCES += plat/brcm/common/brcm_mhu.c \
plat/brcm/common/brcm_scpi.c \ plat/brcm/common/brcm_scpi.c \
plat/${SOC_DIR}/src/brcm_pm_ops.c plat/${SOC_DIR}/src/brcm_pm_ops.c
...@@ -85,5 +144,19 @@ BL31_SOURCES += plat/${SOC_DIR}/src/ihost_pm.c \ ...@@ -85,5 +144,19 @@ BL31_SOURCES += plat/${SOC_DIR}/src/ihost_pm.c \
plat/${SOC_DIR}/src/pm.c plat/${SOC_DIR}/src/pm.c
endif endif
ifeq (${ELOG_SUPPORT},1)
ifeq (${ELOG_STORE_MEDIA},DDR)
BL2_SOURCES += plat/brcm/board/common/bcm_elog_ddr.c
endif
endif
# Do not execute the startup code on warm reset. # Do not execute the startup code on warm reset.
PROGRAMMABLE_RESET_ADDRESS := 1 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
This diff is collapsed.
/*
* 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;
}
/*
* 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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment