コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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);
    }
}
コード例 #4
0
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);
}
コード例 #5
0
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; 
}
コード例 #6
0
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
    {
コード例 #7
0
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;
}
コード例 #8
0
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;
}
コード例 #9
0
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;
}
コード例 #10
0
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);
}
コード例 #11
0
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;
}
コード例 #12
0
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;
}
コード例 #13
0
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;
}