18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (c) 2018, Broadcom */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* 58c2ecf20Sopenharmony_ci * This module contains USB PHY initialization for power up and S3 resume 68c2ecf20Sopenharmony_ci * for newer Synopsys based USB hardware first used on the bcm7216. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/delay.h> 108c2ecf20Sopenharmony_ci#include <linux/io.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/soc/brcmstb/brcmstb.h> 138c2ecf20Sopenharmony_ci#include "phy-brcm-usb-init.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define PHY_LOCK_TIMEOUT_MS 200 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Register definitions for syscon piarbctl registers */ 188c2ecf20Sopenharmony_ci#define PIARBCTL_CAM 0x00 198c2ecf20Sopenharmony_ci#define PIARBCTL_SPLITTER 0x04 208c2ecf20Sopenharmony_ci#define PIARBCTL_MISC 0x08 218c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_SECURE_MASK 0x80000000 228c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_USB_SELECT_MASK 0x40000000 238c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_USB_4G_SDRAM_MASK 0x20000000 248c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_USB_PRIORITY_MASK 0x000f0000 258c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_USB_MEM_PAGE_MASK 0x0000f000 268c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_CAM1_MEM_PAGE_MASK 0x00000f00 278c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_CAM0_MEM_PAGE_MASK 0x000000f0 288c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_SATA_PRIORITY_MASK 0x0000000f 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define PIARBCTL_MISC_USB_ONLY_MASK \ 318c2ecf20Sopenharmony_ci (PIARBCTL_MISC_USB_SELECT_MASK | \ 328c2ecf20Sopenharmony_ci PIARBCTL_MISC_USB_4G_SDRAM_MASK | \ 338c2ecf20Sopenharmony_ci PIARBCTL_MISC_USB_PRIORITY_MASK | \ 348c2ecf20Sopenharmony_ci PIARBCTL_MISC_USB_MEM_PAGE_MASK) 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* Register definitions for the USB CTRL block */ 378c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP 0x00 388c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK 0x02000000 398c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_SCB2_EN_MASK 0x00008000 408c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_tca_drv_sel_MASK 0x01000000 418c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_SCB1_EN_MASK 0x00004000 428c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK 0x00000200 438c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_IPP_MASK 0x00000020 448c2ecf20Sopenharmony_ci#define USB_CTRL_SETUP_IOC_MASK 0x00000010 458c2ecf20Sopenharmony_ci#define USB_CTRL_USB_PM 0x04 468c2ecf20Sopenharmony_ci#define USB_CTRL_USB_PM_USB_PWRDN_MASK 0x80000000 478c2ecf20Sopenharmony_ci#define USB_CTRL_USB_PM_SOFT_RESET_MASK 0x40000000 488c2ecf20Sopenharmony_ci#define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK 0x00800000 498c2ecf20Sopenharmony_ci#define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK 0x00400000 508c2ecf20Sopenharmony_ci#define USB_CTRL_USB_PM_STATUS 0x08 518c2ecf20Sopenharmony_ci#define USB_CTRL_USB_DEVICE_CTL1 0x10 528c2ecf20Sopenharmony_ci#define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003 538c2ecf20Sopenharmony_ci#define USB_CTRL_TEST_PORT_CTL 0x30 548c2ecf20Sopenharmony_ci#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK 0x000000ff 558c2ecf20Sopenharmony_ci#define USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_PME_GEN_MASK 0x0000002e 568c2ecf20Sopenharmony_ci#define USB_CTRL_TP_DIAG1 0x34 578c2ecf20Sopenharmony_ci#define USB_CTLR_TP_DIAG1_wake_MASK 0x00000002 588c2ecf20Sopenharmony_ci#define USB_CTRL_CTLR_CSHCR 0x50 598c2ecf20Sopenharmony_ci#define USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK 0x00040000 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* Register definitions for the USB_PHY block in 7211b0 */ 628c2ecf20Sopenharmony_ci#define USB_PHY_PLL_CTL 0x00 638c2ecf20Sopenharmony_ci#define USB_PHY_PLL_CTL_PLL_RESETB_MASK 0x40000000 648c2ecf20Sopenharmony_ci#define USB_PHY_PLL_LDO_CTL 0x08 658c2ecf20Sopenharmony_ci#define USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK 0x00000004 668c2ecf20Sopenharmony_ci#define USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK 0x00000002 678c2ecf20Sopenharmony_ci#define USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK 0x00000001 688c2ecf20Sopenharmony_ci#define USB_PHY_UTMI_CTL_1 0x04 698c2ecf20Sopenharmony_ci#define USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800 708c2ecf20Sopenharmony_ci#define USB_PHY_UTMI_CTL_1_PHY_MODE_MASK 0x0000000c 718c2ecf20Sopenharmony_ci#define USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT 2 728c2ecf20Sopenharmony_ci#define USB_PHY_IDDQ 0x1c 738c2ecf20Sopenharmony_ci#define USB_PHY_IDDQ_phy_iddq_MASK 0x00000001 748c2ecf20Sopenharmony_ci#define USB_PHY_STATUS 0x20 758c2ecf20Sopenharmony_ci#define USB_PHY_STATUS_pll_lock_MASK 0x00000001 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* Register definitions for the MDIO registers in the DWC2 block of 788c2ecf20Sopenharmony_ci * the 7211b0. 798c2ecf20Sopenharmony_ci * NOTE: The PHY's MDIO registers are only accessible through the 808c2ecf20Sopenharmony_ci * legacy DesignWare USB controller even though it's not being used. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci#define USB_GMDIOCSR 0 838c2ecf20Sopenharmony_ci#define USB_GMDIOGEN 4 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* Register definitions for the BDC EC block in 7211b0 */ 868c2ecf20Sopenharmony_ci#define BDC_EC_AXIRDA 0x0c 878c2ecf20Sopenharmony_ci#define BDC_EC_AXIRDA_RTS_MASK 0xf0000000 888c2ecf20Sopenharmony_ci#define BDC_EC_AXIRDA_RTS_SHIFT 28 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic void usb_mdio_write_7211b0(struct brcm_usb_init_params *params, 928c2ecf20Sopenharmony_ci uint8_t addr, uint16_t data) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO]; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci addr &= 0x1f; /* 5-bit address */ 978c2ecf20Sopenharmony_ci brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN); 988c2ecf20Sopenharmony_ci while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) 998c2ecf20Sopenharmony_ci ; 1008c2ecf20Sopenharmony_ci brcm_usb_writel(0x59020000 | (addr << 18) | data, 1018c2ecf20Sopenharmony_ci usb_mdio + USB_GMDIOGEN); 1028c2ecf20Sopenharmony_ci while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) 1038c2ecf20Sopenharmony_ci ; 1048c2ecf20Sopenharmony_ci brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN); 1058c2ecf20Sopenharmony_ci while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) 1068c2ecf20Sopenharmony_ci ; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic uint16_t __maybe_unused usb_mdio_read_7211b0( 1108c2ecf20Sopenharmony_ci struct brcm_usb_init_params *params, uint8_t addr) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO]; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci addr &= 0x1f; /* 5-bit address */ 1158c2ecf20Sopenharmony_ci brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN); 1168c2ecf20Sopenharmony_ci while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) 1178c2ecf20Sopenharmony_ci ; 1188c2ecf20Sopenharmony_ci brcm_usb_writel(0x69020000 | (addr << 18), usb_mdio + USB_GMDIOGEN); 1198c2ecf20Sopenharmony_ci while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) 1208c2ecf20Sopenharmony_ci ; 1218c2ecf20Sopenharmony_ci brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN); 1228c2ecf20Sopenharmony_ci while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31)) 1238c2ecf20Sopenharmony_ci ; 1248c2ecf20Sopenharmony_ci return brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & 0xffff; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic void usb2_eye_fix_7211b0(struct brcm_usb_init_params *params) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci /* select bank */ 1308c2ecf20Sopenharmony_ci usb_mdio_write_7211b0(params, 0x1f, 0x80a0); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* Set the eye */ 1338c2ecf20Sopenharmony_ci usb_mdio_write_7211b0(params, 0x0a, 0xc6a0); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic void xhci_soft_reset(struct brcm_usb_init_params *params, 1378c2ecf20Sopenharmony_ci int on_off) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Assert reset */ 1428c2ecf20Sopenharmony_ci if (on_off) 1438c2ecf20Sopenharmony_ci USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB); 1448c2ecf20Sopenharmony_ci /* De-assert reset */ 1458c2ecf20Sopenharmony_ci else 1468c2ecf20Sopenharmony_ci USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void usb_init_ipp(struct brcm_usb_init_params *params) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 1528c2ecf20Sopenharmony_ci u32 reg; 1538c2ecf20Sopenharmony_ci u32 orig_reg; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci orig_reg = reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP)); 1588c2ecf20Sopenharmony_ci if (params->ipp != 2) 1598c2ecf20Sopenharmony_ci /* override ipp strap pin (if it exits) */ 1608c2ecf20Sopenharmony_ci reg &= ~(USB_CTRL_MASK(SETUP, STRAP_IPP_SEL)); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* Override the default OC and PP polarity */ 1638c2ecf20Sopenharmony_ci reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC)); 1648c2ecf20Sopenharmony_ci if (params->ioc) 1658c2ecf20Sopenharmony_ci reg |= USB_CTRL_MASK(SETUP, IOC); 1668c2ecf20Sopenharmony_ci if (params->ipp == 1) 1678c2ecf20Sopenharmony_ci reg |= USB_CTRL_MASK(SETUP, IPP); 1688c2ecf20Sopenharmony_ci brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP)); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* 1718c2ecf20Sopenharmony_ci * If we're changing IPP, make sure power is off long enough 1728c2ecf20Sopenharmony_ci * to turn off any connected devices. 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ci if ((reg ^ orig_reg) & USB_CTRL_MASK(SETUP, IPP)) 1758c2ecf20Sopenharmony_ci msleep(50); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic void syscon_piarbctl_init(struct regmap *rmap) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci /* Switch from legacy USB OTG controller to new STB USB controller */ 1818c2ecf20Sopenharmony_ci regmap_update_bits(rmap, PIARBCTL_MISC, PIARBCTL_MISC_USB_ONLY_MASK, 1828c2ecf20Sopenharmony_ci PIARBCTL_MISC_USB_SELECT_MASK | 1838c2ecf20Sopenharmony_ci PIARBCTL_MISC_USB_4G_SDRAM_MASK); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic void usb_init_common(struct brcm_usb_init_params *params) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci u32 reg; 1898c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN); 1948c2ecf20Sopenharmony_ci /* 1 millisecond - for USB clocks to settle down */ 1958c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) { 1988c2ecf20Sopenharmony_ci reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1)); 1998c2ecf20Sopenharmony_ci reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE); 2008c2ecf20Sopenharmony_ci reg |= params->mode; 2018c2ecf20Sopenharmony_ci brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1)); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci switch (params->mode) { 2048c2ecf20Sopenharmony_ci case USB_CTLR_MODE_HOST: 2058c2ecf20Sopenharmony_ci USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB); 2068c2ecf20Sopenharmony_ci break; 2078c2ecf20Sopenharmony_ci default: 2088c2ecf20Sopenharmony_ci USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB); 2098c2ecf20Sopenharmony_ci USB_CTRL_SET(ctrl, USB_PM, BDC_SOFT_RESETB); 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic void usb_wake_enable_7211b0(struct brcm_usb_init_params *params, 2158c2ecf20Sopenharmony_ci bool enable) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (enable) 2208c2ecf20Sopenharmony_ci USB_CTRL_SET(ctrl, CTLR_CSHCR, ctl_pme_en); 2218c2ecf20Sopenharmony_ci else 2228c2ecf20Sopenharmony_ci USB_CTRL_UNSET(ctrl, CTLR_CSHCR, ctl_pme_en); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic void usb_init_common_7211b0(struct brcm_usb_init_params *params) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 2288c2ecf20Sopenharmony_ci void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY]; 2298c2ecf20Sopenharmony_ci void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC]; 2308c2ecf20Sopenharmony_ci int timeout_ms = PHY_LOCK_TIMEOUT_MS; 2318c2ecf20Sopenharmony_ci u32 reg; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (params->syscon_piarbctl) 2348c2ecf20Sopenharmony_ci syscon_piarbctl_init(params->syscon_piarbctl); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci usb_wake_enable_7211b0(params, false); 2398c2ecf20Sopenharmony_ci if (!params->wake_enabled) { 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* undo possible suspend settings */ 2428c2ecf20Sopenharmony_ci brcm_usb_writel(0, usb_phy + USB_PHY_IDDQ); 2438c2ecf20Sopenharmony_ci reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL); 2448c2ecf20Sopenharmony_ci reg |= USB_PHY_PLL_CTL_PLL_RESETB_MASK; 2458c2ecf20Sopenharmony_ci brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* temporarily enable FSM so PHY comes up properly */ 2488c2ecf20Sopenharmony_ci reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1); 2498c2ecf20Sopenharmony_ci reg |= USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK; 2508c2ecf20Sopenharmony_ci brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1); 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Init the PHY */ 2548c2ecf20Sopenharmony_ci reg = USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK | 2558c2ecf20Sopenharmony_ci USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK | 2568c2ecf20Sopenharmony_ci USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK; 2578c2ecf20Sopenharmony_ci brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* wait for lock */ 2608c2ecf20Sopenharmony_ci while (timeout_ms-- > 0) { 2618c2ecf20Sopenharmony_ci reg = brcm_usb_readl(usb_phy + USB_PHY_STATUS); 2628c2ecf20Sopenharmony_ci if (reg & USB_PHY_STATUS_pll_lock_MASK) 2638c2ecf20Sopenharmony_ci break; 2648c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* Set the PHY_MODE */ 2688c2ecf20Sopenharmony_ci reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1); 2698c2ecf20Sopenharmony_ci reg &= ~USB_PHY_UTMI_CTL_1_PHY_MODE_MASK; 2708c2ecf20Sopenharmony_ci reg |= params->mode << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT; 2718c2ecf20Sopenharmony_ci brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci usb_init_common(params); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* 2768c2ecf20Sopenharmony_ci * The BDC controller will get occasional failures with 2778c2ecf20Sopenharmony_ci * the default "Read Transaction Size" of 6 (1024 bytes). 2788c2ecf20Sopenharmony_ci * Set it to 4 (256 bytes). 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_ci if ((params->mode != USB_CTLR_MODE_HOST) && bdc_ec) { 2818c2ecf20Sopenharmony_ci reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA); 2828c2ecf20Sopenharmony_ci reg &= ~BDC_EC_AXIRDA_RTS_MASK; 2838c2ecf20Sopenharmony_ci reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT); 2848c2ecf20Sopenharmony_ci brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA); 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* 2888c2ecf20Sopenharmony_ci * Disable FSM, otherwise the PHY will auto suspend when no 2898c2ecf20Sopenharmony_ci * device is connected and will be reset on resume. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ci reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1); 2928c2ecf20Sopenharmony_ci reg &= ~USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK; 2938c2ecf20Sopenharmony_ci brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci usb2_eye_fix_7211b0(params); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic void usb_init_xhci(struct brcm_usb_init_params *params) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci xhci_soft_reset(params, 0); 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic void usb_uninit_common(struct brcm_usb_init_params *params) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci} 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cistatic void usb_uninit_common_7211b0(struct brcm_usb_init_params *params) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 3188c2ecf20Sopenharmony_ci void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY]; 3198c2ecf20Sopenharmony_ci u32 reg; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (params->wake_enabled) { 3248c2ecf20Sopenharmony_ci USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN); 3258c2ecf20Sopenharmony_ci usb_wake_enable_7211b0(params, true); 3268c2ecf20Sopenharmony_ci } else { 3278c2ecf20Sopenharmony_ci USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN); 3288c2ecf20Sopenharmony_ci brcm_usb_writel(0, usb_phy + USB_PHY_PLL_LDO_CTL); 3298c2ecf20Sopenharmony_ci reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL); 3308c2ecf20Sopenharmony_ci reg &= ~USB_PHY_PLL_CTL_PLL_RESETB_MASK; 3318c2ecf20Sopenharmony_ci brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL); 3328c2ecf20Sopenharmony_ci brcm_usb_writel(USB_PHY_IDDQ_phy_iddq_MASK, 3338c2ecf20Sopenharmony_ci usb_phy + USB_PHY_IDDQ); 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic void usb_uninit_xhci(struct brcm_usb_init_params *params) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (!params->wake_enabled) 3448c2ecf20Sopenharmony_ci xhci_soft_reset(params, 1); 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic int usb_get_dual_select(struct brcm_usb_init_params *params) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 3508c2ecf20Sopenharmony_ci u32 reg = 0; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1)); 3558c2ecf20Sopenharmony_ci reg &= USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE); 3568c2ecf20Sopenharmony_ci return reg; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic void usb_set_dual_select(struct brcm_usb_init_params *params, int mode) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci void __iomem *ctrl = params->regs[BRCM_REGS_CTRL]; 3628c2ecf20Sopenharmony_ci u32 reg; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1)); 3678c2ecf20Sopenharmony_ci reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE); 3688c2ecf20Sopenharmony_ci reg |= mode; 3698c2ecf20Sopenharmony_ci brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1)); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic const struct brcm_usb_init_ops bcm7216_ops = { 3738c2ecf20Sopenharmony_ci .init_ipp = usb_init_ipp, 3748c2ecf20Sopenharmony_ci .init_common = usb_init_common, 3758c2ecf20Sopenharmony_ci .init_xhci = usb_init_xhci, 3768c2ecf20Sopenharmony_ci .uninit_common = usb_uninit_common, 3778c2ecf20Sopenharmony_ci .uninit_xhci = usb_uninit_xhci, 3788c2ecf20Sopenharmony_ci .get_dual_select = usb_get_dual_select, 3798c2ecf20Sopenharmony_ci .set_dual_select = usb_set_dual_select, 3808c2ecf20Sopenharmony_ci}; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic const struct brcm_usb_init_ops bcm7211b0_ops = { 3838c2ecf20Sopenharmony_ci .init_ipp = usb_init_ipp, 3848c2ecf20Sopenharmony_ci .init_common = usb_init_common_7211b0, 3858c2ecf20Sopenharmony_ci .init_xhci = usb_init_xhci, 3868c2ecf20Sopenharmony_ci .uninit_common = usb_uninit_common_7211b0, 3878c2ecf20Sopenharmony_ci .uninit_xhci = usb_uninit_xhci, 3888c2ecf20Sopenharmony_ci .get_dual_select = usb_get_dual_select, 3898c2ecf20Sopenharmony_ci .set_dual_select = usb_set_dual_select, 3908c2ecf20Sopenharmony_ci}; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_civoid brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci params->family_name = "7216"; 3988c2ecf20Sopenharmony_ci params->ops = &bcm7216_ops; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_civoid brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci pr_debug("%s\n", __func__); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci params->family_name = "7211"; 4078c2ecf20Sopenharmony_ci params->ops = &bcm7211b0_ops; 4088c2ecf20Sopenharmony_ci params->suspend_with_clocks = true; 4098c2ecf20Sopenharmony_ci} 410