in tegra/xusb-tegra186.c [315:458]
static int tegra186_utmi_enable_phy_sleepwalk(struct tegra_xusb_lane *lane,
enum usb_device_speed speed)
{
struct tegra_xusb_padctl *padctl = lane->pad->padctl;
struct tegra186_xusb_padctl *priv = to_tegra186_xusb_padctl(padctl);
unsigned int index = lane->index;
u32 value;
mutex_lock(&padctl->lock);
/* ensure sleepwalk logic is disabled */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value &= ~MASTER_ENABLE;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* ensure sleepwalk logics are in low power mode */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value |= MASTER_CFG_SEL;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* set debounce time */
value = ao_readl(priv, XUSB_AO_USB_DEBOUNCE_DEL);
value &= ~UTMIP_LINE_DEB_CNT(~0);
value |= UTMIP_LINE_DEB_CNT(1);
ao_writel(priv, value, XUSB_AO_USB_DEBOUNCE_DEL);
/* ensure fake events of sleepwalk logic are desiabled */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value &= ~(FAKE_USBOP_VAL | FAKE_USBON_VAL |
FAKE_USBOP_EN | FAKE_USBON_EN);
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* ensure wake events of sleepwalk logic are not latched */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value &= ~LINE_WAKEUP_EN;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* disable wake event triggers of sleepwalk logic */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value &= ~WAKE_VAL(~0);
value |= WAKE_VAL_NONE;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* power down the line state detectors of the pad */
value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index));
value |= (USBOP_VAL_PD | USBON_VAL_PD);
ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index));
/* save state per speed */
value = ao_readl(priv, XUSB_AO_UTMIP_SAVED_STATE(index));
value &= ~SPEED(~0);
switch (speed) {
case USB_SPEED_HIGH:
value |= UTMI_HS;
break;
case USB_SPEED_FULL:
value |= UTMI_FS;
break;
case USB_SPEED_LOW:
value |= UTMI_LS;
break;
default:
value |= UTMI_RST;
break;
}
ao_writel(priv, value, XUSB_AO_UTMIP_SAVED_STATE(index));
/* enable the trigger of the sleepwalk logic */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value |= LINEVAL_WALK_EN;
value &= ~WAKE_WALK_EN;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* reset the walk pointer and clear the alarm of the sleepwalk logic,
* as well as capture the configuration of the USB2.0 pad
*/
value = ao_readl(priv, XUSB_AO_UTMIP_TRIGGERS(index));
value |= (CLR_WALK_PTR | CLR_WAKE_ALARM | CAP_CFG);
ao_writel(priv, value, XUSB_AO_UTMIP_TRIGGERS(index));
/* setup the pull-ups and pull-downs of the signals during the four
* stages of sleepwalk.
* if device is connected, program sleepwalk logic to maintain a J and
* keep driving K upon seeing remote wake.
*/
value = USBOP_RPD_A | USBOP_RPD_B | USBOP_RPD_C | USBOP_RPD_D;
value |= USBON_RPD_A | USBON_RPD_B | USBON_RPD_C | USBON_RPD_D;
switch (speed) {
case USB_SPEED_HIGH:
case USB_SPEED_FULL:
/* J state: D+/D- = high/low, K state: D+/D- = low/high */
value |= HIGHZ_A;
value |= AP_A;
value |= AN_B | AN_C | AN_D;
break;
case USB_SPEED_LOW:
/* J state: D+/D- = low/high, K state: D+/D- = high/low */
value |= HIGHZ_A;
value |= AN_A;
value |= AP_B | AP_C | AP_D;
break;
default:
value |= HIGHZ_A | HIGHZ_B | HIGHZ_C | HIGHZ_D;
break;
}
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK(index));
/* power up the line state detectors of the pad */
value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index));
value &= ~(USBOP_VAL_PD | USBON_VAL_PD);
ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index));
usleep_range(150, 200);
/* switch the electric control of the USB2.0 pad to XUSB_AO */
value = ao_readl(priv, XUSB_AO_UTMIP_PAD_CFG(index));
value |= FSLS_USE_XUSB_AO | TRK_CTRL_USE_XUSB_AO | RPD_CTRL_USE_XUSB_AO |
RPU_USE_XUSB_AO | VREG_USE_XUSB_AO;
ao_writel(priv, value, XUSB_AO_UTMIP_PAD_CFG(index));
/* set the wake signaling trigger events */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value &= ~WAKE_VAL(~0);
value |= WAKE_VAL_ANY;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
/* enable the wake detection */
value = ao_readl(priv, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
value |= MASTER_ENABLE | LINE_WAKEUP_EN;
ao_writel(priv, value, XUSB_AO_UTMIP_SLEEPWALK_CFG(index));
mutex_unlock(&padctl->lock);
return 0;
}