diff options
author | Venkat Moganty <vmoganty@nvidia.com> | 2010-05-19 21:47:53 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-28 17:49:58 -0700 |
commit | 1f8151757685553dd859d1e4c9d00d3f9c006d6c (patch) | |
tree | 56349edb7c2d0ec5477c19d12b89bdde7375fb0b | |
parent | fc0021e42a7e7f230651fe6703fc83cb8993bf88 (diff) |
[ARM/tegra] usb-phy: integrate LP0 fixes from 2.6.29
Change-Id: I6519568f20c4cd859c198d82c2a3007305a61317
UTMIP pads were turned off before the UTMI phy is set in to the suspend mode.
This is corrected by turning off the UTMIP power control pads after phy is
suspended.
Added workaround for ULPI to bring out of suspend by setting USB2_CLK_OVR_ON
bit in CLK_RST_CONTROLLER register.
Change-Id: I3219946e6351c8ddf5e036dfc3a3f2b3693e99a6
Enable Clock Over On bit for all three controllers during phy resume and
disable during the suspend. Added timeout for the phy clock wait loops.
Change-Id: I71324cc89b4e3031ecc94ee5c05ba6193bab6533
add timeouts to all infinite polling loops to prevent soft lockups when
restoring the phy
Change-Id: I067d50fe26c8e951d92e4e36814d20d9ad2022f2
Reviewed-on: http://git-master/r/1836
Reviewed-by: Gary King <gking@nvidia.com>
Tested-by: Gary King <gking@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/nvddk/nvddk_usbphy_ap20.c | 368 |
1 files changed, 183 insertions, 185 deletions
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_usbphy_ap20.c b/arch/arm/mach-tegra/nvddk/nvddk_usbphy_ap20.c index 245e447327c7..15211a6697d0 100644 --- a/arch/arm/mach-tegra/nvddk/nvddk_usbphy_ap20.c +++ b/arch/arm/mach-tegra/nvddk/nvddk_usbphy_ap20.c @@ -47,6 +47,7 @@ #include "nvddk_usbphy_priv.h" #include "nvodm_query.h" #include "ap20/arahb_arbc.h" +#include "ap20/arclk_rst.h" /* Defines for USB register read and writes */ #define USB_REG_RD(reg)\ @@ -77,7 +78,7 @@ #define USB_REG_READ_VAL(reg, field) \ USB_DRF_VAL(reg, field, USB_REG_RD(reg)) -#define USB_REG_SET_DRF_NUM(reg, field, num, value) \ +#define USB_FLD_SET_DRF_NUM(reg, field, num, value) \ NV_FLD_SET_DRF_NUM(USB2_CONTROLLER_2_USB2D, reg, field, num, value); /* Defines for USB IF register read and writes */ @@ -275,6 +276,88 @@ static const NvU8 s_UtmipElasticLimit = 16; //UTMIP High Speed Sync Start Delay static const NvU8 s_UtmipHsSyncStartDelay = 0; +static void +Ap20UsbPhyConfigUsbClockOverOn( + NvDdkUsbPhy *pUsbPhy, + NvBool EnableOverOn) +{ + NvU32 RegVal = 0x0; + + RegVal = NV_REGR(pUsbPhy->hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0); + switch (pUsbPhy->Instance) + { + case 0: + RegVal = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, LVL2_CLK_GATE_OVRB, + USB1_CLK_OVR_ON, EnableOverOn, RegVal); + break; + case 1: + RegVal = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, LVL2_CLK_GATE_OVRB, + USB2_CLK_OVR_ON, EnableOverOn, RegVal); + break; + case 2: + RegVal = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, LVL2_CLK_GATE_OVRB, + USB3_CLK_OVR_ON, EnableOverOn, RegVal); + break; + default: + NV_ASSERT(!"Unable to enable/disable USB Clock Over On"); + return; + } + NV_REGW(pUsbPhy->hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0, RegVal); + +} + +static NvError +Ap20UsbPhyWaitForInValidPhyClock( + NvDdkUsbPhy *pUsbPhy) +{ + NvU32 TimeOut = USB_PHY_HW_TIMEOUT_US; + + // Wait for the phy clock to become in valid or hardware timeout + do { + if (!USB_IF_REG_READ_VAL(SUSP_CTRL, USB_PHY_CLK_VALID)) + return NvSuccess; + NvOsWaitUS(1); + TimeOut--; + } while (TimeOut); + + NvOsDebugPrintf("Phy Clock is not stopped and timed out\n"); + + return NvError_Timeout; +} + + +static void +Ap20UsbPhyUlpiViewPortProgramData( + NvDdkUsbPhy *pUsbPhy, + NvU32 Addr, + NvU32 Data) +{ + NvU32 RegVal = 0x0; + NvU32 TimeOut = USB_PHY_HW_TIMEOUT_US; + + RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); + RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); + RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_PORT, 0, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, Addr, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, Data, RegVal); + USB_REG_WR(ULPI_VIEWPORT, RegVal); + + // wait for run bit to be cleared + do + { + RegVal = USB_REG_RD(ULPI_VIEWPORT); + if (!TimeOut) + { + NvOsDebugPrintf(" !!!Error in accessing ULPI !!! \n"); + return; + } + NvOsWaitUS(1); + TimeOut--; + } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); +} static NvError Ap20UsbPhyUtmiConfigure( @@ -377,9 +460,11 @@ Ap20UsbPhyUtmiPowerControl( if (Enable) { - // Disable the automatic phy enable on wakeup event - USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_WAKE_ON_DISCON_EN_DEV, DISABLE); - USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_WAKE_ON_CNNT_EN_DEV, DISABLE); + if (pUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_Device) + { + // Disable the automatic phy enable on wakeup event + USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_WAKE_ON_CNNT_EN_DEV, DISABLE); + } // USB Power Up sequence if (!pUsbPhy->pUtmiPadConfig->PadOnRefCount) @@ -473,12 +558,6 @@ Ap20UsbPhyUtmiPowerControl( USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_SUSP_SET, SET); NvOsWaitUS(10); USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_SUSP_SET, UNSET); - //NvOsDebugPrintf("Waiting for Phy Clock to stop \n"); - // check for phy in suspend.. - do { - NvOsWaitUS(1); - } while (USB_IF_REG_READ_VAL(SUSP_CTRL, USB_PHY_CLK_VALID)); - //NvOsDebugPrintf("Phy Clock stopped successfully \n"); } // Put the Phy in the suspend mode @@ -489,24 +568,21 @@ Ap20UsbPhyUtmiPowerControl( USB_REG_WR(PORTSC1, RegVal); } - // Setup debounce time for wakeup event 5 HCLK cycles - USB_IF_REG_UPDATE_NUM(SUSP_CTRL, USB_WAKEUP_DEBOUNCE_COUNT, 5); - // ENABLE the automatic phy enable on wakeup event - USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_WAKE_ON_CNNT_EN_DEV, ENABLE); - USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_WAKE_ON_DISCON_EN_DEV, ENABLE); - // USB Power down sequence - /* decrement the pad control refernce count */ - pUsbPhy->pUtmiPadConfig->PadOnRefCount--; - if (!pUsbPhy->pUtmiPadConfig->PadOnRefCount) + // wait untill phy in suspend.. + Ap20UsbPhyWaitForInValidPhyClock(pUsbPhy); + + if (pUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_Device) { - /* since there is no reference to the pads turn off */ - RegVal = NV_READ32(pUsbPhy->pUtmiPadConfig->pVirAdr + ((USB1_UTMIP_BIAS_CFG0_0)/4)); - // Power down OTG and Bias circuitry - RegVal = USB_UTMIP_FLD_SET_DRF_DEF(BIAS_CFG0, UTMIP_OTGPD, 1, RegVal); - RegVal = USB_UTMIP_FLD_SET_DRF_DEF(BIAS_CFG0, UTMIP_BIASPD, 1, RegVal); - NV_WRITE32(pUsbPhy->pUtmiPadConfig->pVirAdr + ((USB1_UTMIP_BIAS_CFG0_0)/4), - RegVal); + // Setup debounce time for wakeup event 5 HCLK cycles + USB_IF_REG_UPDATE_NUM(SUSP_CTRL, USB_WAKEUP_DEBOUNCE_COUNT, 5); + // ENABLE the automatic phy enable on wakeup event + USB1_IF_REG_UPDATE_DEF(USB_SUSP_CTRL, USB_WAKE_ON_CNNT_EN_DEV, ENABLE); } + // Hold UTMIP in reset + RegVal =USB_IF_REG_RD(SUSP_CTRL); + RegVal = USB3_IF_FLD_SET_DRF_DEF(SUSP_CTRL, UTMIP_RESET, ENABLE, RegVal); + USB_IF_REG_WR(SUSP_CTRL, RegVal); + // Disable Batery charge enabling bit set to '1' for disable USB_UTMIP_REG_UPDATE_NUM(BAT_CHRG_CFG0, UTMIP_PD_CHRG, 1); @@ -529,10 +605,20 @@ Ap20UsbPhyUtmiPowerControl( XCVR_CFG1, UTMIP_FORCE_PDDR_POWERDOWN, 1, RegVal); USB_UTMIP_REG_WR(XCVR_CFG1, RegVal); - // Hold UTMIP in reset - RegVal =USB_IF_REG_RD(SUSP_CTRL); - RegVal = USB3_IF_FLD_SET_DRF_DEF(SUSP_CTRL, UTMIP_RESET, ENABLE, RegVal); - USB_IF_REG_WR(SUSP_CTRL, RegVal); + + // USB Power down sequence + /* decrement the pad control refernce count */ + pUsbPhy->pUtmiPadConfig->PadOnRefCount--; + if (!pUsbPhy->pUtmiPadConfig->PadOnRefCount) + { + /* since there is no reference to the pads turn off */ + RegVal = NV_READ32(pUsbPhy->pUtmiPadConfig->pVirAdr + ((USB1_UTMIP_BIAS_CFG0_0)/4)); + // Power down OTG and Bias circuitry + RegVal = USB_UTMIP_FLD_SET_DRF_DEF(BIAS_CFG0, UTMIP_OTGPD, 1, RegVal); + RegVal = USB_UTMIP_FLD_SET_DRF_DEF(BIAS_CFG0, UTMIP_BIASPD, 1, RegVal); + NV_WRITE32(pUsbPhy->pUtmiPadConfig->pVirAdr + ((USB1_UTMIP_BIAS_CFG0_0)/4), + RegVal); + } } } @@ -666,6 +752,8 @@ Ap20UsbPhyUlpiLinkModeConfigure( NvDdkUsbPhy *pUsbPhy, NvBool Enable) { NvU32 RegVal; + NvU32 TimeOut = USB_PHY_HW_TIMEOUT_US; + if (Enable) { // Put the UHSIC in the reset @@ -704,46 +792,29 @@ Ap20UsbPhyUlpiLinkModeConfigure( ULPI_IF_DRF_NUM(TIMING_CTRL_1, ULPI_DIR_TRIMMER_LOAD, 1) | ULPI_IF_DRF_NUM(TIMING_CTRL_1, ULPI_DIR_TRIMMER_SEL, 4)); - - // fix VbusValid for Harmony due to floating VBUS - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x8, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x40, RegVal); - + RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, SET, 0xFFFFFFFF); + RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, CLEAR, RegVal); + RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_PORT, 0, RegVal); USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { + // wait for ULPI wake up is cleared + do { RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); - + if (!TimeOut) + { + NvOsDebugPrintf("Error accessing ULPI view port\n"); + break; + } + NvOsWaitUS(1); + TimeOut--; + } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_WAKEUP, RegVal)); + // fix VbusValid for Harmony due to floating VBUS + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x08, 0x40); // set UseExternalVbusIndicator to 1 - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0xB, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x80, RegVal); - - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x0B, 0x80); // enabling WKCN/WKDS/WKOC bit RegVal = USB_REG_RD(PORTSC1); @@ -754,117 +825,26 @@ Ap20UsbPhyUlpiLinkModeConfigure( } else { - // Resetting the ULPI register IndicatorPassThru - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x9, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x40, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); - - // Resetting ULPI register UseExternalVbusIndicator - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0xC, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x80, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); + // Programming the ULPI register function control + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x04, 0x4D); - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + // Resetting the ULPI register IndicatorPassThru + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x09, 0x40); // USB Interrupt Rising - making sure vbus comparator and id are off - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x0d, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x00, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x0D, 0x00); // USB Interrupt Falling - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x10, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x00, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x10, 0x00); //Carkit Control - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x19, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x00, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x19, 0x00); // Disabling ID float Rise/Fall (Carkit Enable) - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x1D, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x00, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x1D, 0x00); // USB I/O and power - RegVal = USB_REG_RD(ULPI_VIEWPORT); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_WAKEUP, CLEAR, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RUN, SET, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_RD_WR, WRITE, RegVal); - RegVal = USB_FLD_SET_DRF_DEF(ULPI_VIEWPORT, ULPI_PORT, SW_DEFAULT, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_REG_ADDR, 0x39, RegVal); - RegVal = USB_REG_SET_DRF_NUM(ULPI_VIEWPORT, ULPI_DATA_WR, 0x00, RegVal); - USB_REG_WR(ULPI_VIEWPORT, RegVal); - - // wait for run bit to be cleared - do - { - RegVal = USB_REG_RD(ULPI_VIEWPORT); - } while (USB_DRF_VAL(ULPI_VIEWPORT, ULPI_RUN, RegVal)); + Ap20UsbPhyUlpiViewPortProgramData(pUsbPhy, 0x39, 0x00); // clear WKCN/WKDS/WKOC wake-on events that can cause the USB // Controller to immediately bring the ULPI PHY out of low power mode @@ -898,6 +878,8 @@ Ap20UsbPhyUlpiPowerControl( RegVal = USB_REG_RD(PORTSC1); RegVal = USB_FLD_SET_DRF_DEF(PORTSC1, PHCD, ENABLE, RegVal); USB_REG_WR(PORTSC1, RegVal); + // Wait for phy clock to go down + Ap20UsbPhyWaitForInValidPhyClock(pUsbPhy); } } } @@ -1293,6 +1275,8 @@ Ap20UsbPhyPowerUp( { NvError ErrVal = NvSuccess; + Ap20UsbPhyConfigUsbClockOverOn(pUsbPhy, NV_TRUE); + switch (pUsbPhy->pProperty->UsbInterfaceType) { case NvOdmUsbInterfaceType_UlpiNullPhy: @@ -1320,8 +1304,8 @@ Ap20UsbPhyPowerUp( Ap20UsbPhySelectUsbMode(pUsbPhy); if (pUsbPhy->pProperty->UsbInterfaceType == - NvOdmUsbInterfaceType_UlpiNullPhy) - pUsbPhy->hOdmUlpi = NvOdmUsbUlpiOpen(pUsbPhy->Instance); + NvOdmUsbInterfaceType_UlpiNullPhy) + pUsbPhy->hOdmUlpi = NvOdmUsbUlpiOpen(pUsbPhy->Instance); } return ErrVal; @@ -1350,6 +1334,8 @@ Ap20UsbPhyPowerDown( break; } + Ap20UsbPhyConfigUsbClockOverOn(pUsbPhy, NV_FALSE); + return NvSuccess; } @@ -1390,11 +1376,8 @@ Ap20PhyRemoveTristate( RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, TRISTATE_REG_B, Z_UAB, NORMAL, RegVal); RegVal = NV_FLD_SET_DRF_DEF(APB_MISC_PP, TRISTATE_REG_B, Z_UAC, NORMAL, RegVal); USB_MISC_REGW(pUsbPhy, APB_MISC_PP_TRISTATE_REG_B_0, RegVal); - do - { - RegVal = USB_IF_REG_RD(SUSP_CTRL); - RegVal = NV_DRF_VAL(USB2_IF_USB,SUSP_CTRL, USB_PHY_CLK_VALID, RegVal); - } while (RegVal != USB2_IF_USB_SUSP_CTRL_0_USB_PHY_CLK_VALID_SET); + + Ap20UsbPhyWaitForStableClock(pUsbPhy); } static void @@ -1448,7 +1431,7 @@ Ap20PhyRestoreContext( NvDdkUsbPhy *pUsbPhy) { NvU32 RegVal = 0; - + NvU32 TimeOut = USB_PHY_HW_TIMEOUT_US; /* If any saved context is present, restore it */ // In case of no valid context just return if (!pUsbPhy->Context.IsValid) @@ -1465,15 +1448,15 @@ Ap20PhyRestoreContext( RegVal = USB_REG_RD(PORTSC1); if (pUsbPhy->Context.UsbPortSpeed == NvDdkUsbPhyPortSpeedType_High) { - RegVal = USB_REG_SET_DRF_NUM(PORTSC1, PTC, 0x05, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(PORTSC1, PTC, 0x05, RegVal); } else if (pUsbPhy->Context.UsbPortSpeed == NvDdkUsbPhyPortSpeedType_Full) { - RegVal = USB_REG_SET_DRF_NUM(PORTSC1, PTC, 0x06, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(PORTSC1, PTC, 0x06, RegVal); } else if (pUsbPhy->Context.UsbPortSpeed == NvDdkUsbPhyPortSpeedType_Low) { - RegVal = USB_REG_SET_DRF_NUM(PORTSC1, PTC, 0x07, RegVal); + RegVal = USB_FLD_SET_DRF_NUM(PORTSC1, PTC, 0x07, RegVal); } else { @@ -1484,33 +1467,48 @@ Ap20PhyRestoreContext( // Disable test mode by setting PTC field to NORMAL_OP USB_REG_UPDATE_DEF(PORTSC1, PTC, NORMAL_OP); - // Poll until CCS is enabled do { - RegVal = USB_REG_RD(PORTSC1); - } while (!USB_DRF_VAL(PORTSC1, CCS, RegVal)); - + RegVal = USB_REG_RD(PORTSC1); + if (USB_DRF_VAL(PORTSC1, CCS, RegVal)) + break; + NvOsWaitUS(1); + TimeOut--; + } while (TimeOut); // Poll until PE is enabled + TimeOut = USB_PHY_HW_TIMEOUT_US; do { RegVal = USB_REG_RD(PORTSC1); - } while (!USB_DRF_VAL(PORTSC1, PE, RegVal)); - + if (USB_DRF_VAL(PORTSC1, PE, RegVal)) + break; + NvOsWaitUS(1); + TimeOut--; + } while (TimeOut); // Clear the PCI status, to avoid an interrupt taken upon resume USB_REG_UPDATE_DEF(USBSTS, PCI, PORT_CHANGE); + TimeOut = USB_PHY_HW_TIMEOUT_US; do { RegVal = USB_REG_RD(USBSTS); - } while (USB_DRF_VAL(USBSTS, PCI, RegVal)); - + if (!(USB_DRF_VAL(USBSTS, PCI, RegVal))) + break; + NvOsWaitUS(1); + TimeOut--; + } while (TimeOut); + TimeOut = USB_PHY_HW_TIMEOUT_US; // Put controller in suspend mode by writing 1 to SUSP bit of PORTSC USB_REG_UPDATE_DEF(PORTSC1, SUSP, SUSPEND); // Wait until port suspend completes - while (!USB_REG_READ_VAL(PORTSC1, SUSP)) + do { + if (USB_REG_READ_VAL(PORTSC1, SUSP)) + break; NvOsWaitUS(1); - }; + TimeOut--; + } while (TimeOut); + if (pUsbPhy->pProperty->UsbInterfaceType == NvOdmUsbInterfaceType_UlpiExternalPhy) { Ap20PhyRemoveTristate(pUsbPhy); |