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;
    }
}
Example #2
0
void t30_UartD_Init(void)
{
    NvU32 RegData;

    // Initialization is responsible for correct pin mux configuration
    // It also needs to wait for the correct osc frequency to be known
    // IMPORTANT, there is some unspecified logic in the UART that always 
    // operate off PLLP_out3, mail from Robert Quan says that correct operation
    // of UART without starting PLLP requires
    // - to put PLLP in bypass
    // - to override the PLLP_ou3 divider to be 1 (or put in bypass)
    // This is done like that here to avoid any dependence on PLLP analog circuitry 
    // operating correctly

    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_BASE_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_BYPASS, ENABLE);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_BASE_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_OUTB_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_OUTB,
        PLLP_OUT3_OVRRIDE, ENABLE);
    RegData |= NV_DRF_NUM(CLK_RST_CONTROLLER,
        PLLP_OUTB, PLLP_OUT3_RATIO, 0);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_OUTB_0, RegData);

    // Set up the pinmuxes to bring UARTD out on ULPI_clk and ULPI_dir
    // for waluigi T30.  All alternate mappings of UARTD are set to select an input other than UARTD.
    //
    //     GMI_AD16 => Alternate 1 ( SPI4 instead of UD3_TXD)
    //     GMI_AD17 => Alternate 1 ( SPI4 instead of UD3_RXD)
    //     ULPI_CLK  =>Alternate 2 (UD3_TXD)
    //     ULPI_DIR  =>Alternate 2 UD3_RXD)
    //
    // Last reviewed on 08/27/2010
    SET_PIN(GMI_A16,PM,SPI4) ;
    SET_PIN(GMI_A17,PM,SPI4) ;
    SET_PIN(ULPI_CLK,PM,UARTD) ;
    SET_PIN(ULPI_DIR,PM,UARTD) ;

    // Enable the pads.
    SET_PIN(ULPI_CLK, TRISTATE, NORMAL);
    SET_PIN(ULPI_DIR, TRISTATE, NORMAL);

    // enable UART D clock, toggle reset  
    RegData = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_CLK_OUT_ENB_U_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, CLK_OUT_ENB_U, 
        CLK_ENB_UARTD, ENABLE);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
                       CLK_RST_CONTROLLER_CLK_OUT_ENB_U_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_U_0);
    RegData  = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_U,
        SWR_UARTD_RST, ENABLE, RegData);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_U_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_U_0);
    RegData  = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_U,
        SWR_UARTD_RST, DISABLE, RegData);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_U_0, RegData);

    // Then there is the specific set up for UART itself, including the clock configuration.
    // configure at top for source & configure the divider, internal to uart for obscure reasons
    // when UARTD_DIV_ENB is enable DLL/DLLM programming is not required
    //.Refer to the CLK_SOURCE_UARTD reg description in arclk_rst
    // UARTD_DIV_ENB is disabled as new divisor logic is not enabled on FPGA Bug #739606 
#if 0
    NV_WRITE32(NV_ADDRESS_MAP_CAR_BASE+
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0 ,
        (CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_CLK_SRC_CLK_M <<
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_CLK_SRC_SHIFT) |
        (CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_DIV_ENB_DISABLE <<
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_DIV_ENB_SHIFT) |
        0);
#endif

}
Example #3
0
void t30_UartC_Init(void)
{
    NvU32 RegData;

    // Initialization is responsible for correct pin mux configuration
    // It also needs to wait for the correct osc frequency to be known
    // IMPORTANT, there is some unspecified logic in the UART that always 
    // operate off PLLP_out3, mail from Robert Quan says that correct operation
    // of UART without starting PLLP requires
    // - to put PLLP in bypass
    // - to override the PLLP_ou3 divider to be 1 (or put in bypass)
    // This is done like that here to avoid any dependence on PLLP analog circuitry 
    // operating correctly

    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_BASE_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_BYPASS, ENABLE);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_BASE_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_OUTB_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_OUTB,
        PLLP_OUT3_OVRRIDE, ENABLE);
    RegData |= NV_DRF_NUM(CLK_RST_CONTROLLER,
        PLLP_OUTB, PLLP_OUT3_RATIO, 0);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_OUTB_0, RegData);

    // Set up the pinmuxes to bring UARTC out on uart3_txd and uart_rxd
    // for oregon T30.
    //
    //     UART3_TXD  =>primary 0 (UC3_TXD)
    //     UART3_RXD  =>primary 0(UC3_RXD)
    //
    SET_PIN(UART3_TXD,PM,UARTC) ;
    SET_PIN(UART3_RXD,PM,UARTC) ;
