summaryrefslogtreecommitdiffstats
path: root/plat/brcm/board/stingray/driver
diff options
context:
space:
mode:
Diffstat (limited to 'plat/brcm/board/stingray/driver')
-rw-r--r--plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h33
-rw-r--r--plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c302
-rw-r--r--plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h11
-rw-r--r--plat/brcm/board/stingray/driver/ihost_pll_config.c287
-rw-r--r--plat/brcm/board/stingray/driver/plat_emmc.c109
-rw-r--r--plat/brcm/board/stingray/driver/sr_usb.h135
-rw-r--r--plat/brcm/board/stingray/driver/swreg.c375
-rw-r--r--plat/brcm/board/stingray/driver/usb.c296
-rw-r--r--plat/brcm/board/stingray/driver/usb_phy.c601
9 files changed, 2149 insertions, 0 deletions
diff --git a/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h b/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h
new file mode 100644
index 0000000..b2427cf
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h
@@ -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
diff --git a/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c
new file mode 100644
index 0000000..74d2077
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c
@@ -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__);
+}
diff --git a/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h
new file mode 100644
index 0000000..8508653
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h
@@ -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
diff --git a/plat/brcm/board/stingray/driver/ihost_pll_config.c b/plat/brcm/board/stingray/driver/ihost_pll_config.c
new file mode 100644
index 0000000..1184928
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/ihost_pll_config.c
@@ -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;
+}
diff --git a/plat/brcm/board/stingray/driver/plat_emmc.c b/plat/brcm/board/stingray/driver/plat_emmc.c
new file mode 100644
index 0000000..82085e1
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/plat_emmc.c
@@ -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);
+}
diff --git a/plat/brcm/board/stingray/driver/sr_usb.h b/plat/brcm/board/stingray/driver/sr_usb.h
new file mode 100644
index 0000000..5033683
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/sr_usb.h
@@ -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 */
diff --git a/plat/brcm/board/stingray/driver/swreg.c b/plat/brcm/board/stingray/driver/swreg.c
new file mode 100644
index 0000000..2b7c53b
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/swreg.c
@@ -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;
+}
diff --git a/plat/brcm/board/stingray/driver/usb.c b/plat/brcm/board/stingray/driver/usb.c
new file mode 100644
index 0000000..4a84141
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/usb.c
@@ -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");
+}
diff --git a/plat/brcm/board/stingray/driver/usb_phy.c b/plat/brcm/board/stingray/driver/usb_phy.c
new file mode 100644
index 0000000..54c98e1
--- /dev/null
+++ b/plat/brcm/board/stingray/driver/usb_phy.c
@@ -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;
+}