diff options
Diffstat (limited to '')
-rw-r--r-- | plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h | 33 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c | 302 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h | 11 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/ihost_pll_config.c | 287 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/plat_emmc.c | 109 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/sr_usb.h | 135 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/swreg.c | 375 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/usb.c | 296 | ||||
-rw-r--r-- | plat/brcm/board/stingray/driver/usb_phy.c | 601 |
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; +} |