void NvRmPrivPmuRailControl( NvRmDeviceHandle hRmDevice, NvU64 NvRailId, NvBool TurnOn) { NvU32 RailAddress, TimeUs; const NvOdmPeripheralConnectivity* pPmuRail; NvRmPmuVddRailCapabilities RailCapabilities = {0}; if (!s_PmuSupportedEnv) return; pPmuRail = NvOdmPeripheralGetGuid(NvRailId); NV_ASSERT(hRmDevice); NV_ASSERT(pPmuRail); NV_ASSERT(pPmuRail->NumAddress); RailAddress = pPmuRail->AddressList[0].Address; if (TurnOn) { NvRmPmuGetCapabilities(hRmDevice, RailAddress, &RailCapabilities); NvRmPmuSetVoltage(hRmDevice, RailAddress, RailCapabilities.requestMilliVolts, &TimeUs); } else { NvRmPmuSetVoltage( hRmDevice, RailAddress, ODM_VOLTAGE_OFF, &TimeUs); } NvOsWaitUS(TimeUs); }
static void UsbPrivEnableVbus(NvDdkUsbPhy *pUsbPhy, NvBool Enable) { const NvOdmPeripheralConnectivity *pConnectivity = NULL; NvRmPmuVddRailCapabilities RailCaps; NvU32 i; switch (pUsbPhy->Instance) { case 0: pConnectivity = NvOdmPeripheralGetGuid(NV_VDD_VBUS_ODM_ID); break; case 1: pConnectivity = NvOdmPeripheralGetGuid(NV_VDD_USB2_VBUS_ODM_ID); break; case 2: pConnectivity = NvOdmPeripheralGetGuid(NV_VDD_USB3_VBUS_ODM_ID); break; default: break; } if (pConnectivity != NULL) { for (i = 0; i < pConnectivity->NumAddress; i++) { // Search for the vdd rail entry if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_Vdd) { NvRmPmuGetCapabilities(pUsbPhy->hRmDevice, pConnectivity->AddressList[i].Address, &RailCaps); if (Enable) { NvRmPmuSetVoltage(pUsbPhy->hRmDevice, pConnectivity->AddressList[i].Address, RailCaps.requestMilliVolts, NULL); } else { NvRmPmuSetVoltage(pUsbPhy->hRmDevice, pConnectivity->AddressList[i].Address, ODM_VOLTAGE_OFF, NULL); } } } } }
void NvRmPrivPmuLPxStateConfig( NvRmDeviceHandle hRmDevice, NvOdmSocPowerState state, NvBool enter) { NvOdmPmuProperty PmuProperty = {0}; NvBool HasPmuProperty = NvOdmQueryGetPmuProperty(&PmuProperty); const NvOdmPeripheralConnectivity* pCoreRail = NvOdmPeripheralGetGuid(NV_VDD_CORE_ODM_ID); NV_ASSERT(hRmDevice); NV_ASSERT(pCoreRail); NV_ASSERT(pCoreRail->NumAddress); // On platforms with combined cpu/core power request core power rail // should be controlled by the combined request only during deep sleep // - enable the On/Off control on entry, and disable on exit if (state == NvOdmSocPowerState_DeepSleep) { // : AP20 need USB power work around #if defined(CONFIG_MACH_STAR) if (HasPmuProperty) #else if (HasPmuProperty && PmuProperty.CombinedPowerReq) #endif { NvU32 level = enter ? ODM_VOLTAGE_ENABLE_EXT_ONOFF : ODM_VOLTAGE_DISABLE_EXT_ONOFF; NvRmPmuSetVoltage(hRmDevice, pCoreRail->AddressList[0].Address, level, NULL); } } // Mask/Unmask PMU interrupt on entry/exit to/from suspend or deep sleep if ((state == NvOdmSocPowerState_Suspend) || (state == NvOdmSocPowerState_DeepSleep)) NvRmPrivPmuInterruptMask(hRmDevice, enter); }
static int pmic_set(void *data, u64 val) { u32 settling_time; const NvOdmPeripheralConnectivity *con = NULL; int ldo_number; int j; NvU32 millivolts; NvU32 loop_count = MAX_REFCOUNT_LOOP; NvRmPmuVddRailCapabilities rail; struct pmic_struct *pmic_info = data; ldo_number = pmic_info->ldo_number; printk("PMIC(debugfs) : WARNING!! reference counter will be broken\n"); con = NvOdmPeripheralGetGuid(NV_ODM_GUID('a','l','l','p','o','w','e','r')); if (con == NULL){ printk("PMIC(debugfs) : query ERROR\n"); return 0; } if(ldo_number == 2){ printk("PMIC(debugfs) : skip LDO2 test, always on!!!\n"); return 0; } NvRmPmuGetVoltage(s_hRmGlobal, con->AddressList[ldo_number].Address, &millivolts); if(val){ if(millivolts){ printk("PMIC(debugfs) : LDO%d already turned on\n" , ldo_number+1); return 0; } NvRmPmuGetCapabilities(s_hRmGlobal, con->AddressList[ldo_number].Address, &rail); for(j=MAX_REFCOUNT_LOOP;j>powerRefCount[ldo_number];j--){ NvRmPmuSetVoltage(s_hRmGlobal, con->AddressList[ldo_number].Address, rail.requestMilliVolts, &settling_time); } printk("PMIC(debugfs) : LDO%d turn on\n", ldo_number+1); //udelay(settling_time); }else{ if(!millivolts){ printk("PMIC(debugfs) : LDO%d already turned off\n", ldo_number+1); return 0; } while(millivolts && loop_count--){ NvRmPmuSetVoltage(s_hRmGlobal, con->AddressList[ldo_number].Address, NVODM_VOLTAGE_OFF, &settling_time); NvRmPmuGetVoltage(s_hRmGlobal, con->AddressList[ldo_number].Address, &millivolts); if(!millivolts){ powerRefCount[ldo_number]=loop_count; printk("PMIC(debugfs) : LDO%d turn off\n", ldo_number+1); } } //udelay(settling_time); } return 0; }
void NvRmPrivCoreVoltageInit(NvRmDeviceHandle hRmDevice) { NvU32 CoreRailAddress, RtcRailAddress, CpuRailAddress; const NvOdmPeripheralConnectivity* pPmuRail; NvRmMilliVolts CurrentCoreMv = 0; NvRmMilliVolts CurrentRtcMv = 0; NvRmMilliVolts NominalCoreMv = NvRmPrivGetNominalMV(hRmDevice); NV_ASSERT(hRmDevice); if (NvRmPrivGetExecPlatform(hRmDevice) != ExecPlatform_Soc) { return; } pPmuRail = NvOdmPeripheralGetGuid(NV_VDD_CORE_ODM_ID); NV_ASSERT(pPmuRail); NV_ASSERT(pPmuRail->NumAddress); CoreRailAddress = pPmuRail->AddressList[0].Address; pPmuRail = NvOdmPeripheralGetGuid(NV_VDD_RTC_ODM_ID); NV_ASSERT(pPmuRail); NV_ASSERT(pPmuRail->NumAddress); RtcRailAddress = pPmuRail->AddressList[0].Address; // This function is called during PMU initialization when current (= boot) // core voltage is expected to be within one safe step from nominal, and // RTC voltage must be within one safe step from the core. Set nominal // voltage (bump PMU ref count), if the above conditions are true. NvRmPmuGetVoltage(hRmDevice, CoreRailAddress, &CurrentCoreMv); NvRmPmuGetVoltage(hRmDevice, RtcRailAddress, &CurrentRtcMv); if((CurrentCoreMv > (NominalCoreMv + NVRM_SAFE_VOLTAGE_STEP_MV)) || ((CurrentCoreMv + NVRM_SAFE_VOLTAGE_STEP_MV) < NominalCoreMv)) { NV_ASSERT(!"Unexpected initial core voltage"); return; } if((CurrentRtcMv > (CurrentCoreMv + NVRM_SAFE_VOLTAGE_STEP_MV)) || ((CurrentRtcMv + NVRM_SAFE_VOLTAGE_STEP_MV) < CurrentCoreMv)) { NV_ASSERT(!"Unexpected initial RTC voltage"); return; } // If core voltage is going up, update it before CPU if (CurrentCoreMv <= NominalCoreMv) { NvRmPmuSetVoltage(hRmDevice, RtcRailAddress, NominalCoreMv, NULL); NvRmPmuSetVoltage(hRmDevice, CoreRailAddress, NominalCoreMv, NULL); } // If the platform has dedicated CPU voltage rail, make sure it is set to // nominal level as well (bump PMU ref count along the way). if (NvRmPrivIsCpuRailDedicated(hRmDevice)) { NvRmPmuVddRailCapabilities cap; NvRmMilliVolts NominalCpuMv = NvRmPrivModuleVscaleGetMV( hRmDevice, NvRmModuleID_Cpu, NvRmPrivGetSocClockLimits(NvRmModuleID_Cpu)->MaxKHz); pPmuRail = NvOdmPeripheralGetGuid(NV_VDD_CPU_ODM_ID); NV_ASSERT(pPmuRail); NV_ASSERT(pPmuRail->NumAddress); CpuRailAddress = pPmuRail->AddressList[0].Address; // Clip nominal CPU voltage to minimal PMU capabilities, and set it. // (note: PMU with CPU voltage range above nominal is temporary // accepted exception; for other limit violations: PMU maximum level // for CPU is not high enough, or PMU core range does not include // nominal core voltage, assert is fired inside NvRmPmuSetVoltage()) NvRmPmuGetCapabilities(hRmDevice, CpuRailAddress, &cap); NominalCpuMv = NV_MAX(NominalCpuMv, cap.MinMilliVolts); NvRmPmuSetVoltage(hRmDevice, CpuRailAddress, NominalCpuMv, NULL); if (CurrentCoreMv > NominalCoreMv) NvOsWaitUS(NVRM_CPU_TO_CORE_DOWN_US); // delay if core to go down } // If core voltage is going down, update it after CPU voltage if (CurrentCoreMv > NominalCoreMv) { NvRmPmuSetVoltage(hRmDevice, RtcRailAddress, NominalCoreMv, NULL); NvRmPmuSetVoltage(hRmDevice, CoreRailAddress, NominalCoreMv, NULL); } // Always On System I/O, DDR IO and RX DDR (if exist) - set nominal, // bump ref count NvRmPrivPmuRailControl(hRmDevice, NV_VDD_SYS_ODM_ID, NV_TRUE); NvRmPrivPmuRailControl(hRmDevice, NV_VDD_DDR_ODM_ID, NV_TRUE); if (NvOdmPeripheralGetGuid(NV_VDD_DDR_RX_ODM_ID)) NvRmPrivPmuRailControl(hRmDevice, NV_VDD_DDR_RX_ODM_ID, NV_TRUE); }