void
NvRmPrivGetSku( NvRmDeviceHandle rm )
{
    NvError e;
    NvRmChipId *id;
    NvU8 *FuseVirt;
    NvU32 reg;

#if NV_USE_FUSE_CLOCK_ENABLE
    NvU8 *CarVirt = 0;
#endif

    NV_ASSERT( rm );
    id = &rm->ChipId;

#if NV_USE_FUSE_CLOCK_ENABLE
    // Enable fuse clock
    e = NvRmPhysicalMemMap(0x60006000, 0x1000, NVOS_MEM_READ_WRITE,
        NvOsMemAttribute_Uncached, (void **)&CarVirt);
    if (e == NvSuccess)
    {
       reg = NV_READ32(CarVirt + CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0);
       reg |= 0x80;
       NV_WRITE32(CarVirt + CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0, reg);
    }
#endif

    /* Read the fuse only on real silicon, as it was not gauranteed to be
     * preset on the eluation/simulation platforms.
     */
    e = NvRmPhysicalMemMap(0x7000f800, 0x400, NVOS_MEM_READ_WRITE,
        NvOsMemAttribute_Uncached, (void **)&FuseVirt);
    if (e == NvSuccess)
    {
        // Read the SKU from the fuse module.
        reg = NV_READ32( FuseVirt + FUSE_SKU_INFO_0 );
        id->SKU = (NvU16)reg;
        NvRmPhysicalMemUnmap(FuseVirt, 0x400);

#if NV_USE_FUSE_CLOCK_ENABLE
        // Disable fuse clock
        if (CarVirt)
        {
            reg = NV_READ32(CarVirt + CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0);
            reg &= ~0x80;
            NV_WRITE32(CarVirt + CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0, reg);
            NvRmPhysicalMemUnmap(CarVirt, 0x1000);
        }
#endif
    } else
    {
        NV_ASSERT(!"Cannot map the FUSE aperture to get the SKU");
        id->SKU = 0;
    }
}
NvError
NvRmPrivMapApertures( NvRmDeviceHandle rm )
{
    NvRmModuleTable *tbl;
    NvRmModuleInstance *inst;
    NvRmModule *mod;
    NvU32 devid;
    NvU32 i;
    NvError e;

    NV_ASSERT( rm );

    /* loop over the instance list and map everything */
    tbl = &rm->ModuleTable;
    mod = tbl->Modules;
    for( i = 0; i < NvRmPrivModuleID_Num; i++ )
    {
        if( mod[i].Index == NVRM_MODULE_INVALID )
        {
            continue;
        }

        if ((i != NvRmPrivModuleID_Ahb_Arb_Ctrl ) &&
            (i != NvRmPrivModuleID_ApbDma ) &&
            (i != NvRmPrivModuleID_ApbDmaChannel ) &&
            (i != NvRmPrivModuleID_ClockAndReset ) &&
            (i != NvRmPrivModuleID_ExternalMemoryController ) &&
            (i != NvRmPrivModuleID_Gpio ) &&
            (i != NvRmPrivModuleID_Interrupt ) &&
            (i != NvRmPrivModuleID_InterruptArbGnt ) &&
            (i != NvRmPrivModuleID_InterruptDrq ) &&
            (i != NvRmPrivModuleID_MemoryController ) &&
            (i != NvRmModuleID_Misc) &&
            (i != NvRmPrivModuleID_ArmPerif) &&
            (i != NvRmModuleID_3D) &&
            (i != NvRmModuleID_CacheMemCtrl ) &&
            (i != NvRmModuleID_Display) &&
            (i != NvRmModuleID_Dvc) &&
            (i != NvRmModuleID_FlowCtrl ) &&
            (i != NvRmModuleID_Fuse ) &&
            (i != NvRmModuleID_GraphicsHost ) &&
            (i != NvRmModuleID_I2c) &&
            (i != NvRmModuleID_Isp) &&
            (i != NvRmModuleID_Mpe) &&
            (i != NvRmModuleID_Pmif ) &&
            (i != NvRmModuleID_Mipi ) &&
            (i != NvRmModuleID_ResourceSema ) &&
            (i != NvRmModuleID_SysStatMonitor ) &&
            (i != NvRmModuleID_TimerUs ) &&
            (i != NvRmModuleID_Vde ) &&
            (i != NvRmModuleID_ExceptionVector ) &&
            (i != NvRmModuleID_Usb2Otg ) &&
            (i != NvRmModuleID_Vi)
            )
        {
            continue;
        }

        /* FIXME If the multiple instances of the same module is adjacent to
         * each other then we can do one allocation for all those modules.
         */

        /* map all of the device instances */
        inst = tbl->ModInst + mod[i].Index;
        devid = inst->DeviceId;
        while( devid == inst->DeviceId )
        {
            /* If this is a device that actually has an aperture... */
            if (inst->PhysAddr)
            {
                e = NvRmPhysicalMemMap(
                        inst->PhysAddr, inst->Length, NVOS_MEM_READ_WRITE,
                        NvOsMemAttribute_Uncached, &inst->VirtAddr);
                if (e != NvSuccess)
                {
                    NV_DEBUG_PRINTF(("Device %d at physical addr 0x%X has no "
                        "virtual mapping\n", devid, inst->PhysAddr));
                    return e;
                }
            }

            inst++;
        }
    }

    return NvSuccess;
}
Пример #3
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;
}
void
NvRmPrivReadChipId( NvRmDeviceHandle rm )
{
#if (NVCPU_IS_X86 && NVOS_IS_WINDOWS)
    NvRmChipId *id;
    NV_ASSERT( rm );

    id = &rm->ChipId;

    id->Family = NvRmChipFamily_HandheldSoc;
    id->Id = 0x15;
    id->Major = 0x0;
    id->Minor = 0x0;
    id->SKU = 0x0;
    id->Netlist = 0x0;
    id->Patch = 0x0;
#else
    NvU32 reg;
    NvRmChipId *id;
    NvU32 fam;
    char *s;
    NvU8 *VirtAddr;
    NvError e;

    NV_ASSERT( rm );
    id = &rm->ChipId;

    /* Hard coding the address of the chip ID address space, as we haven't yet
     * parsed the relocation table.
     */
    e = NvRmPhysicalMemMap(0x70000000, 0x1000, NVOS_MEM_READ_WRITE,
        NvOsMemAttribute_Uncached, (void **)&VirtAddr);
    if (e != NvSuccess)
    {
        NV_DEBUG_PRINTF(("APB misc aperture map failure\n"));
        return;
    }

    /* chip id is in the misc aperture */
    reg = NV_READ32( VirtAddr + APB_MISC_GP_HIDREV_0 );
    id->Id = (NvU16)NV_DRF_VAL( APB_MISC_GP, HIDREV, CHIPID, reg );
    id->Major = (NvU8)NV_DRF_VAL( APB_MISC_GP, HIDREV, MAJORREV, reg );
    id->Minor = (NvU8)NV_DRF_VAL( APB_MISC_GP, HIDREV, MINORREV, reg );

    fam = NV_DRF_VAL( APB_MISC_GP, HIDREV, HIDFAM, reg );
    switch( fam ) {
    case APB_MISC_GP_HIDREV_0_HIDFAM_GPU:
        id->Family = NvRmChipFamily_Gpu;
        s = "GPU";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_HANDHELD:
        id->Family = NvRmChipFamily_Handheld;
        s = "Handheld";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_BR_CHIPS:
        id->Family = NvRmChipFamily_BrChips;
        s = "BrChips";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_CRUSH:
        id->Family = NvRmChipFamily_Crush;
        s = "Crush";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_MCP:
        id->Family = NvRmChipFamily_Mcp;
        s = "MCP";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_CK:
        id->Family = NvRmChipFamily_Ck;
        s = "Ck";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_VAIO:
        id->Family = NvRmChipFamily_Vaio;
        s = "Vaio";
        break;
    case APB_MISC_GP_HIDREV_0_HIDFAM_HANDHELD_SOC:
        id->Family = NvRmChipFamily_HandheldSoc;
        s = "Handheld SOC";
        break;
    default:
        NV_ASSERT( !"bad chip family" );
        NvRmPhysicalMemUnmap(VirtAddr, 0x1000);
        return;
    }

    reg = NV_READ32( VirtAddr + APB_MISC_GP_EMU_REVID_0 );
    id->Netlist = (NvU16)NV_DRF_VAL( APB_MISC_GP, EMU_REVID, NETLIST, reg );
    id->Patch = (NvU16)NV_DRF_VAL( APB_MISC_GP, EMU_REVID, PATCH, reg );

    if( id->Major == 0 )
    {
        char *emu;
        if( id->Netlist == 0 )
        {
            NvOsDebugPrintf( "Simulation Chip: 0x%x\n", id->Id );
        }
        else
        {
            if( id->Minor == 0 )
            {
                emu = "QuickTurn";
            }
            else
            {
                emu = "FPGA";
            }

            NvOsDebugPrintf( "Emulation (%s) Chip: 0x%x Netlist: 0x%x "
                "Patch: 0x%x\n", emu, id->Id, id->Netlist, id->Patch );
        }
    }
    else
    {
        // on real silicon

        NvRmPrivGetSku( rm );

        NvOsDebugPrintf( "Chip Id: 0x%x (%s) Major: 0x%x Minor: 0x%x "
            "SKU: 0x%x\n", id->Id, s, id->Major, id->Minor, id->SKU );
    }

    // add a sanity check here, so that if we think we are on sim, but don't
    // detect a sim/quickturn netlist bail out with an error
    if ( NvRmIsSimulation() && id->Major != 0 )
    {
        // this should all get optimized away in release builds because the
        // above will get evaluated to if ( 0 )
        NV_ASSERT(!"invalid major version number for simulation");
    }
    NvRmPhysicalMemUnmap(VirtAddr, 0x1000);
#endif
}
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;
}