in tegra/xusb-tegra210.c [464:680]
static int tegra210_pex_uphy_enable(struct tegra_xusb_padctl *padctl)
{
struct tegra_xusb_pcie_pad *pcie = to_pcie_pad(padctl->pcie);
unsigned long timeout;
u32 value;
unsigned int i;
int err;
if (pcie->enable)
return 0;
err = clk_prepare_enable(pcie->pll);
if (err < 0)
return err;
if (tegra210_plle_hw_sequence_is_enabled())
goto skip_pll_init;
err = reset_control_deassert(pcie->rst);
if (err < 0)
goto disable;
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value &= ~(XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT);
value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_VAL <<
XUSB_PADCTL_UPHY_PLL_CTL2_CAL_CTRL_SHIFT;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
value &= ~(XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT);
value |= XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_VAL <<
XUSB_PADCTL_UPHY_PLL_CTL5_DCO_CTRL_SHIFT;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL5);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value |= XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
value &= ~((XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
(XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL4_REFCLK_SEL_SHIFT));
value |= (XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_USB_VAL <<
XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_SEL_SHIFT) |
XUSB_PADCTL_UPHY_PLL_CTL4_TXCLKREF_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value &= ~((XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_MDIV_SHIFT) |
(XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT));
value |= XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_USB_VAL <<
XUSB_PADCTL_UPHY_PLL_CTL1_FREQ_NDIV_SHIFT;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_IDDQ;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value &= ~(XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_MASK <<
XUSB_PADCTL_UPHY_PLL_CTL1_SLEEP_SHIFT);
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
usleep_range(10, 20);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
value |= XUSB_PADCTL_UPHY_PLL_CTL4_REFCLKBUF_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL4);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value |= XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
timeout = jiffies + msecs_to_jiffies(100);
while (time_before(jiffies, timeout)) {
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
if (value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE)
break;
usleep_range(10, 20);
}
if (time_after_eq(jiffies, timeout)) {
err = -ETIMEDOUT;
goto reset;
}
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
timeout = jiffies + msecs_to_jiffies(100);
while (time_before(jiffies, timeout)) {
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
if (!(value & XUSB_PADCTL_UPHY_PLL_CTL2_CAL_DONE))
break;
usleep_range(10, 20);
}
if (time_after_eq(jiffies, timeout)) {
err = -ETIMEDOUT;
goto reset;
}
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value |= XUSB_PADCTL_UPHY_PLL_CTL1_ENABLE;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
timeout = jiffies + msecs_to_jiffies(100);
while (time_before(jiffies, timeout)) {
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
if (value & XUSB_PADCTL_UPHY_PLL_CTL1_LOCKDET_STATUS)
break;
usleep_range(10, 20);
}
if (time_after_eq(jiffies, timeout)) {
err = -ETIMEDOUT;
goto reset;
}
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
value |= XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN |
XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
timeout = jiffies + msecs_to_jiffies(100);
while (time_before(jiffies, timeout)) {
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
if (value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE)
break;
usleep_range(10, 20);
}
if (time_after_eq(jiffies, timeout)) {
err = -ETIMEDOUT;
goto reset;
}
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
timeout = jiffies + msecs_to_jiffies(100);
while (time_before(jiffies, timeout)) {
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
if (!(value & XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_DONE))
break;
usleep_range(10, 20);
}
if (time_after_eq(jiffies, timeout)) {
err = -ETIMEDOUT;
goto reset;
}
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_CLK_EN;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
tegra210_xusb_pll_hw_control_enable();
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL1_PWR_OVRD;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL1);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL2_CAL_OVRD;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL2);
value = padctl_readl(padctl, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
value &= ~XUSB_PADCTL_UPHY_PLL_CTL8_RCAL_OVRD;
padctl_writel(padctl, value, XUSB_PADCTL_UPHY_PLL_P0_CTL8);
usleep_range(10, 20);
tegra210_xusb_pll_hw_sequence_start();
skip_pll_init:
pcie->enable = true;
for (i = 0; i < padctl->pcie->soc->num_lanes; i++) {
value = padctl_readl(padctl, XUSB_PADCTL_USB3_PAD_MUX);
value |= XUSB_PADCTL_USB3_PAD_MUX_PCIE_IDDQ_DISABLE(i);
padctl_writel(padctl, value, XUSB_PADCTL_USB3_PAD_MUX);
}
return 0;
reset:
reset_control_assert(pcie->rst);
disable:
clk_disable_unprepare(pcie->pll);
return err;
}