Example #1
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);
}
Example #2
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
    {
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;
}