void NvRmPrivIoPowerDetectStart( NvRmDeviceHandle hRmDeviceHandle, NvU32 PwrDetMask) { // (1) Enable specified power detect cell NV_REGW(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_PWR_DET_0, PwrDetMask); // (2-3) Set power detect latches for enabled cells to safe "1" (high) value if ((hRmDeviceHandle->ChipId.Id == 0x15) || (hRmDeviceHandle->ChipId.Id == 0x16)) { // On AP15/AP16 set/clear reset bit in PMC scratch0 NvRmPrivAp15IoPowerDetectReset(hRmDeviceHandle); // For AP15 A01 chip the above reset does nothing, therefore // need to set latch "pass-thru" before transition if ((hRmDeviceHandle->ChipId.Id == 0x15) && (hRmDeviceHandle->ChipId.Major == 0x01) && (hRmDeviceHandle->ChipId.Minor == 0x01)) { NvOsWaitUS(NVRM_PWR_DET_DELAY_US); NV_REGW(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_PWR_DET_LATCH_0, 1); } } else { // On AP20+ reset high values directly NvRmPrivAp20IoPowerDetectReset(hRmDeviceHandle); } }
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 NvBool EETI_Resume(NvOdmTouchDeviceHandle hDevice) { EETI_TouchDevice* hTouch = (EETI_TouchDevice*)hDevice; if (hDevice == NULL) { return NV_FALSE; } #if 0 NvOdmGpioInterruptMask(hTouch->hGpioIntr, NV_TRUE); NvOdmGpioInterruptUnregister(hTouch->hGpio, hTouch->hPin, hTouch->hGpioIntr); #endif NvOdmGpioConfig(hTouch->hGpio, hTouch->hPin, NvOdmGpioPinMode_Output); /* Send reset pulse to touch HW */ NvOdmGpioSetState(hTouch->hGpio, hTouch->hPin, 1); NvOsWaitUS(50); NvOdmGpioSetState(hTouch->hGpio, hTouch->hPin, 0); NvOsSleepMS(50); NvOdmGpioSetState(hTouch->hGpio, hTouch->hPin, 1); NvOdmGpioConfig(hTouch->hGpio, hTouch->hPin, NvOdmGpioPinMode_InputInterruptLow); #if 0 if (NvOdmGpioInterruptRegister(hTouch->hGpio, &hTouch->hGpioIntr, hTouch->hPin, NvOdmGpioPinMode_InputInterruptLow, EETI_GpioIsr, (void*)hTouch, EETI_DEBOUNCE_TIME_MS) == NV_FALSE) { return NV_FALSE; } #endif return NV_TRUE; }
void NvRmPmuSetVoltage( NvRmDeviceHandle hDevice, NvU32 vddId, NvU32 MilliVolts, NvU32 * pSettleMicroSeconds) { NvU32 i; NvU32 t = NVRM_PWR_DET_DELAY_US; NV_ASSERT(hDevice); if (pSettleMicroSeconds) *pSettleMicroSeconds = 0; if (!s_PmuSupportedEnv) return; // This API is blocked if diagnostic is in progress for any module if (NvRmPrivIsDiagMode(NvRmModuleID_Invalid)) return; #if PMU_RAILS_NEVER_OFF if (MilliVolts == ODM_VOLTAGE_OFF) return; #endif NV_ASSERT(s_Pmu.hMutex); NvOsMutexLock(s_Pmu.hMutex); // Set voltage and latch IO level sampling results for (i = 0; i < VOLTAGE_CONTROL_RETRY_CNT; i++) { if (NvOdmPmuSetVoltage(s_Pmu.hOdmPmu, vddId, MilliVolts, pSettleMicroSeconds)) break; } NV_ASSERT(i < VOLTAGE_CONTROL_RETRY_CNT); if (s_Pmu.IoPwrDetectMask || s_Pmu.NoIoPwrMask) { NV_ASSERT(MilliVolts != ODM_VOLTAGE_OFF); if (pSettleMicroSeconds) { t += (*pSettleMicroSeconds); *pSettleMicroSeconds = 0; // Don't wait twice } NvOsWaitUS(t); if (s_Pmu.IoPwrDetectMask) // Latch just powered IO rails NvRmPrivIoPowerDetectLatch(hDevice); if (s_Pmu.NoIoPwrMask) // Enable just powered IO rails NvRmPrivIoPowerControl(hDevice, s_Pmu.NoIoPwrMask, NV_TRUE); s_Pmu.IoPwrDetectMask = s_Pmu.NoIoPwrMask = 0; } NvOsMutexUnlock(s_Pmu.hMutex); }
static int nvec_battery_probe(struct nvec_device *pdev) { int i, rc; NvError ErrorStatus = NvSuccess; NvBool result = NV_FALSE; batt_dev = kzalloc(sizeof(struct tegra_battery_dev), GFP_KERNEL); if (!batt_dev) { pr_err("nvec_battery_probe:NOMEM\n"); return -ENOMEM; } ErrorStatus = NvOsMutexCreate(&batt_dev->hBattEventMutex); if (NvSuccess != ErrorStatus) { pr_err("NvOsMutexCreate Failed!\n"); goto Cleanup; } ErrorStatus = NvOsSemaphoreCreate(&batt_dev->hOdmSemaphore, 0); if (NvSuccess != ErrorStatus) { pr_err("NvOsSemaphoreCreate Failed!\n"); goto Cleanup; } /*Henry++ adjust thread to be createn at last batt_dev->exitThread = NV_FALSE; batt_dev->inSuspend = NV_FALSE; ErrorStatus = NvOsThreadCreate(NvBatteryEventHandlerThread, batt_dev, &(batt_dev->hBattEventThread)); if (NvSuccess != ErrorStatus) { pr_err("NvOsThreadCreate FAILED\n"); goto Cleanup; } */ //Henry add retry when fail **** for(i=0;i<BATTERY_RETRY_TIMES;i++){ result = NvOdmBatteryDeviceOpen(&(batt_dev->hOdmBattDev), (NvOdmOsSemaphoreHandle *)&batt_dev->hOdmSemaphore); if (!result || !batt_dev->hOdmBattDev) { pr_err("NvOdmBatteryDeviceOpen FAILED,retry i=%i\n",i); NvOsWaitUS(10000); continue; } else{ break; } } if(i==BATTERY_RETRY_TIMES){ pr_err("NvOdmBatteryDeviceOpen FAILED\n"); goto Cleanup; } //****************************** for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) { if (power_supply_register(&pdev->dev, &tegra_power_supplies[i])) pr_err("Failed to register power supply\n"); } batt_dev->batt_status_poll_period = NVBATTERY_POLLING_INTERVAL; rc = device_create_file(&pdev->dev, &tegra_battery_attr); if (rc) { for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) { power_supply_unregister(&tegra_power_supplies[i]); } pr_err("nvec_battery_probe:device_create_file FAILED"); goto Cleanup; } //Henry++ adjust thread to be createn at last batt_dev->exitThread = NV_FALSE; batt_dev->inSuspend = NV_FALSE; ErrorStatus = NvOsThreadCreate(NvBatteryEventHandlerThread, batt_dev, &(batt_dev->hBattEventThread)); if (NvSuccess != ErrorStatus) { pr_err("NvOsThreadCreate FAILED\n"); goto Cleanup; } return 0; Cleanup: batt_dev->exitThread = NV_TRUE; if (batt_dev->hOdmSemaphore) { NvOsSemaphoreSignal(batt_dev->hOdmSemaphore); NvOsSemaphoreDestroy(batt_dev->hOdmSemaphore); batt_dev->hOdmSemaphore = NULL; } if (batt_dev->hBattEventThread) { NvOsThreadJoin(batt_dev->hBattEventThread); } if (batt_dev->hBattEventMutex) { NvOsMutexDestroy(batt_dev->hBattEventMutex); batt_dev->hBattEventMutex = NULL; } if (batt_dev->hOdmBattDev) { NvOdmBatteryDeviceClose(batt_dev->hOdmBattDev); batt_dev->hOdmBattDev = NULL; } kfree(batt_dev); batt_dev = NULL; //return -1; return 0; //henry++ workaround system can't enter suspend }
void NvOdmOsWaitUS(NvU32 usec) { NvOsWaitUS(usec); }
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; }
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); }
static void PowerGroupPowerControl( NvRmDeviceHandle hRmDeviceHandle, NvU32 PowerGroup, NvBool Enable) { NvU32 reg, Id, Mask, Status; // Do nothing if not SoC platform NV_ASSERT(hRmDeviceHandle); if (NvRmPrivGetExecPlatform(hRmDeviceHandle) != ExecPlatform_Soc) return; // Do nothing if power group is already in requested state NV_ASSERT(s_PowerGroupIds[PowerGroup] != NV_POWERGROUP_INVALID); Id = s_PowerGroupIds[PowerGroup]; Mask = (0x1 << Id); Status = Mask & NV_REGR(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_PWRGATE_STATUS_0); if (Enable == (Status != 0x0)) return; /* * Gating procedure: * - assert resets to all modules in power group * - toggle power gate * * Ungating procedure * - assert resets to all modules in power group (redundunt) * - toggle power gate * - enable clocks to all modules in power group * - reset propagation delay * - remove clamping * - disable clocks to all modules in power group * - de-assert reset to all modules in power group * * Special note on toggle timers( shared with OAL which does CPU power * gating): per convention with OAL default settings are never changed. */ PowerGroupResetControl(hRmDeviceHandle, PowerGroup, NV_TRUE); reg = NV_DRF_DEF(APBDEV_PMC, PWRGATE_TOGGLE, START, ENABLE) | Id; NV_REGW(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_PWRGATE_TOGGLE_0, reg); for (;;) { reg = NV_REGR(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_PWRGATE_STATUS_0); if (Status != (reg & Mask)) break; } if (Enable) { PowerGroupClockControl(hRmDeviceHandle, PowerGroup, NV_TRUE); NvOsWaitUS(NVRM_RESET_DELAY); // PCIE and VDE clamping masks are swapped relatively to // partition Ids (bug 602975) if (PowerGroup == NV_POWERGROUP_PCIE) Mask = 0x1 << s_PowerGroupIds[NV_POWERGROUP_VDE]; else if (PowerGroup == NV_POWERGROUP_VDE) Mask = 0x1 << s_PowerGroupIds[NV_POWERGROUP_PCIE]; NV_REGW(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_REMOVE_CLAMPING_CMD_0, Mask); for (;;) { reg = NV_REGR(hRmDeviceHandle, NvRmModuleID_Pmif, 0, APBDEV_PMC_REMOVE_CLAMPING_CMD_0); if (reg == 0) break; } PowerGroupClockControl(hRmDeviceHandle, PowerGroup, NV_FALSE); PowerGroupResetControl(hRmDeviceHandle, PowerGroup, NV_FALSE); } }
NvBool NvOdmMouseReset(NvOdmMouseDeviceHandle hDevice) { NvError err = NvError_Success; NvEcRequest Request = {0}; NvEcResponse Response = {0}; NvU32 count = 0, MousePort = 0, i = 0; NvBool ret = NV_FALSE; NvOdmMouseDevice *hMouseDev = (NvOdmMouseDevice *)hDevice; MousePort = MOUSE_PS2_PORT_ID_0; count = CMD_MAX_RETRIES + 1; while ((ret==NV_FALSE) && (count--)) { // fill up request structure Request.PacketType = NvEcPacketType_Request; Request.RequestType = NvEcRequestResponseType_AuxDevice; Request.RequestSubtype = ((NvEcRequestResponseSubtype) (NV_DRF_NUM(NVEC,SUBTYPE,AUX_PORT_ID, MousePort))) | ((NvEcRequestResponseSubtype)NvEcAuxDeviceSubtype_SendCommand); Request.NumPayloadBytes = 2; Request.Payload[0] = 0xFF; // set the reset command Request.Payload[1] = 3; // Request to EC err = NvEcSendRequest(hMouseDev->hEc, &Request, &Response, sizeof(Request), sizeof(Response)); if (NvSuccess != err) { //NVODMMOUSE_PRINTF(("NvEcSendRequest failed !!")); NvOsDebugPrintf("NvEcSendRequest failed !!\n"); NvOsWaitUS(100000); continue; } // mouse not found if (NvEcStatus_Success != Response.Status) { //NVODMMOUSE_PRINTF(("EC response failed !!")); NvOsDebugPrintf("EC response failed !!\n"); //if (MousePort != MOUSE_PS2_PORT_ID_1) //{ // count = CMD_MAX_RETRIES + 1; // MousePort = MOUSE_PS2_PORT_ID_1; //} NvOsWaitUS(100000); continue; } if (Response.NumPayloadBytes != 3) continue; // success if (Response.Payload[0] == 0xFA) { ret = NV_TRUE; // at lease one Mouse found! hMouseDev->ValidMousePorts[i] = MousePort; //if (MousePort != MOUSE_PS2_PORT_ID_1) //{ // count = CMD_MAX_RETRIES + 1; // MousePort = MOUSE_PS2_PORT_ID_1; // i++; // continue; //} } } return ret; }