in tegra/xusb-tegra124.c [1476:1611]
static int tegra124_usb3_port_enable(struct tegra_xusb_port *port)
{
struct tegra_xusb_usb3_port *usb3 = to_usb3_port(port);
struct tegra_xusb_padctl *padctl = port->padctl;
struct tegra_xusb_lane *lane = usb3->base.lane;
unsigned int index = port->index, offset;
u32 value;
value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
if (!usb3->internal)
value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
else
value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_INTERNAL(index);
value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(index);
value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(index, usb3->port);
padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP);
/*
* TODO: move this code into the PCIe/SATA PHY ->power_on() callbacks
* and conditionalize based on mux function? This seems to work, but
* might not be the exact proper sequence.
*/
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
(XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) |
(XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT));
value |= (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_VAL <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
(XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_VAL <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) |
(XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_VAL <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT);
if (usb3->context_saved) {
value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
(XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
value |= (usb3->ctle_g <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
(usb3->ctle_z <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
}
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(index));
value = XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_VAL;
if (usb3->context_saved) {
value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
(XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
value |= (usb3->tap1 <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
(usb3->amp <<
XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
}
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(index));
if (lane->pad == padctl->pcie)
offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane->index);
else
offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2;
value = padctl_readl(padctl, offset);
value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK <<
XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT);
value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_VAL <<
XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT;
padctl_writel(padctl, value, offset);
if (lane->pad == padctl->pcie)
offset = XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane->index);
else
offset = XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5;
value = padctl_readl(padctl, offset);
value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN;
padctl_writel(padctl, value, offset);
/* Enable SATA PHY when SATA lane is used */
if (lane->pad == padctl->sata) {
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT);
value |= 0x2 <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
(XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
(XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN);
value |= (0x7 <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
(0x8 <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
(0x8 <<
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS;
padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
}
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(index);
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
usleep_range(100, 200);
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(index);
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
usleep_range(100, 200);
value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(index);
padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
return 0;
}