static NvError PwmPowerConfigure(NvRmPwmHandle hPwm, NvBool IsEnablePower) { NvError status = NvSuccess; if (IsEnablePower == NV_TRUE) { if (!hPwm->PowerEnabled) { // Enable power status = NvRmPowerVoltageControl(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), s_PwmPowerID, NvRmVoltsUnspecified, NvRmVoltsUnspecified, NULL, 0, NULL); if (status == NvSuccess) { // Enable the clock to the pwm controller status = NvRmPowerModuleClockControl(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), s_PwmPowerID, NV_TRUE); hPwm->PowerEnabled = NV_TRUE; } } } else { if (hPwm->PowerEnabled) { // Disable the clock to the pwm controller status = NvRmPowerModuleClockControl(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), s_PwmPowerID, NV_FALSE); if(status == NvSuccess) { // Disable power status = NvRmPowerVoltageControl(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), s_PwmPowerID, NvRmVoltsOff, NvRmVoltsOff, NULL, 0, NULL); hPwm->PowerEnabled = NV_FALSE; } } } return status; }
NvError NvRmPrivPmuInit(NvRmDeviceHandle hRmDevice) { NvError e; ExecPlatform env; NvOdmPmuProperty PmuProperty; NV_ASSERT(hRmDevice); env = NvRmPrivGetExecPlatform(hRmDevice); NvOsMemset(&s_Pmu, 0, sizeof(NvRmPmu)); s_PmuSupportedEnv = NV_FALSE; if (env == ExecPlatform_Soc) { // Set supported environment flag s_PmuSupportedEnv = NV_TRUE; // Create the PMU mutex, semaphore, interrupt handler thread, // register PMU interrupt, and get ODM PMU handle NV_CHECK_ERROR_CLEANUP(NvOsMutexCreate(&s_Pmu.hMutex)); NV_CHECK_ERROR_CLEANUP(NvOsSemaphoreCreate(&s_Pmu.hSemaphore, 0)); if (NvOdmQueryGetPmuProperty(&PmuProperty) && PmuProperty.IrqConnected) { if (hRmDevice->ChipId.Id >= 0x20) NvRmPrivAp20SetPmuIrqPolarity( hRmDevice, PmuProperty.IrqPolarity); else NV_ASSERT(PmuProperty.IrqPolarity == NvOdmInterruptPolarity_Low); { NvOsInterruptHandler hPmuIsr = PmuIsr; NvU32 PmuExtIrq = NvRmGetIrqForLogicalInterrupt( hRmDevice, NVRM_MODULE_ID(NvRmPrivModuleID_PmuExt, 0), 0); NV_CHECK_ERROR_CLEANUP(NvRmInterruptRegister(hRmDevice, 1, &PmuExtIrq, &hPmuIsr, &s_Pmu, &s_Pmu.hInterrupt, NV_FALSE)); } } if(!NvOdmPmuDeviceOpen(&s_Pmu.hOdmPmu)) { e = NvError_NotInitialized; goto fail; } NV_CHECK_ERROR_CLEANUP(NvOsThreadCreate(PmuThread, &s_Pmu, &s_Pmu.hThread)); NvRmPrivIoPowerControlInit(hRmDevice); NvRmPrivCoreVoltageInit(hRmDevice); } return NvSuccess; fail: NvRmPrivPmuDeinit(hRmDevice); return e; }
static void UsbPhyOpenHwInterface( NvDdkUsbPhyHandle hUsbPhy) { static NvDdkUsbPhyCapabilities s_UsbPhyCap[] = { // AP15 { NV_FALSE, NV_FALSE }, // AP16 { NV_FALSE, NV_TRUE }, // AP20 { NV_TRUE, NV_FALSE}, }; NvDdkUsbPhyCapabilities *pUsbfCap = NULL; NvRmModuleCapability s_UsbPhyCaps[] = { {1, 0, 0, &s_UsbPhyCap[0]}, // AP15 A01 {1, 1, 0, &s_UsbPhyCap[0]}, // AP15 A02 {1, 2, 0, &s_UsbPhyCap[1]}, // AP16, USB1 {1, 3, 0, &s_UsbPhyCap[1]}, // AP16, USB2 {1, 5, 0, &s_UsbPhyCap[2]}, // AP20, USB1 {1, 6, 0, &s_UsbPhyCap[2]}, // AP20, USB2 {1, 7, 0, &s_UsbPhyCap[2]}, // AP20, USB3 }; NV_ASSERT_SUCCESS( NvRmModuleGetCapabilities(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), s_UsbPhyCaps, NV_ARRAY_SIZE(s_UsbPhyCaps), (void**)&pUsbfCap)); // Fill the client capabilities structure. NvOsMemcpy(&hUsbPhy->Caps, pUsbfCap, sizeof(NvDdkUsbPhyCapabilities)); //NvOsDebugPrintf("NvDdkUsbPhyCapabilities::\n"); //NvOsDebugPrintf("PhyRegInController::[%d] 0-FALSE 1-TRUE\n", hUsbPhy->Caps.PhyRegInController); //NvOsDebugPrintf("CommonClockAndReset::[%d] 0-FALSE 1-TRUE\n", hUsbPhy->Caps.CommonClockAndReset); if (hUsbPhy->Caps.PhyRegInController) { //NvOsDebugPrintf("AP20 USB Controllers\n"); Ap20UsbPhyOpenHwInterface(hUsbPhy); } }
void NvRmPwmClose(NvRmPwmHandle hPwm) { NvU32 i; if (!hPwm) return; NV_ASSERT(hPwm->RefCount); NvOsMutexLock(s_hPwmMutex); hPwm->RefCount--; if (hPwm->RefCount == 0) { // Unmap the pwm register virtual address space for (i = 0; i < NvRmPwmOutputId_Num-2; i++) { NvRmPhysicalMemUnmap((void*)s_hPwm->VirtualAddress[i], s_hPwm->PwmBankSize); } // Unmap the pmc register virtual address space NvRmPhysicalMemUnmap( (void*)s_hPwm->VirtualAddress[NvRmPwmOutputId_Num-2], s_hPwm->PmcBankSize); if (s_IsPwmFirstConfig) { // Disable power PwmPowerConfigure(hPwm, NV_FALSE); // Unregister with RM power NvRmPowerUnRegister(hPwm->RmDeviceHandle, s_PwmPowerID); // Tri-state the pin-mux pins NV_ASSERT_SUCCESS(NvRmSetModuleTristate(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), NV_TRUE)); s_IsPwmFirstConfig = NV_FALSE; } NvOsFree(s_hPwm); s_hPwm = NULL; } NvOsMutexUnlock(s_hPwmMutex); }
static NvError PwmCheckValidConfig(NvRmPwmHandle hPwm, NvRmPwmOutputId OutputId, NvRmPwmMode Mode) { NvError status = NvSuccess; NvRmModulePwmInterfaceCaps PwmCaps; if ((Mode != NvRmPwmMode_Disable) && (Mode != NvRmPwmMode_Enable)) return NvError_NotSupported; status = NvRmGetModuleInterfaceCapabilities(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), sizeof(NvRmModulePwmInterfaceCaps), &PwmCaps); if (status != NvSuccess) return status; if (PwmCaps.PwmOutputIdSupported & (1 << (OutputId-1))) return status; else return NvError_NotSupported; }
NvError NvRmPwmConfig( NvRmPwmHandle hPwm, NvRmPwmOutputId OutputId, NvRmPwmMode Mode, NvU32 DutyCycle, NvU32 RequestedFreqHzOrPeriod, NvU32 *pCurrentFreqHzOrPeriod) { NvError status = NvSuccess; NvU32 RegValue = 0, ResultFreqKHz = 0; NvU8 PwmMode = 0; NvU32 ClockFreqKHz = 0, DCycle = 0, DataOn = 0, DataOff = 0; NvU32 PmcCtrlReg = 0, PmcDpdPadsReg = 0, PmcBlinkTimerReg = 0; NvU32 RequestPeriod = 0, ResultPeriod = 0; NvU32 DataOnRegVal = 0, DataOffRegVal = 0; NvU32 *pPinMuxConfigTable = NULL; NvU32 Count = 0, divider = 1; NvOsMutexLock(s_hPwmMutex); if (OutputId != NvRmPwmOutputId_Blink) { if (!s_IsPwmFirstConfig) { hPwm->PowerEnabled = NV_FALSE; // Register with RM power s_PwmPowerID = NVRM_POWER_CLIENT_TAG('P','W','M',' '); status = NvRmPowerRegister(hPwm->RmDeviceHandle, NULL, &s_PwmPowerID); if (status != NvSuccess) goto fail; // Enable power status = PwmPowerConfigure(hPwm, NV_TRUE); if (status != NvSuccess) { NvRmPowerUnRegister(hPwm->RmDeviceHandle, s_PwmPowerID); goto fail; } // Reset pwm module NvRmModuleReset(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0)); // Config pwm pinmux NvOdmQueryPinMux(NvOdmIoModule_Pwm, (const NvU32 **)&pPinMuxConfigTable, &Count); if (Count != 1) { status = NvError_NotSupported; PwmPowerConfigure(hPwm, NV_FALSE); NvRmPowerUnRegister(hPwm->RmDeviceHandle, s_PwmPowerID); goto fail; } hPwm->PinMap = pPinMuxConfigTable[0]; status = NvRmSetModuleTristate(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), NV_FALSE); if (status != NvSuccess) { PwmPowerConfigure(hPwm, NV_FALSE); NvRmPowerUnRegister(hPwm->RmDeviceHandle, s_PwmPowerID); goto fail; } s_IsPwmFirstConfig = NV_TRUE; } // Enable power status = PwmPowerConfigure(hPwm, NV_TRUE); if (status != NvSuccess) { NvRmPowerUnRegister(hPwm->RmDeviceHandle, s_PwmPowerID); goto fail; } // Validate PWM output and pin map config status = PwmCheckValidConfig(hPwm, OutputId, Mode); if (status != NvSuccess) goto fail; ClockFreqKHz = (RequestedFreqHzOrPeriod * PWM_FREQ_FACTOR) / 1000; if (ClockFreqKHz == 0) ClockFreqKHz = 1; if (RequestedFreqHzOrPeriod == NvRmFreqMaximum) ClockFreqKHz = NvRmFreqMaximum; status = NvRmPowerModuleClockConfig(hPwm->RmDeviceHandle, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), s_PwmPowerID, NvRmFreqUnspecified, NvRmFreqUnspecified, &ClockFreqKHz, 1, &ResultFreqKHz, 0); if (status != NvSuccess) goto fail; *pCurrentFreqHzOrPeriod = (ResultFreqKHz * 1000) / PWM_FREQ_FACTOR; if (Mode == NvRmPwmMode_Disable) PwmMode = 0; else PwmMode = 1; /* * Convert from percentage unsigned 15.16 fixed point * format to actual register value */ DCycle = (DutyCycle * MAX_DUTY_CYCLE/100)>>16; if (DCycle > MAX_DUTY_CYCLE) DCycle = MAX_DUTY_CYCLE; RegValue = PWM_SETNUM(CSR_0, ENB, PwmMode) | PWM_SETNUM(CSR_0, PWM_0, DCycle); if (s_IsFreqDividerSupported) { if ((*pCurrentFreqHzOrPeriod > RequestedFreqHzOrPeriod) && (RequestedFreqHzOrPeriod != 0)) { divider = *pCurrentFreqHzOrPeriod/RequestedFreqHzOrPeriod; if ((*pCurrentFreqHzOrPeriod%RequestedFreqHzOrPeriod)*2>RequestedFreqHzOrPeriod) divider +=1; *pCurrentFreqHzOrPeriod = *pCurrentFreqHzOrPeriod / divider; RegValue |= PWM_SETNUM(CSR_0, PFM_0, divider); } } PWM_REGW(hPwm->VirtualAddress[OutputId-1], 0, RegValue); // If PWM mode is disabled and all pwd channels are disabled then // disable power to PWM if (!PwmMode) { if (IsPwmDisabled(hPwm)) { // Disable power status = PwmPowerConfigure(hPwm, NV_FALSE); if (status != NvSuccess) { NvRmPowerUnRegister(hPwm->RmDeviceHandle, s_PwmPowerID); goto fail; } } } } else {
NvError NvRmPwmOpen( NvRmDeviceHandle hDevice, NvRmPwmHandle *phPwm) { NvError status = NvSuccess; NvU32 PwmPhysAddr = 0, i = 0, PmcPhysAddr = 0; NvRmModuleCapability caps[4]; NvRmModuleCapability *pCap = NULL; NV_ASSERT(hDevice); NV_ASSERT(phPwm); NvOsMutexLock(s_hPwmMutex); if (s_hPwm) { s_hPwm->RefCount++; goto exit; } // Allcoate the memory for the pwm handle s_hPwm = NvOsAlloc(sizeof(NvRmPwm)); if (!s_hPwm) { status = NvError_InsufficientMemory; goto fail; } NvOsMemset(s_hPwm, 0, sizeof(NvRmPwm)); // Set the pwm handle parameters s_hPwm->RmDeviceHandle = hDevice; // Get the pwm physical and virtual base address NvRmModuleGetBaseAddress(hDevice, NVRM_MODULE_ID(NvRmModuleID_Pwm, 0), &PwmPhysAddr, &(s_hPwm->PwmBankSize)); s_hPwm->PwmBankSize = PWM_BANK_SIZE; for (i = 0; i < NvRmPwmOutputId_Num-2; i++) { status = NvRmPhysicalMemMap( PwmPhysAddr + i*s_hPwm->PwmBankSize, s_hPwm->PwmBankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached, (void**)&s_hPwm->VirtualAddress[i]); if (status != NvSuccess) { NvOsFree(s_hPwm); goto fail; } } // Get the pmc physical and virtual base address NvRmModuleGetBaseAddress(hDevice, NVRM_MODULE_ID(NvRmModuleID_Pmif, 0), &PmcPhysAddr, &(s_hPwm->PmcBankSize)); s_hPwm->PmcBankSize = PMC_BANK_SIZE; status = NvRmPhysicalMemMap( PmcPhysAddr, s_hPwm->PmcBankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached, (void**)&s_hPwm->VirtualAddress[NvRmPwmOutputId_Num-2]); if (status != NvSuccess) { NvOsFree(s_hPwm); goto fail; } caps[0].MajorVersion = 1; caps[0].MinorVersion = 0; caps[0].EcoLevel = 0; caps[0].Capability = &caps[0]; caps[1].MajorVersion = 1; caps[1].MinorVersion = 1; caps[1].EcoLevel = 0; caps[1].Capability = &caps[1]; caps[2].MajorVersion = 1; caps[2].MinorVersion = 2; caps[2].EcoLevel = 0; caps[2].Capability = &caps[2]; caps[3].MajorVersion = 2; caps[3].MinorVersion = 0; caps[3].EcoLevel = 0; caps[3].Capability = &caps[3]; NV_ASSERT_SUCCESS(NvRmModuleGetCapabilities( hDevice, NvRmModuleID_Pwm, caps, sizeof(caps)/sizeof(caps[0]), (void**)&pCap)); if ((pCap->MajorVersion > 1) || ((pCap->MajorVersion == 1) && (pCap->MinorVersion > 0))) s_IsFreqDividerSupported = NV_TRUE; s_hPwm->RefCount++; exit: *phPwm = s_hPwm; NvOsMutexUnlock(s_hPwmMutex); return NvSuccess; fail: NvOsMutexUnlock(s_hPwmMutex); return status; }
NvError NvDdkUsbPhyPowerDown( NvDdkUsbPhyHandle hUsbPhy, NvBool IsHostMode, NvBool IsDpd) { NvError e = NvSuccess; NvDdkUsbPhyIoctl_VBusStatusOutputArgs VBusStatus; NvU32 TimeOut = USB_PHY_HW_TIMEOUT_US; NV_ASSERT(hUsbPhy); NvOsMutexLock(hUsbPhy->ThreadSafetyMutex); if (!hUsbPhy->IsPhyPoweredUp) { NvOsMutexUnlock(hUsbPhy->ThreadSafetyMutex); return e; } /* Allow saving register context for the USB host if it is a ULPI interface or if the lowest power state is LP1 */ if (hUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_Host) { hUsbPhy->SaveContext(hUsbPhy); } /* Turn on/off the vbus for host mode */ hUsbPhy->IsHostMode = IsHostMode; if (IsHostMode) { UsbPrivEnableVbus(hUsbPhy, NV_FALSE); /* Wait till Vbus is turned off */ do { NvOsWaitUS(1000); TimeOut -= 1000; e = hUsbPhy->Ioctl(hUsbPhy, NvDdkUsbPhyIoctlType_VBusStatus, NULL, &VBusStatus); } while (VBusStatus.VBusDetected && TimeOut); } // Power down the USB Phy NV_CHECK_ERROR_CLEANUP(hUsbPhy->PowerDown(hUsbPhy)); // On AP20 H-CLK should not be turned off // This is required to detect the sensor interrupts. // However, phy can be programmed to put in the low power mode if (!hUsbPhy->Caps.PhyRegInController) { // Disable the clock NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NV_FALSE)); } // Disable power NV_CHECK_ERROR_CLEANUP( NvRmPowerVoltageControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NvRmVoltsOff, NvRmVoltsOff, NULL, 0, NULL)); /* Turn off the USB busy hints */ UsbPhyDfsBusyHint(hUsbPhy, NV_FALSE, NV_WAIT_INFINITE); if (hUsbPhy->TurnOffPowerRail) { NvOdmEnableUsbPhyPowerRail(NV_FALSE); NvOdmEnableOtgCircuitry(NV_FALSE); } hUsbPhy->IsPhyPoweredUp = NV_FALSE; fail: NvOsMutexUnlock(hUsbPhy->ThreadSafetyMutex); return e; }
NvError NvDdkUsbPhyPowerUp( NvDdkUsbPhyHandle hUsbPhy, NvBool IsHostMode, NvBool IsDpd) { NvError e = NvSuccess; NV_ASSERT(hUsbPhy); NvOsMutexLock(hUsbPhy->ThreadSafetyMutex); if (hUsbPhy->IsPhyPoweredUp) { NvOsMutexUnlock(hUsbPhy->ThreadSafetyMutex); return e; } if (hUsbPhy->TurnOffPowerRail) { NvOdmEnableUsbPhyPowerRail(NV_TRUE); } // Enable power for USB module NV_CHECK_ERROR_CLEANUP( NvRmPowerVoltageControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NvRmVoltsUnspecified, NvRmVoltsUnspecified, NULL, 0, NULL)); // On Ap20 We will not turn off the H-Clk so not required to turn on if (!hUsbPhy->Caps.PhyRegInController) { NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NV_TRUE)); } // Power up the Phy NV_CHECK_ERROR_CLEANUP(hUsbPhy->PowerUp(hUsbPhy)); /* Allow restoring register context for the USB host if it is a ULPI interface or if the lowest power state is LP1 */ if (hUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_Host) { hUsbPhy->RestoreContext(hUsbPhy); } hUsbPhy->IsHostMode = IsHostMode; if (IsHostMode) { UsbPrivEnableVbus(hUsbPhy, NV_TRUE); } else { /* Turn on the USB busy hints */ UsbPhyDfsBusyHint(hUsbPhy, NV_TRUE, NV_WAIT_INFINITE); } hUsbPhy->IsPhyPoweredUp = NV_TRUE; fail: NvOsMutexUnlock(hUsbPhy->ThreadSafetyMutex); return e; }
void NvDdkUsbPhyClose( NvDdkUsbPhyHandle hUsbPhy) { if (!hUsbPhy) return; NvOsMutexLock(s_UsbPhyMutex); if (!hUsbPhy->RefCount) { NvOsMutexUnlock(s_UsbPhyMutex); return; } --hUsbPhy->RefCount; if (hUsbPhy->RefCount) { NvOsMutexUnlock(s_UsbPhyMutex); return; } NvRmSetModuleTristate( hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), NV_TRUE); NvOsMutexLock(hUsbPhy->ThreadSafetyMutex); if (hUsbPhy->RmPowerClientId) { if (hUsbPhy->IsPhyPoweredUp) { NV_ASSERT_SUCCESS( NvRmPowerModuleClockControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NV_FALSE)); //NvOsDebugPrintf("NvDdkUsbPhyClose::VOLTAGE OFF\n"); NV_ASSERT_SUCCESS( NvRmPowerVoltageControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NvRmVoltsOff, NvRmVoltsOff, NULL, 0, NULL)); hUsbPhy->IsPhyPoweredUp = NV_FALSE; } // Unregister driver from Power Manager NvRmPowerUnRegister(hUsbPhy->hRmDevice, hUsbPhy->RmPowerClientId); NvOsSemaphoreDestroy(hUsbPhy->hPwrEventSem); } NvOsMutexUnlock(hUsbPhy->ThreadSafetyMutex); NvOsMutexDestroy(hUsbPhy->ThreadSafetyMutex); if (hUsbPhy->CloseHwInterface) { hUsbPhy->CloseHwInterface(hUsbPhy); } if ((hUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_Host) || (hUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_OTG)) { UsbPrivEnableVbus(hUsbPhy, NV_FALSE); } NvOdmEnableUsbPhyPowerRail(NV_FALSE); NvRmPhysicalMemUnmap( (void*)hUsbPhy->UsbVirAdr, hUsbPhy->UsbBankSize); NvRmPhysicalMemUnmap( (void*)hUsbPhy->MiscVirAdr, hUsbPhy->MiscBankSize); NvOsMemset(hUsbPhy, 0, sizeof(NvDdkUsbPhy)); NvOsMutexUnlock(s_UsbPhyMutex); }
NvError NvDdkUsbPhyOpen( NvRmDeviceHandle hRm, NvU32 Instance, NvDdkUsbPhyHandle *hUsbPhy) { NvError e; NvU32 MaxInstances = 0; NvDdkUsbPhy *pUsbPhy = NULL; NvOsMutexHandle UsbPhyMutex = NULL; NvRmModuleInfo info[MAX_USB_INSTANCES]; NvU32 j; NV_ASSERT(hRm); NV_ASSERT(hUsbPhy); NV_ASSERT(Instance < MAX_USB_INSTANCES); NV_CHECK_ERROR(NvRmModuleGetModuleInfo( hRm, NvRmModuleID_Usb2Otg, &MaxInstances, NULL )); if (MaxInstances > MAX_USB_INSTANCES) { // Ceil "instances" to MAX_USB_INSTANCES MaxInstances = MAX_USB_INSTANCES; } NV_CHECK_ERROR(NvRmModuleGetModuleInfo( hRm, NvRmModuleID_Usb2Otg, &MaxInstances, info )); for (j = 0; j < MaxInstances; j++) { // Check whether the requested instance is present if(info[j].Instance == Instance) break; } // No match found return if (j == MaxInstances) { return NvError_ModuleNotPresent; } if (!s_UsbPhyMutex) { e = NvOsMutexCreate(&UsbPhyMutex); if (e!=NvSuccess) return e; if (NvOsAtomicCompareExchange32( (NvS32*)&s_UsbPhyMutex, 0, (NvS32)UsbPhyMutex)!=0) { NvOsMutexDestroy(UsbPhyMutex); } } NvOsMutexLock(s_UsbPhyMutex); if (!s_pUsbPhy) { s_pUsbPhy = NvOsAlloc(MaxInstances * sizeof(NvDdkUsbPhy)); if (s_pUsbPhy) NvOsMemset(s_pUsbPhy, 0, MaxInstances * sizeof(NvDdkUsbPhy)); } NvOsMutexUnlock(s_UsbPhyMutex); if (!s_pUsbPhy) return NvError_InsufficientMemory; NvOsMutexLock(s_UsbPhyMutex); if (!s_pUtmiPadConfig) { s_pUtmiPadConfig = NvOsAlloc(sizeof(NvDdkUsbPhyUtmiPadConfig)); if (s_pUtmiPadConfig) { NvRmPhysAddr PhyAddr; NvOsMemset(s_pUtmiPadConfig, 0, sizeof(NvDdkUsbPhyUtmiPadConfig)); NvRmModuleGetBaseAddress( hRm, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, 0), &PhyAddr, &s_pUtmiPadConfig->BankSize); NV_CHECK_ERROR_CLEANUP( NvRmPhysicalMemMap( PhyAddr, s_pUtmiPadConfig->BankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached, (void **)&s_pUtmiPadConfig->pVirAdr)); } } NvOsMutexUnlock(s_UsbPhyMutex); if (!s_pUtmiPadConfig) return NvError_InsufficientMemory; pUsbPhy = &s_pUsbPhy[Instance]; NvOsMutexLock(s_UsbPhyMutex); if (!pUsbPhy->RefCount) { NvRmPhysAddr PhysAddr; NvOsMutexHandle ThreadSafetyMutex = NULL; NvOsMemset(pUsbPhy, 0, sizeof(NvDdkUsbPhy)); pUsbPhy->Instance = Instance; pUsbPhy->hRmDevice = hRm; pUsbPhy->RefCount = 1; pUsbPhy->IsPhyPoweredUp = NV_FALSE; pUsbPhy->pUtmiPadConfig = s_pUtmiPadConfig; pUsbPhy->pProperty = NvOdmQueryGetUsbProperty( NvOdmIoModule_Usb, pUsbPhy->Instance); pUsbPhy->TurnOffPowerRail = UsbPhyTurnOffPowerRail(MaxInstances); NV_CHECK_ERROR_CLEANUP(NvOsMutexCreate(&ThreadSafetyMutex)); if (NvOsAtomicCompareExchange32( (NvS32*)&pUsbPhy->ThreadSafetyMutex, 0, (NvS32)ThreadSafetyMutex)!=0) { NvOsMutexDestroy(ThreadSafetyMutex); } NvRmModuleGetBaseAddress( pUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, pUsbPhy->Instance), &PhysAddr, &pUsbPhy->UsbBankSize); NV_CHECK_ERROR_CLEANUP( NvRmPhysicalMemMap( PhysAddr, pUsbPhy->UsbBankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached, (void **)&pUsbPhy->UsbVirAdr)); NvRmModuleGetBaseAddress( pUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Misc, 0), &PhysAddr, &pUsbPhy->MiscBankSize); NV_CHECK_ERROR_CLEANUP( NvRmPhysicalMemMap( PhysAddr, pUsbPhy->MiscBankSize, NVOS_MEM_READ_WRITE, NvOsMemAttribute_Uncached, (void **)&pUsbPhy->MiscVirAdr)); if ( ( pUsbPhy->pProperty->UsbInterfaceType == NvOdmUsbInterfaceType_UlpiNullPhy) || ( pUsbPhy->pProperty->UsbInterfaceType == NvOdmUsbInterfaceType_UlpiExternalPhy)) { if (NvRmSetModuleTristate( pUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, pUsbPhy->Instance), NV_FALSE) != NvSuccess ) return NvError_NotSupported; } // Register with Power Manager NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate(&pUsbPhy->hPwrEventSem, 0)); pUsbPhy->RmPowerClientId = NVRM_POWER_CLIENT_TAG('U','S','B','p'); NV_CHECK_ERROR_CLEANUP( NvRmPowerRegister(pUsbPhy->hRmDevice, pUsbPhy->hPwrEventSem, &pUsbPhy->RmPowerClientId)); // Open the H/W interface UsbPhyOpenHwInterface(pUsbPhy); // Initialize the USB Phy NV_CHECK_ERROR_CLEANUP(UsbPhyInitialize(pUsbPhy)); } else { pUsbPhy->RefCount++; } *hUsbPhy = pUsbPhy; NvOsMutexUnlock(s_UsbPhyMutex); return NvSuccess; fail: NvDdkUsbPhyClose(pUsbPhy); NvOsMutexUnlock(s_UsbPhyMutex); return e; }
static NvError UsbPhyInitialize( NvDdkUsbPhyHandle hUsbPhy) { NvError e = NvSuccess; NvRmFreqKHz CurrentFreq = 0; NvRmFreqKHz PrefFreqList[3] = {12000, 60000, NvRmFreqUnspecified}; // NvOsDebugPrintf("UsbPhyInitialize::VOLTAGE ON, instance %d\n", // hUsbPhy->Instance); // request power NV_CHECK_ERROR_CLEANUP( NvRmPowerVoltageControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NvRmVoltsUnspecified, NvRmVoltsUnspecified, NULL, 0, NULL)); // Enable clock to the USB controller and Phy NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NV_TRUE)); if (!hUsbPhy->Caps.PhyRegInController) { if (hUsbPhy->pProperty->UsbInterfaceType == NvOdmUsbInterfaceType_UlpiNullPhy) { /* Request for 60MHz clk */ NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, PrefFreqList[1], PrefFreqList[1], &PrefFreqList[1], 1, &CurrentFreq, 0)); } else { /* Request for 12 MHz clk */ NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, PrefFreqList[0], PrefFreqList[0], &PrefFreqList[0], 1, &CurrentFreq, 0)); } } // else { /* No need for actual clock configuration - all USB PLL frequencies are available concurrently in this case. */ } // Reset controller NvRmModuleReset(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance)); // On AP20 H-CLK should not be turned off // This is required to detect the sensor interrupts. // However, phy can be programmed to put in the low power mode if (!hUsbPhy->Caps.PhyRegInController) { // Disable the clock NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NV_FALSE)); } // Disable power NV_CHECK_ERROR_CLEANUP( NvRmPowerVoltageControl(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, NvRmVoltsOff, NvRmVoltsOff, NULL, 0, NULL)); // if we are not turning off the power rail during power up and down // then turn on only once during the initalization. if (!hUsbPhy->TurnOffPowerRail) { NvOdmEnableUsbPhyPowerRail(NV_TRUE); } fail: return e; }
static NvError UsbPhyDfsBusyHint( NvDdkUsbPhyHandle hUsbPhy, NvBool DfsOn, NvU32 BoostDurationMs) { NvRmDfsBusyHint pUsbHintOn[] = { { NvRmDfsClockId_Emc, NV_WAIT_INFINITE, USB_HW_MIN_SYSTEM_FREQ_KH, NV_TRUE }, { NvRmDfsClockId_Ahb, NV_WAIT_INFINITE, USB_HW_MIN_SYSTEM_FREQ_KH, NV_TRUE }, { NvRmDfsClockId_Cpu, NV_WAIT_INFINITE, USB_HW_MIN_CPU_FREQ_KH, NV_TRUE } }; NvRmDfsBusyHint pUsbHintOff[] = { { NvRmDfsClockId_Emc, 0, 0, NV_TRUE }, { NvRmDfsClockId_Ahb, 0, 0, NV_TRUE }, { NvRmDfsClockId_Cpu, 0, 0, NV_TRUE } }; NvError e = NvSuccess; NvU32 NumHints; if (hUsbPhy->IsHostMode) { // Do not enable busy hints for cpu clock in host mode NumHints = NV_ARRAY_SIZE(pUsbHintOn) - 1; } else { NumHints = NV_ARRAY_SIZE(pUsbHintOn); } pUsbHintOn[0].BoostDurationMs = BoostDurationMs; pUsbHintOn[1].BoostDurationMs = BoostDurationMs; pUsbHintOn[2].BoostDurationMs = BoostDurationMs; if (DfsOn) { if (hUsbPhy->Caps.PhyRegInController) { // Indicate USB controller is active NvRmFreqKHz PrefFreq = NvRmPowerModuleGetMaxFrequency( hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance)); NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, PrefFreq, PrefFreq, &PrefFreq, 1, NULL, 0)); } return NvRmPowerBusyHintMulti(hUsbPhy->hRmDevice, hUsbPhy->RmPowerClientId, pUsbHintOn, NumHints, NvRmDfsBusyHintSyncMode_Async); } else { if (hUsbPhy->Caps.PhyRegInController) { // Indicate USB controller is idle NvRmFreqKHz PrefFreq = USBC_IDLE_KHZ; NV_CHECK_ERROR_CLEANUP( NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice, NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance), hUsbPhy->RmPowerClientId, PrefFreq, PrefFreq, &PrefFreq, 1, NULL, 0)); } return NvRmPowerBusyHintMulti(hUsbPhy->hRmDevice, hUsbPhy->RmPowerClientId, pUsbHintOff, NumHints, NvRmDfsBusyHintSyncMode_Async); } fail: return e; }