//    SET_PIN(UART3_CTS_N,PM,UARTC) ;
//    SET_PIN(UART3_RTS_N,PM,UARTC) ;

    // Enable the pads.
    SET_PIN(UART3_TXD, TRISTATE, NORMAL);
    SET_PIN(UART3_RXD, TRISTATE, NORMAL);

    // enable UART C clock, toggle reset  
    RegData = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, CLK_OUT_ENB_H, 
        CLK_ENB_UARTC, ENABLE);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
                       CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_H_0);
    RegData  = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_H,
        SWR_UARTC_RST, ENABLE, RegData);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_H_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_H_0);
    RegData  = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_H,
        SWR_UARTC_RST, DISABLE, RegData);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_H_0, RegData);

    // Then there is the specific set up for UART itself, including the clock configuration.
    // configure at top for source & configure the divider, internal to uart for obscure reasons
    // when UARTC_DIV_ENB is enable DLL/DLLM programming is not required
    //.Refer to the CLK_SOURCE_UARTD reg description in arclk_rst
    // UARTD_DIV_ENB is disabled as new divisor logic is not enabled on FPGA Bug #739606 
#if 0
    NV_WRITE32(NV_ADDRESS_MAP_CAR_BASE+
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0 ,
        (CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_CLK_SRC_CLK_M <<
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_CLK_SRC_SHIFT) |
        (CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_DIV_ENB_DISABLE <<
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTD_0_UARTD_DIV_ENB_SHIFT) |
        0);
