1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019 - 2021, Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <platform_usb.h> 8*91f16700Schasinglulu #include <usb_phy.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #define USB_PHY_ALREADY_STARTED (-2) 11*91f16700Schasinglulu #define USB_MAX_DEVICES 2 12*91f16700Schasinglulu #define USB3H_USB2DRD_PHY 0 13*91f16700Schasinglulu #define USB3_DRD_PHY 1 14*91f16700Schasinglulu 15*91f16700Schasinglulu /* Common bit fields for all the USB2 phy */ 16*91f16700Schasinglulu #define USB2_PHY_ISO DRDU2_U2PHY_ISO 17*91f16700Schasinglulu #define USB2_AFE_PLL_PWRDWNB DRDU2_U2AFE_PLL_PWRDWNB 18*91f16700Schasinglulu #define USB2_AFE_BG_PWRDWNB DRDU2_U2AFE_BG_PWRDWNB 19*91f16700Schasinglulu #define USB2_AFE_LDO_PWRDWNB DRDU2_U2AFE_LDO_PWRDWNB 20*91f16700Schasinglulu #define USB2_CTRL_CORERDY DRDU2_U2CTRL_CORERDY 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define USB2_PHY_PCTL_MASK DRDU2_U2PHY_PCTL_MASK 23*91f16700Schasinglulu #define USB2_PHY_PCTL_OFFSET DRDU2_U2PHY_PCTL_OFFSET 24*91f16700Schasinglulu #define USB2_PHY_PCTL_VAL U2PHY_PCTL_VAL 25*91f16700Schasinglulu 26*91f16700Schasinglulu #define USB2_PLL_RESETB DRDU2_U2PLL_RESETB 27*91f16700Schasinglulu #define USB2_PHY_RESETB DRDU2_U2PHY_RESETB 28*91f16700Schasinglulu 29*91f16700Schasinglulu static usb_phy_port_t usb_phy_port[2U][MAX_NR_PORTS]; 30*91f16700Schasinglulu 31*91f16700Schasinglulu static usb_phy_t usb_phy_info[2U] = { 32*91f16700Schasinglulu {DRDU2_U2PLL_NDIV_FRAC, USB3H_PIPE_CTRL, 0U, USB3H_DRDU2_PHY}, 33*91f16700Schasinglulu {0U, 0U, DRDU3_PIPE_CTRL, DRDU3_PHY} 34*91f16700Schasinglulu }; 35*91f16700Schasinglulu 36*91f16700Schasinglulu typedef struct { 37*91f16700Schasinglulu void *pcd_id; 38*91f16700Schasinglulu } usb_platform_dev; 39*91f16700Schasinglulu 40*91f16700Schasinglulu /* index 0: USB3H + USB2 DRD, 1: USB3 DRD */ 41*91f16700Schasinglulu static usb_platform_dev xhci_devices_configs[USB_MAX_DEVICES] = { 42*91f16700Schasinglulu {&usb_phy_info[0U]}, 43*91f16700Schasinglulu {&usb_phy_info[1U]} 44*91f16700Schasinglulu }; 45*91f16700Schasinglulu 46*91f16700Schasinglulu static int32_t pll_lock_check(uint32_t address, uint32_t bit) 47*91f16700Schasinglulu { 48*91f16700Schasinglulu uint32_t retry; 49*91f16700Schasinglulu uint32_t data; 50*91f16700Schasinglulu 51*91f16700Schasinglulu retry = PLL_LOCK_RETRY_COUNT; 52*91f16700Schasinglulu do { 53*91f16700Schasinglulu data = mmio_read_32(address); 54*91f16700Schasinglulu if ((data & bit) != 0U) { 55*91f16700Schasinglulu return 0; 56*91f16700Schasinglulu } 57*91f16700Schasinglulu udelay(1); 58*91f16700Schasinglulu } while (--retry != 0); 59*91f16700Schasinglulu 60*91f16700Schasinglulu ERROR("%s(): FAIL (0x%08x)\n", __func__, address); 61*91f16700Schasinglulu return -1; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu /* 65*91f16700Schasinglulu * USB2 PHY using external FSM bringup sequence 66*91f16700Schasinglulu * Total #3 USB2 phys. All phys has the same 67*91f16700Schasinglulu * bringup sequence. Register bit fields for 68*91f16700Schasinglulu * some of the PHY's are different. 69*91f16700Schasinglulu * Bit fields which are different are passed using 70*91f16700Schasinglulu * struct u2_phy_ext_fsm with bit-fields and register addr. 71*91f16700Schasinglulu */ 72*91f16700Schasinglulu 73*91f16700Schasinglulu static void u2_phy_ext_fsm_power_on(struct u2_phy_ext_fsm *u2_phy) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO); 76*91f16700Schasinglulu /* Delay as per external FSM spec */ 77*91f16700Schasinglulu udelay(10U); 78*91f16700Schasinglulu 79*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq); 80*91f16700Schasinglulu /* Delay as per external FSM spec */ 81*91f16700Schasinglulu udelay(10U); 82*91f16700Schasinglulu 83*91f16700Schasinglulu mmio_clrbits_32(u2_phy->phy_ctrl_reg, 84*91f16700Schasinglulu (USB2_AFE_BG_PWRDWNB | 85*91f16700Schasinglulu USB2_AFE_PLL_PWRDWNB | 86*91f16700Schasinglulu USB2_AFE_LDO_PWRDWNB | 87*91f16700Schasinglulu USB2_CTRL_CORERDY)); 88*91f16700Schasinglulu 89*91f16700Schasinglulu mmio_clrsetbits_32(u2_phy->phy_ctrl_reg, 90*91f16700Schasinglulu (USB2_PHY_PCTL_MASK << USB2_PHY_PCTL_OFFSET), 91*91f16700Schasinglulu (USB2_PHY_PCTL_VAL << USB2_PHY_PCTL_OFFSET)); 92*91f16700Schasinglulu /* Delay as per external FSM spec */ 93*91f16700Schasinglulu udelay(160U); 94*91f16700Schasinglulu 95*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_CTRL_CORERDY); 96*91f16700Schasinglulu /* Delay as per external FSM spec */ 97*91f16700Schasinglulu udelay(50U); 98*91f16700Schasinglulu 99*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_BG_PWRDWNB); 100*91f16700Schasinglulu /* Delay as per external FSM spec */ 101*91f16700Schasinglulu udelay(200U); 102*91f16700Schasinglulu 103*91f16700Schasinglulu mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_onin); 104*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_LDO_PWRDWNB); 105*91f16700Schasinglulu /* Delay as per external FSM spec */ 106*91f16700Schasinglulu udelay(10U); 107*91f16700Schasinglulu 108*91f16700Schasinglulu mmio_setbits_32(u2_phy->pwr_ctrl_reg, u2_phy->pwr_okin); 109*91f16700Schasinglulu /* Delay as per external FSM spec */ 110*91f16700Schasinglulu udelay(10U); 111*91f16700Schasinglulu 112*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_AFE_PLL_PWRDWNB); 113*91f16700Schasinglulu /* Delay as per external FSM spec */ 114*91f16700Schasinglulu udelay(10U); 115*91f16700Schasinglulu 116*91f16700Schasinglulu mmio_clrbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_ISO); 117*91f16700Schasinglulu /* Delay as per external FSM spec */ 118*91f16700Schasinglulu udelay(10U); 119*91f16700Schasinglulu mmio_clrbits_32(u2_phy->phy_ctrl_reg, u2_phy->phy_iddq); 120*91f16700Schasinglulu /* Delay as per external FSM spec */ 121*91f16700Schasinglulu udelay(1U); 122*91f16700Schasinglulu 123*91f16700Schasinglulu mmio_setbits_32(u2_phy->pll_ctrl_reg, USB2_PLL_RESETB); 124*91f16700Schasinglulu mmio_setbits_32(u2_phy->phy_ctrl_reg, USB2_PHY_RESETB); 125*91f16700Schasinglulu 126*91f16700Schasinglulu } 127*91f16700Schasinglulu 128*91f16700Schasinglulu static int32_t usb3h_u2_phy_power_on(uint32_t base) 129*91f16700Schasinglulu { 130*91f16700Schasinglulu int32_t status; 131*91f16700Schasinglulu struct u2_phy_ext_fsm u2_phy; 132*91f16700Schasinglulu 133*91f16700Schasinglulu u2_phy.pll_ctrl_reg = base + USB3H_U2PLL_CTRL; 134*91f16700Schasinglulu u2_phy.phy_ctrl_reg = base + USB3H_U2PHY_CTRL; 135*91f16700Schasinglulu u2_phy.phy_iddq = USB3H_U2PHY_IDDQ; 136*91f16700Schasinglulu u2_phy.pwr_ctrl_reg = base + USB3H_PWR_CTRL; 137*91f16700Schasinglulu u2_phy.pwr_okin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN; 138*91f16700Schasinglulu u2_phy.pwr_onin = USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN; 139*91f16700Schasinglulu 140*91f16700Schasinglulu u2_phy_ext_fsm_power_on(&u2_phy); 141*91f16700Schasinglulu 142*91f16700Schasinglulu status = pll_lock_check(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_LOCK); 143*91f16700Schasinglulu if (status != 0) { 144*91f16700Schasinglulu /* re-try by toggling the PLL reset */ 145*91f16700Schasinglulu mmio_clrbits_32(base + USB3H_U2PLL_CTRL, 146*91f16700Schasinglulu (uint32_t)USB3H_U2PLL_RESETB); 147*91f16700Schasinglulu mmio_setbits_32(base + USB3H_U2PLL_CTRL, USB3H_U2PLL_RESETB); 148*91f16700Schasinglulu status = pll_lock_check(base + USB3H_U2PLL_CTRL, 149*91f16700Schasinglulu USB3H_U2PLL_LOCK); 150*91f16700Schasinglulu if (status != 0) 151*91f16700Schasinglulu ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__, 152*91f16700Schasinglulu base + USB3H_U2PLL_CTRL); 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu mmio_clrsetbits_32(base + USB3H_U2PHY_CTRL, 156*91f16700Schasinglulu (USB3H_U2PHY_PCTL_MASK << USB3H_U2PHY_PCTL_OFFSET), 157*91f16700Schasinglulu (U2PHY_PCTL_NON_DRV_LOW << USB3H_U2PHY_PCTL_OFFSET)); 158*91f16700Schasinglulu return status; 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu static int32_t usb3h_u3_phy_power_on(uint32_t base) 162*91f16700Schasinglulu { 163*91f16700Schasinglulu int32_t status; 164*91f16700Schasinglulu 165*91f16700Schasinglulu /* Set pctl with mode and soft reset */ 166*91f16700Schasinglulu mmio_clrsetbits_32(base + USB3H_U3PHY_CTRL, 167*91f16700Schasinglulu (USB3H_U3PHY_PCTL_MASK << USB3H_U3PHY_PCTL_OFFSET), 168*91f16700Schasinglulu (U3PHY_PCTL_VAL << USB3H_U3PHY_PCTL_OFFSET)); 169*91f16700Schasinglulu 170*91f16700Schasinglulu mmio_clrbits_32(base + USB3H_U3PHY_PLL_CTRL, 171*91f16700Schasinglulu (uint32_t) USB3H_U3SSPLL_SUSPEND_EN); 172*91f16700Schasinglulu mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_SEQ_START); 173*91f16700Schasinglulu mmio_setbits_32(base + USB3H_U3PHY_PLL_CTRL, USB3H_U3PLL_RESETB); 174*91f16700Schasinglulu 175*91f16700Schasinglulu /* Time to stabilize the PLL Control */ 176*91f16700Schasinglulu mdelay(1U); 177*91f16700Schasinglulu 178*91f16700Schasinglulu status = pll_lock_check(base + USB3H_U3PHY_PLL_CTRL, 179*91f16700Schasinglulu USB3H_U3PLL_SS_LOCK); 180*91f16700Schasinglulu 181*91f16700Schasinglulu return status; 182*91f16700Schasinglulu } 183*91f16700Schasinglulu 184*91f16700Schasinglulu static int32_t drdu3_u2_phy_power_on(uint32_t base) 185*91f16700Schasinglulu { 186*91f16700Schasinglulu int32_t status; 187*91f16700Schasinglulu struct u2_phy_ext_fsm u2_phy; 188*91f16700Schasinglulu 189*91f16700Schasinglulu u2_phy.pll_ctrl_reg = base + DRDU3_U2PLL_CTRL; 190*91f16700Schasinglulu u2_phy.phy_ctrl_reg = base + DRDU3_U2PHY_CTRL; 191*91f16700Schasinglulu u2_phy.phy_iddq = DRDU3_U2PHY_IDDQ; 192*91f16700Schasinglulu u2_phy.pwr_ctrl_reg = base + DRDU3_PWR_CTRL; 193*91f16700Schasinglulu u2_phy.pwr_okin = DRDU3_U2PHY_DFE_SWITCH_PWROKIN; 194*91f16700Schasinglulu u2_phy.pwr_onin = DRDU3_U2PHY_DFE_SWITCH_PWRONIN; 195*91f16700Schasinglulu 196*91f16700Schasinglulu u2_phy_ext_fsm_power_on(&u2_phy); 197*91f16700Schasinglulu 198*91f16700Schasinglulu status = pll_lock_check(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_LOCK); 199*91f16700Schasinglulu if (status != 0) { 200*91f16700Schasinglulu /* re-try by toggling the PLL reset */ 201*91f16700Schasinglulu mmio_clrbits_32(base + DRDU3_U2PLL_CTRL, 202*91f16700Schasinglulu (uint32_t)DRDU2_U2PLL_RESETB); 203*91f16700Schasinglulu mmio_setbits_32(base + DRDU3_U2PLL_CTRL, DRDU3_U2PLL_RESETB); 204*91f16700Schasinglulu 205*91f16700Schasinglulu status = pll_lock_check(base + DRDU3_U2PLL_CTRL, 206*91f16700Schasinglulu DRDU3_U2PLL_LOCK); 207*91f16700Schasinglulu if (status != 0) { 208*91f16700Schasinglulu ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__, 209*91f16700Schasinglulu base + DRDU3_U2PLL_CTRL); 210*91f16700Schasinglulu } 211*91f16700Schasinglulu } 212*91f16700Schasinglulu mmio_clrsetbits_32(base + DRDU3_U2PHY_CTRL, 213*91f16700Schasinglulu (DRDU3_U2PHY_PCTL_MASK << DRDU3_U2PHY_PCTL_OFFSET), 214*91f16700Schasinglulu (U2PHY_PCTL_NON_DRV_LOW << DRDU3_U2PHY_PCTL_OFFSET)); 215*91f16700Schasinglulu 216*91f16700Schasinglulu return status; 217*91f16700Schasinglulu } 218*91f16700Schasinglulu 219*91f16700Schasinglulu static int32_t drdu3_u3_phy_power_on(uint32_t base) 220*91f16700Schasinglulu { 221*91f16700Schasinglulu int32_t status; 222*91f16700Schasinglulu 223*91f16700Schasinglulu /* Set pctl with mode and soft reset */ 224*91f16700Schasinglulu mmio_clrsetbits_32(base + DRDU3_U3PHY_CTRL, 225*91f16700Schasinglulu (DRDU3_U3PHY_PCTL_MASK << DRDU3_U3PHY_PCTL_OFFSET), 226*91f16700Schasinglulu (U3PHY_PCTL_VAL << DRDU3_U3PHY_PCTL_OFFSET)); 227*91f16700Schasinglulu 228*91f16700Schasinglulu mmio_clrbits_32(base + DRDU3_U3PHY_PLL_CTRL, 229*91f16700Schasinglulu (uint32_t) DRDU3_U3SSPLL_SUSPEND_EN); 230*91f16700Schasinglulu mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_SEQ_START); 231*91f16700Schasinglulu mmio_setbits_32(base + DRDU3_U3PHY_PLL_CTRL, DRDU3_U3PLL_RESETB); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* Time to stabilize the PLL Control */ 234*91f16700Schasinglulu mdelay(1U); 235*91f16700Schasinglulu 236*91f16700Schasinglulu status = pll_lock_check(base + DRDU3_U3PHY_PLL_CTRL, 237*91f16700Schasinglulu DRDU3_U3PLL_SS_LOCK); 238*91f16700Schasinglulu 239*91f16700Schasinglulu return status; 240*91f16700Schasinglulu } 241*91f16700Schasinglulu 242*91f16700Schasinglulu static int32_t drdu2_u2_phy_power_on(uint32_t base) 243*91f16700Schasinglulu { 244*91f16700Schasinglulu int32_t status; 245*91f16700Schasinglulu struct u2_phy_ext_fsm u2_phy; 246*91f16700Schasinglulu 247*91f16700Schasinglulu u2_phy.pll_ctrl_reg = base + DRDU2_U2PLL_CTRL; 248*91f16700Schasinglulu u2_phy.phy_ctrl_reg = base + DRDU2_PHY_CTRL; 249*91f16700Schasinglulu u2_phy.phy_iddq = DRDU2_U2IDDQ; 250*91f16700Schasinglulu u2_phy.pwr_ctrl_reg = base + DRDU2_PWR_CTRL; 251*91f16700Schasinglulu u2_phy.pwr_okin = DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I; 252*91f16700Schasinglulu u2_phy.pwr_onin = DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I; 253*91f16700Schasinglulu 254*91f16700Schasinglulu u2_phy_ext_fsm_power_on(&u2_phy); 255*91f16700Schasinglulu 256*91f16700Schasinglulu status = pll_lock_check(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_LOCK); 257*91f16700Schasinglulu if (status != 0) { 258*91f16700Schasinglulu /* re-try by toggling the PLL reset */ 259*91f16700Schasinglulu mmio_clrbits_32(base + DRDU2_U2PLL_CTRL, 260*91f16700Schasinglulu (uint32_t)DRDU2_U2PLL_RESETB); 261*91f16700Schasinglulu mmio_setbits_32(base + DRDU2_U2PLL_CTRL, DRDU2_U2PLL_RESETB); 262*91f16700Schasinglulu 263*91f16700Schasinglulu status = pll_lock_check(base + DRDU2_U2PLL_CTRL, 264*91f16700Schasinglulu DRDU2_U2PLL_LOCK); 265*91f16700Schasinglulu if (status != 0) 266*91f16700Schasinglulu ERROR("%s() re-try PLL lock FAIL (0x%08x)\n", __func__, 267*91f16700Schasinglulu base + DRDU2_U2PLL_CTRL); 268*91f16700Schasinglulu } 269*91f16700Schasinglulu mmio_clrsetbits_32(base + DRDU2_PHY_CTRL, 270*91f16700Schasinglulu (DRDU2_U2PHY_PCTL_MASK << DRDU2_U2PHY_PCTL_OFFSET), 271*91f16700Schasinglulu (U2PHY_PCTL_NON_DRV_LOW << DRDU2_U2PHY_PCTL_OFFSET)); 272*91f16700Schasinglulu 273*91f16700Schasinglulu return status; 274*91f16700Schasinglulu } 275*91f16700Schasinglulu 276*91f16700Schasinglulu void u3h_u2drd_phy_reset(usb_phy_port_t *phy_port) 277*91f16700Schasinglulu { 278*91f16700Schasinglulu usb_phy_t *phy = phy_port->p; 279*91f16700Schasinglulu 280*91f16700Schasinglulu switch (phy_port->port_id) { 281*91f16700Schasinglulu case USB3HS_PORT: 282*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL, 283*91f16700Schasinglulu (uint32_t) USB3H_U2CTRL_CORERDY); 284*91f16700Schasinglulu mmio_setbits_32(phy->usb3hreg + USB3H_U2PHY_CTRL, 285*91f16700Schasinglulu USB3H_U2CTRL_CORERDY); 286*91f16700Schasinglulu break; 287*91f16700Schasinglulu case DRDU2_PORT: 288*91f16700Schasinglulu mmio_clrbits_32(phy->drdu2reg + DRDU2_PHY_CTRL, 289*91f16700Schasinglulu (uint32_t) DRDU2_U2CTRL_CORERDY); 290*91f16700Schasinglulu mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL, 291*91f16700Schasinglulu DRDU2_U2CTRL_CORERDY); 292*91f16700Schasinglulu break; 293*91f16700Schasinglulu } 294*91f16700Schasinglulu } 295*91f16700Schasinglulu 296*91f16700Schasinglulu void u3drd_phy_reset(usb_phy_port_t *phy_port) 297*91f16700Schasinglulu { 298*91f16700Schasinglulu usb_phy_t *phy = phy_port->p; 299*91f16700Schasinglulu 300*91f16700Schasinglulu if (phy_port->port_id == DRD3HS_PORT) { 301*91f16700Schasinglulu mmio_clrbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL, 302*91f16700Schasinglulu (uint32_t) DRDU3_U2CTRL_CORERDY); 303*91f16700Schasinglulu mmio_setbits_32(phy->drdu3reg + DRDU3_U2PHY_CTRL, 304*91f16700Schasinglulu DRDU3_U2CTRL_CORERDY); 305*91f16700Schasinglulu } 306*91f16700Schasinglulu } 307*91f16700Schasinglulu 308*91f16700Schasinglulu static int32_t u3h_u2drd_phy_power_on(usb_phy_port_t *phy_port) 309*91f16700Schasinglulu { 310*91f16700Schasinglulu usb_phy_t *phy = phy_port->p; 311*91f16700Schasinglulu int32_t status; 312*91f16700Schasinglulu 313*91f16700Schasinglulu switch (phy_port->port_id) { 314*91f16700Schasinglulu case USB3SS_PORT: 315*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, 316*91f16700Schasinglulu (uint32_t) USB3H_DISABLE_USB30_P0); 317*91f16700Schasinglulu status = usb3h_u3_phy_power_on(phy->usb3hreg); 318*91f16700Schasinglulu if (status != 0) { 319*91f16700Schasinglulu goto err_usb3h_phy_on; 320*91f16700Schasinglulu } 321*91f16700Schasinglulu break; 322*91f16700Schasinglulu case USB3HS_PORT: 323*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, 324*91f16700Schasinglulu (uint32_t) USB3H_DISABLE_EUSB_P1); 325*91f16700Schasinglulu mmio_setbits_32(AXI_DEBUG_CTRL, 326*91f16700Schasinglulu AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); 327*91f16700Schasinglulu mmio_setbits_32(USB3H_DEBUG_CTRL, 328*91f16700Schasinglulu USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); 329*91f16700Schasinglulu 330*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL, 331*91f16700Schasinglulu USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWRONIN); 332*91f16700Schasinglulu /* Delay as per external FSM spec */ 333*91f16700Schasinglulu udelay(10U); 334*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + USB3H_PWR_CTRL, 335*91f16700Schasinglulu USB3H_PWR_CTRL_U2PHY_DFE_SWITCH_PWROKIN); 336*91f16700Schasinglulu status = usb3h_u2_phy_power_on(phy->usb3hreg); 337*91f16700Schasinglulu if (status != 0) { 338*91f16700Schasinglulu goto err_usb3h_phy_on; 339*91f16700Schasinglulu } 340*91f16700Schasinglulu break; 341*91f16700Schasinglulu case DRDU2_PORT: 342*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, 343*91f16700Schasinglulu (uint32_t) USB3H_DISABLE_EUSB_P0); 344*91f16700Schasinglulu mmio_setbits_32(AXI_DEBUG_CTRL, 345*91f16700Schasinglulu AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); 346*91f16700Schasinglulu mmio_setbits_32(USB3H_DEBUG_CTRL, 347*91f16700Schasinglulu USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); 348*91f16700Schasinglulu 349*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL, 350*91f16700Schasinglulu DRDU2_U2PHY_DFE_SWITCH_PWRONIN_I); 351*91f16700Schasinglulu /* Delay as per external FSM spec */ 352*91f16700Schasinglulu udelay(10U); 353*91f16700Schasinglulu mmio_clrbits_32(phy->usb3hreg + DRDU2_PWR_CTRL, 354*91f16700Schasinglulu DRDU2_U2PHY_DFE_SWITCH_PWROKIN_I); 355*91f16700Schasinglulu 356*91f16700Schasinglulu status = drdu2_u2_phy_power_on(phy->drdu2reg); 357*91f16700Schasinglulu if (status != 0) { 358*91f16700Schasinglulu mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, 359*91f16700Schasinglulu USB3H_DISABLE_EUSB_P0); 360*91f16700Schasinglulu goto err_drdu2_phy_on; 361*91f16700Schasinglulu } 362*91f16700Schasinglulu break; 363*91f16700Schasinglulu } 364*91f16700Schasinglulu 365*91f16700Schasinglulu /* Device Mode */ 366*91f16700Schasinglulu if (phy_port->port_id == DRDU2_PORT) { 367*91f16700Schasinglulu mmio_write_32(phy->drdu2reg + DRDU2_SOFT_RESET_CTRL, 368*91f16700Schasinglulu DRDU2_BDC_AXI_SOFT_RST_N); 369*91f16700Schasinglulu mmio_setbits_32(phy->drdu2reg + DRDU2_PHY_CTRL, 370*91f16700Schasinglulu DRDU2_U2SOFT_RST_N); 371*91f16700Schasinglulu } 372*91f16700Schasinglulu /* Host Mode */ 373*91f16700Schasinglulu mmio_write_32(phy->usb3hreg + USB3H_SOFT_RESET_CTRL, 374*91f16700Schasinglulu USB3H_XHC_AXI_SOFT_RST_N); 375*91f16700Schasinglulu mmio_setbits_32(phy->usb3hreg + USB3H_U3PHY_CTRL, USB3H_U3SOFT_RST_N); 376*91f16700Schasinglulu 377*91f16700Schasinglulu return 0U; 378*91f16700Schasinglulu err_usb3h_phy_on:mmio_setbits_32(phy->usb3hreg + USB3H_PHY_PWR_CTRL, 379*91f16700Schasinglulu (USB3H_DISABLE_EUSB_P1 | 380*91f16700Schasinglulu USB3H_DISABLE_USB30_P0)); 381*91f16700Schasinglulu err_drdu2_phy_on: 382*91f16700Schasinglulu 383*91f16700Schasinglulu return status; 384*91f16700Schasinglulu } 385*91f16700Schasinglulu 386*91f16700Schasinglulu static int32_t u3drd_phy_power_on(usb_phy_port_t *phy_port) 387*91f16700Schasinglulu { 388*91f16700Schasinglulu usb_phy_t *phy = phy_port->p; 389*91f16700Schasinglulu int32_t status; 390*91f16700Schasinglulu 391*91f16700Schasinglulu switch (phy_port->port_id) { 392*91f16700Schasinglulu case DRD3SS_PORT: 393*91f16700Schasinglulu mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL, 394*91f16700Schasinglulu (uint32_t) DRDU3_DISABLE_USB30_P0); 395*91f16700Schasinglulu 396*91f16700Schasinglulu status = drdu3_u3_phy_power_on(phy->drdu3reg); 397*91f16700Schasinglulu if (status != 0) { 398*91f16700Schasinglulu goto err_drdu3_phy_on; 399*91f16700Schasinglulu } 400*91f16700Schasinglulu break; 401*91f16700Schasinglulu case DRD3HS_PORT: 402*91f16700Schasinglulu mmio_clrbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL, 403*91f16700Schasinglulu (uint32_t) DRDU3_DISABLE_EUSB_P0); 404*91f16700Schasinglulu mmio_setbits_32(AXI_DEBUG_CTRL, 405*91f16700Schasinglulu AXI_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); 406*91f16700Schasinglulu mmio_setbits_32(USB3H_DEBUG_CTRL, 407*91f16700Schasinglulu USB3H_DBG_CTRL_SSPHY_DRD_MODE_DISABLE); 408*91f16700Schasinglulu 409*91f16700Schasinglulu mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL, 410*91f16700Schasinglulu DRDU3_U2PHY_DFE_SWITCH_PWRONIN); 411*91f16700Schasinglulu /* Delay as per external FSM spec */ 412*91f16700Schasinglulu udelay(10U); 413*91f16700Schasinglulu mmio_clrbits_32(phy->drdu3reg + DRDU3_PWR_CTRL, 414*91f16700Schasinglulu DRDU3_U2PHY_DFE_SWITCH_PWROKIN); 415*91f16700Schasinglulu 416*91f16700Schasinglulu status = drdu3_u2_phy_power_on(phy->drdu3reg); 417*91f16700Schasinglulu if (status != 0) { 418*91f16700Schasinglulu goto err_drdu3_phy_on; 419*91f16700Schasinglulu } 420*91f16700Schasinglulu 421*91f16700Schasinglulu /* Host Mode */ 422*91f16700Schasinglulu mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL, 423*91f16700Schasinglulu DRDU3_XHC_AXI_SOFT_RST_N); 424*91f16700Schasinglulu mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL, 425*91f16700Schasinglulu DRDU3_U3XHC_SOFT_RST_N); 426*91f16700Schasinglulu /* Device Mode */ 427*91f16700Schasinglulu mmio_setbits_32(phy->drdu3reg + DRDU3_SOFT_RESET_CTRL, 428*91f16700Schasinglulu DRDU3_BDC_AXI_SOFT_RST_N); 429*91f16700Schasinglulu mmio_setbits_32(phy->drdu3reg + DRDU3_U3PHY_CTRL, 430*91f16700Schasinglulu DRDU3_U3BDC_SOFT_RST_N); 431*91f16700Schasinglulu break; 432*91f16700Schasinglulu } 433*91f16700Schasinglulu 434*91f16700Schasinglulu return 0U; 435*91f16700Schasinglulu err_drdu3_phy_on:mmio_setbits_32(phy->drdu3reg + DRDU3_PHY_PWR_CTRL, 436*91f16700Schasinglulu (DRDU3_DISABLE_EUSB_P0 | 437*91f16700Schasinglulu DRDU3_DISABLE_USB30_P0)); 438*91f16700Schasinglulu 439*91f16700Schasinglulu return status; 440*91f16700Schasinglulu } 441*91f16700Schasinglulu 442*91f16700Schasinglulu static void u3h_u2drd_phy_power_off(usb_phy_port_t *phy_port) 443*91f16700Schasinglulu { 444*91f16700Schasinglulu usb_phy_t *p = phy_port->p; 445*91f16700Schasinglulu 446*91f16700Schasinglulu switch (phy_port->port_id) { 447*91f16700Schasinglulu case USB3SS_PORT: 448*91f16700Schasinglulu mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL, 449*91f16700Schasinglulu USB3H_DISABLE_USB30_P0); 450*91f16700Schasinglulu break; 451*91f16700Schasinglulu case USB3HS_PORT: 452*91f16700Schasinglulu mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL, 453*91f16700Schasinglulu USB3H_DISABLE_EUSB_P1); 454*91f16700Schasinglulu break; 455*91f16700Schasinglulu case DRDU2_PORT: 456*91f16700Schasinglulu mmio_setbits_32(p->usb3hreg + USB3H_PHY_PWR_CTRL, 457*91f16700Schasinglulu USB3H_DISABLE_EUSB_P0); 458*91f16700Schasinglulu break; 459*91f16700Schasinglulu } 460*91f16700Schasinglulu } 461*91f16700Schasinglulu 462*91f16700Schasinglulu static void u3drd_phy_power_off(usb_phy_port_t *phy_port) 463*91f16700Schasinglulu { 464*91f16700Schasinglulu usb_phy_t *p = phy_port->p; 465*91f16700Schasinglulu 466*91f16700Schasinglulu switch (phy_port->port_id) { 467*91f16700Schasinglulu case DRD3SS_PORT: 468*91f16700Schasinglulu mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL, 469*91f16700Schasinglulu DRDU3_DISABLE_USB30_P0); 470*91f16700Schasinglulu break; 471*91f16700Schasinglulu case DRD3HS_PORT: 472*91f16700Schasinglulu mmio_setbits_32(p->drdu3reg + DRDU3_PHY_PWR_CTRL, 473*91f16700Schasinglulu DRDU3_DISABLE_EUSB_P0); 474*91f16700Schasinglulu break; 475*91f16700Schasinglulu } 476*91f16700Schasinglulu } 477*91f16700Schasinglulu 478*91f16700Schasinglulu int32_t usb_info_fill(usb_phy_t *phy_info) 479*91f16700Schasinglulu { 480*91f16700Schasinglulu int32_t index; 481*91f16700Schasinglulu 482*91f16700Schasinglulu if (phy_info->initialized != 0U) { 483*91f16700Schasinglulu return USB_PHY_ALREADY_STARTED; 484*91f16700Schasinglulu } 485*91f16700Schasinglulu 486*91f16700Schasinglulu if (phy_info->phy_id == USB3H_DRDU2_PHY) { 487*91f16700Schasinglulu phy_info->phy_port = usb_phy_port[USB3H_DRDU2_PHY - 1U]; 488*91f16700Schasinglulu phy_info->ports_enabled = 0x7U; 489*91f16700Schasinglulu } else { 490*91f16700Schasinglulu phy_info->phy_port = usb_phy_port[DRDU3_PHY - 1U]; 491*91f16700Schasinglulu phy_info->ports_enabled = 0x3U; 492*91f16700Schasinglulu } 493*91f16700Schasinglulu 494*91f16700Schasinglulu for (index = MAX_NR_PORTS - 1U; index > -1; index--) { 495*91f16700Schasinglulu phy_info->phy_port[index].enabled = (phy_info->ports_enabled 496*91f16700Schasinglulu >> index) & 0x1U; 497*91f16700Schasinglulu phy_info->phy_port[index].p = phy_info; 498*91f16700Schasinglulu phy_info->phy_port[index].port_id = index; 499*91f16700Schasinglulu } 500*91f16700Schasinglulu 501*91f16700Schasinglulu return 0U; 502*91f16700Schasinglulu } 503*91f16700Schasinglulu 504*91f16700Schasinglulu int32_t usb_phy_init(usb_platform_dev *device) 505*91f16700Schasinglulu { 506*91f16700Schasinglulu int32_t status; 507*91f16700Schasinglulu usb_phy_t *phy_info; 508*91f16700Schasinglulu uint32_t index; 509*91f16700Schasinglulu 510*91f16700Schasinglulu phy_info = (usb_phy_t *)device->pcd_id; 511*91f16700Schasinglulu 512*91f16700Schasinglulu status = usb_info_fill(phy_info); 513*91f16700Schasinglulu if (status != 0) { 514*91f16700Schasinglulu return (status == USB_PHY_ALREADY_STARTED) ? 0 : status; 515*91f16700Schasinglulu } 516*91f16700Schasinglulu 517*91f16700Schasinglulu for (index = 0U; index < MAX_NR_PORTS; index++) { 518*91f16700Schasinglulu if (phy_info->phy_port[index].enabled != 0U) { 519*91f16700Schasinglulu switch (phy_info->phy_id) { 520*91f16700Schasinglulu case USB3H_DRDU2_PHY: 521*91f16700Schasinglulu status = 522*91f16700Schasinglulu u3h_u2drd_phy_power_on(&phy_info-> 523*91f16700Schasinglulu phy_port[index]); 524*91f16700Schasinglulu break; 525*91f16700Schasinglulu default: 526*91f16700Schasinglulu status = 527*91f16700Schasinglulu u3drd_phy_power_on(&phy_info-> 528*91f16700Schasinglulu phy_port[index]); 529*91f16700Schasinglulu } 530*91f16700Schasinglulu } 531*91f16700Schasinglulu } 532*91f16700Schasinglulu 533*91f16700Schasinglulu phy_info->initialized = !status; 534*91f16700Schasinglulu return status; 535*91f16700Schasinglulu } 536*91f16700Schasinglulu 537*91f16700Schasinglulu void usb_phy_shutdown(usb_platform_dev *device) 538*91f16700Schasinglulu { 539*91f16700Schasinglulu usb_phy_t *phy_info; 540*91f16700Schasinglulu uint32_t index; 541*91f16700Schasinglulu 542*91f16700Schasinglulu phy_info = (usb_phy_t *)device->pcd_id; 543*91f16700Schasinglulu 544*91f16700Schasinglulu phy_info->initialized = 0U; 545*91f16700Schasinglulu 546*91f16700Schasinglulu for (index = 0U; index < MAX_NR_PORTS; index++) { 547*91f16700Schasinglulu if (phy_info->phy_port[index].enabled != 0U) { 548*91f16700Schasinglulu switch (phy_info->phy_id) { 549*91f16700Schasinglulu case USB3H_DRDU2_PHY: 550*91f16700Schasinglulu u3h_u2drd_phy_power_off(&phy_info-> 551*91f16700Schasinglulu phy_port[index]); 552*91f16700Schasinglulu break; 553*91f16700Schasinglulu case DRDU3_PHY: 554*91f16700Schasinglulu u3drd_phy_power_off(&phy_info->phy_port[index]); 555*91f16700Schasinglulu break; 556*91f16700Schasinglulu default: 557*91f16700Schasinglulu INFO("%s: invalid phy id 0x%x\n", __func__, 558*91f16700Schasinglulu phy_info->phy_id); 559*91f16700Schasinglulu } 560*91f16700Schasinglulu } 561*91f16700Schasinglulu } 562*91f16700Schasinglulu } 563*91f16700Schasinglulu 564*91f16700Schasinglulu int32_t usb_xhci_init(usb_platform_dev *device) 565*91f16700Schasinglulu { 566*91f16700Schasinglulu int32_t status; 567*91f16700Schasinglulu 568*91f16700Schasinglulu status = usb_phy_init(device); 569*91f16700Schasinglulu if (status == USB_PHY_ALREADY_STARTED) { 570*91f16700Schasinglulu status = 0U; 571*91f16700Schasinglulu } 572*91f16700Schasinglulu 573*91f16700Schasinglulu return status; 574*91f16700Schasinglulu } 575*91f16700Schasinglulu 576*91f16700Schasinglulu int32_t usb_device_init(unsigned int usb_func) 577*91f16700Schasinglulu { 578*91f16700Schasinglulu int32_t status; 579*91f16700Schasinglulu int32_t devices_initialized = 0U; 580*91f16700Schasinglulu 581*91f16700Schasinglulu if ((usb_func & USB3H_USB2DRD) != 0U) { 582*91f16700Schasinglulu status = usb_xhci_init( 583*91f16700Schasinglulu &xhci_devices_configs[USB3H_USB2DRD_PHY]); 584*91f16700Schasinglulu if (status == 0) { 585*91f16700Schasinglulu devices_initialized++; 586*91f16700Schasinglulu } else { 587*91f16700Schasinglulu ERROR("%s(): USB3H_USB2DRD init failure\n", __func__); 588*91f16700Schasinglulu } 589*91f16700Schasinglulu } 590*91f16700Schasinglulu 591*91f16700Schasinglulu if ((usb_func & USB3_DRD) != 0U) { 592*91f16700Schasinglulu status = usb_xhci_init(&xhci_devices_configs[USB3_DRD_PHY]); 593*91f16700Schasinglulu if (status == 0) { 594*91f16700Schasinglulu devices_initialized++; 595*91f16700Schasinglulu } else { 596*91f16700Schasinglulu ERROR("%s(): USB3_DRD init failure\n", __func__); 597*91f16700Schasinglulu } 598*91f16700Schasinglulu } 599*91f16700Schasinglulu 600*91f16700Schasinglulu return devices_initialized; 601*91f16700Schasinglulu } 602