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

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,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
@@ -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__);
}
@@ -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
@@ -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;
}
@@ -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);
}
@@ -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 */
@@ -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");
}
@@ -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;
}