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);
}
Exemple #5
0
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
}
Exemple #6
0
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);
    }
}
Exemple #10
0
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;
}