#endif

}
Example #4
0
void t30_UartA_Init(void)
{
    NvU32 RegData;

    // Initialization is responsible for correct pin mux configuration
    // It also needs to wait for the correct osc frequency to be known
    // IMPORTANT, there is some unspecified logic in the UART that always 
    // operate off PLLP_out3, mail from Robert Quan says that correct operation
    // of UART without starting PLLP requires
    // - to put PLLP in bypass
    // - to override the PLLP_ou3 divider to be 1 (or put in bypass)
    // This is done like that here to avoid any dependence on PLLP analog circuitry 
    // operating correctly

    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_BASE_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_BASE, PLLP_BYPASS, ENABLE);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_BASE_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_OUTB_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, PLLP_OUTB,
        PLLP_OUT3_OVRRIDE, ENABLE);
    RegData |= NV_DRF_NUM(CLK_RST_CONTROLLER,
        PLLP_OUTB, PLLP_OUT3_RATIO, 0);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_PLLP_OUTB_0, RegData);

    // Set up the pinmuxes to bring UARTA out on ULPI_DATA0 and ULPI_DATA1
    // for T30.  All alternate mappings of UARTA are set to select an input other than UARTA.
    //
    //     UART2_RTS_N => Alternate 3 ( SPI4 instead of UA3_TXD)
    //     UART2_CTS_N => Alternate 3 ( SPI4 instead of UA3_TXD)
    //     ULPI_DATA0  =>Alternate 2 (UA3_TXD)
    //     ULPI_DATA1  =>Alternate 2 UA3_RXD)
    //     SDMMC1_DAT3 => Primary     (SDMMC1_DAT3 instead of UA3_TXD)
    //     SDMMC1_DAT2 => Primary     (SDMMC1_DAT2 instead of UA3_RXD)
    //     GPIO_PU0    => Alternate 2 (GMI_A6 instead of UA3_TXD)
    //     GPIO_PU1    => Alternate 2 (GMI_A7 instead of UA3_RXD)
    //     SDMMC3_CLK  => Alternate 2 (SDMMC3_SCLK instead of UA3_TXD)
    //     SDMMC3_CMD  => Alternate 2 (SDMMC3_CMD instead of UA3_RXD)
    //
    // Last reviewed on 08/27/2010
    SET_PIN(UART2_RTS_N,PM,SPI4) ;
    SET_PIN(UART2_CTS_N,PM,SPI4) ;
    SET_PIN(ULPI_DATA0,PM,UARTA) ;
    SET_PIN(ULPI_DATA1,PM,UARTA) ;
    SET_PIN(SDMMC1_DAT3,PM,SDMMC1) ;
    SET_PIN(SDMMC1_DAT2,PM,SDMMC1) ;
    SET_PIN(GPIO_PU0,PM,GMI) ;
    SET_PIN(GPIO_PU1,PM,GMI) ;
    SET_PIN(SDMMC3_CLK,  PM, SDMMC3);
    SET_PIN(SDMMC3_CMD,  PM, SDMMC3);
    // Enable the pads.
    SET_PIN(ULPI_DATA0, TRISTATE, NORMAL);
    SET_PIN(ULPI_DATA1, TRISTATE, NORMAL);

    // enable UART A clock, toggle reset  
    RegData = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0);
    RegData |= NV_DRF_DEF(CLK_RST_CONTROLLER, CLK_OUT_ENB_L, 
        CLK_ENB_UARTA, ENABLE);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
                       CLK_RST_CONTROLLER_CLK_OUT_ENB_L_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_L_0);
    RegData  = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
        SWR_UARTA_RST, ENABLE, RegData);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegData);
    RegData  = NV_READ32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_L_0);
    RegData  = NV_FLD_SET_DRF_DEF(CLK_RST_CONTROLLER, RST_DEVICES_L,
        SWR_UARTA_RST, DISABLE, RegData);
    NV_WRITE32(NV_ADDRESS_MAP_PPSB_CLK_RST_BASE +
        CLK_RST_CONTROLLER_RST_DEVICES_L_0, RegData);

    // Then there is the specific set up for UART itself, including the clock configuration.
    // configure at top for source & configure the divider, internal to uart for obscure reasons
    // when UARTA_DIV_ENB is enable DLL/DLLM programming is not required
    //.Refer to the CLK_SOURCE_UARTA reg description in arclk_rst
    // UARTA_DIV_ENB is disabled as new divisor logic is not enabled on FPGA Bug #739606 
    NV_WRITE32(NV_ADDRESS_MAP_CAR_BASE+
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTA_0 ,
        (CLK_RST_CONTROLLER_CLK_SOURCE_UARTA_0_UARTA_CLK_SRC_CLK_M <<
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTA_0_UARTA_CLK_SRC_SHIFT) |
        (CLK_RST_CONTROLLER_CLK_SOURCE_UARTA_0_UARTA_DIV_ENB_DISABLE <<
        CLK_RST_CONTROLLER_CLK_SOURCE_UARTA_0_UARTA_DIV_ENB_SHIFT) |
        0);

}
NvRmPmRequest 
NvRmPrivAp20GetPmRequest(
    NvRmDeviceHandle hRmDevice,
    const NvRmDfsSampler* pCpuSampler,
    NvRmFreqKHz* pCpuKHz)
{
    // Assume initial slave CPU1 On request
    static NvRmPmRequest s_LastPmRequest = (NvRmPmRequest_CpuOnFlag | 0x1);
    static NvRmFreqKHz s_Cpu1OnMinKHz = 0, s_Cpu1OffMaxKHz = 0;
    static NvU32 s_Cpu1OnPendingCnt = 0, s_Cpu1OffPendingCnt = 0;

    NvU32 t;
    NvRmPmRequest PmRequest = NvRmPmRequest_None;
    NvBool Cpu1Off =
        (0 != NV_DRF_VAL(CLK_RST_CONTROLLER, RST_CPU_CMPLX_SET, SET_CPURESET1,
                         NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
                                 CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET_0)));
    NvRmFreqKHz CpuLoadGaugeKHz;

    // Use clocks for load when no busy hint, otherwise use activity metrics
    if (NvRmPrivDfsGetBusyHintActive(NvRmDfsClockId_Cpu)) {
        CpuLoadGaugeKHz = pCpuSampler->AverageKHz;
    } else {
        CpuLoadGaugeKHz = *pCpuKHz;
    }

    // Slave CPU1 power management policy thresholds:
    // - use fixed values if they are defined explicitly, otherwise
    // - set CPU1 OffMax threshold at 3/4 of cpu frequency range,
    //   and 1/2 of max frequency as CPU1 OnMin threshold
    if ((s_Cpu1OffMaxKHz == 0) && (s_Cpu1OnMinKHz == 0))
    {
        NvRmFreqKHz MaxKHz =
            NvRmPrivGetSocClockLimits(NvRmModuleID_Cpu)->MaxKHz;

        s_Cpu1OnMinKHz = NVRM_CPU1_ON_MIN_KHZ ?
                         NVRM_CPU1_ON_MIN_KHZ : (MaxKHz / 2);
        s_Cpu1OffMaxKHz = NVRM_CPU1_OFF_MAX_KHZ ?
                          NVRM_CPU1_OFF_MAX_KHZ : (3 * MaxKHz / 4);
        NV_ASSERT(s_Cpu1OnMinKHz < s_Cpu1OffMaxKHz);
    }

    // Timestamp
    if (s_pTimerUs == NULL)
        s_pTimerUs = NvRmPrivAp15GetTimerUsVirtAddr(hRmDevice);
    t = NV_READ32(s_pTimerUs);

    /*
     * Request OS kernel to turn CPU1 Off if all of the following is true:
     * (a) CPU frequency is below OnMin threshold, 
     * (b) CPU1 is actually On
     *
     * Request OS kernel to turn CPU1 On if all of the following is true:
     * (a) CPU frequency is above OffMax threshold 
     * (b) CPU1 is actually Off
     */
    if (CpuLoadGaugeKHz < s_Cpu1OnMinKHz)
    {
        s_Cpu1OnPendingCnt = 0;
        if ((s_Cpu1OffPendingCnt & 0x1) == 0)
        {
            s_Cpu1OffPendingCnt = t | 0x1;  // Use LSb as a delay start flag
            return PmRequest;
        }
        if ((t - s_Cpu1OffPendingCnt) < (NVRM_CPU1_OFF_PENDING_MS * 1000))
            return PmRequest;

        if (!Cpu1Off)
        {
            s_LastPmRequest = PmRequest = (NvRmPmRequest_CpuOffFlag | 0x1);
            s_Cpu1OffPendingCnt = 0;   // re-start delay after request
        }
#if NVRM_TEST_PMREQUEST_UP_MODE
        NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
            CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET_0,
            CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET_0_SET_CPURESET1_FIELD);
#endif
    }
    else if (CpuLoadGaugeKHz > s_Cpu1OffMaxKHz)
    {
        s_Cpu1OffPendingCnt = 0;
        if ((s_Cpu1OnPendingCnt & 0x1) == 0)
        {
            s_Cpu1OnPendingCnt = t | 0x1;  // Use LSb as a delay start flag
            return PmRequest;
        }
        if ((t - s_Cpu1OnPendingCnt) < (NVRM_CPU1_ON_PENDING_MS * 1000))
            return PmRequest;

        if (Cpu1Off)
        {
            s_LastPmRequest = PmRequest = (NvRmPmRequest_CpuOnFlag | 0x1);
            *pCpuKHz = NvRmPrivGetSocClockLimits(NvRmModuleID_Cpu)->MaxKHz;
            s_Cpu1OnPendingCnt = 0;  // re-start delay after request
        }
#if NVRM_TEST_PMREQUEST_UP_MODE
        NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
            CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR_0,
            CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR_0_CLR_CPURESET1_FIELD);
#endif
    }
    else
    {   // Re-start both delays inside hysteresis loop
        s_Cpu1OnPendingCnt = 0;
        s_Cpu1OffPendingCnt = 0;
    }
    return PmRequest;
}
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
}