예제 #1
0
void
Adt7461ParameterCapsGet(
    NvOdmTmonDeviceHandle hTmon,
    NvOdmTmonZoneID ZoneId,
    NvOdmTmonConfigParam ParamId,
    NvOdmTmonParameterCaps* pCaps)
{
    NvBool ExtRange;
    ADT7461PrivData* pPrivData;
    const ADT7461ChannelInfo* pChannel;

    NV_ASSERT(hTmon && hTmon->pPrivate && pCaps);
    pPrivData = hTmon->pPrivate;
#if PRE_ER_GMT_THERMALSENSOR
    ExtRange = 0; /* not support ADT thermal sensor*/
#else
    ExtRange = ((pPrivData->ShadowConfig &
                 ADT7461ConfigBits_ExtendedRange) != 0);
#endif			

    pChannel = &pPrivData->pDeviceInfo->Channels[(
        pPrivData->ConnectivityMap[ZoneId])];

    switch (ParamId)
    {
        case NvOdmTmonConfigParam_IntrLimitHigh:
        case NvOdmTmonConfigParam_IntrLimitLow:
            pCaps->OdmProtected =
                pChannel->ChannelPolicy.IntrLimitsOdmProtected;
            break;

        case NvOdmTmonConfigParam_HwLimitCrit:
            pCaps->OdmProtected =
                pChannel->ChannelPolicy.HwLimitCritOdmProtected;
            break;

        case NvOdmTmonConfigParam_SampleMs:
            // smaple intervals in descending order
            pCaps->MaxValue = s_Adt7461SampleIntervalsMS[0];
            pCaps->MinValue = s_Adt7461SampleIntervalsMS[(
                NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS) - 1)];
            pCaps->OdmProtected = pChannel->ChannelPolicy.RateOdmProtected;
            return;

        default:        // unsupported parameter
            pCaps->MaxValue = ODM_TMON_PARAMETER_UNSPECIFIED;
            pCaps->MinValue = ODM_TMON_PARAMETER_UNSPECIFIED;
            pCaps->OdmProtected = NV_TRUE;
            return;
    }

    // Common range for limits
    pCaps->MaxValue = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange);
    pCaps->MinValue = ADT7461_T_RANGE_LIMIT_LOW(ExtRange);
}
예제 #2
0
void 
Adt7461CapabilitiesGet(
    NvOdmTmonDeviceHandle hTmon,
    NvOdmTmonZoneID ZoneId,
    NvOdmTmonCapabilities* pCaps)
{
    NvBool ExtRange;
    ADT7461PrivData* pPrivData;

    NV_ASSERT(hTmon && hTmon->pPrivate && pCaps);
    pPrivData = hTmon->pPrivate;
    ExtRange = ((pPrivData->ShadowConfig &
                 ADT7461ConfigBits_ExtendedRange) != 0);
    
    pCaps->Tmax = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange);
    pCaps->Tmin = ADT7461_T_RANGE_LIMIT_LOW(ExtRange);
    pCaps->IntrSupported = NV_TRUE;
    pCaps->HwCriticalSupported = NV_TRUE;
    pCaps->HwCoolingSupported = NV_FALSE;
}
예제 #3
0
void 
Adt7461CapabilitiesGet(
    NvOdmTmonDeviceHandle hTmon,
    NvOdmTmonZoneID ZoneId,
    NvOdmTmonCapabilities* pCaps)
{
    NvBool ExtRange;
    ADT7461PrivData* pPrivData;

    NV_ASSERT(hTmon && hTmon->pPrivate && pCaps);
    pPrivData = hTmon->pPrivate;
#if PRE_ER_GMT_THERMALSENSOR
    ExtRange = 0; /* not support ADT thermal sensor*/
#else
    ExtRange = ((pPrivData->ShadowConfig &
                 ADT7461ConfigBits_ExtendedRange) != 0);
#endif		
    
    pCaps->Tmax = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange);
    pCaps->Tmin = ADT7461_T_RANGE_LIMIT_LOW(ExtRange);
    pCaps->IntrSupported = NV_TRUE;
    pCaps->HwCriticalSupported = NV_TRUE;
    pCaps->HwCoolingSupported = NV_FALSE;
}
예제 #4
0
NvBool
Adt7461ParameterConfig(
    NvOdmTmonDeviceHandle hTmon,
    NvOdmTmonZoneID ZoneId,
    NvOdmTmonConfigParam ParamId,
    NvS32* pSetting)
{
    NvU8 Data;
    NvBool ExtRange, OdmProtected;
    ADT7461PrivData* pPrivData;
    const ADT7461RegisterInfo* pReg;
    const ADT7461ChannelInfo* pChannel;

    NV_ASSERT(hTmon && hTmon->pPrivate && pSetting);
    pPrivData = hTmon->pPrivate;
#if PRE_ER_GMT_THERMALSENSOR
    ExtRange = 0; /* not support ADT thermal sensor*/
#else
    ExtRange = ((pPrivData->ShadowConfig &
                 ADT7461ConfigBits_ExtendedRange) != 0);
#endif			
    pChannel = &pPrivData->pDeviceInfo->Channels[(
        pPrivData->ConnectivityMap[ZoneId])];

    switch (ParamId)
    {
        case NvOdmTmonConfigParam_IntrLimitHigh:
#if PRE_ER_WORKAROUND
            return NV_TRUE;
#endif
            pReg = &pChannel->IntrLimitHigh;
            OdmProtected = pChannel->ChannelPolicy.IntrLimitsOdmProtected;
            break;

        case NvOdmTmonConfigParam_IntrLimitLow:
#if PRE_ER_WORKAROUND
            return NV_TRUE;
#endif
            pReg = &pChannel->IntrLimitLow;
            OdmProtected = pChannel->ChannelPolicy.IntrLimitsOdmProtected;
            break;

        case NvOdmTmonConfigParam_HwLimitCrit:
#if PRE_ER_WORKAROUND
            return NV_TRUE;
#endif
            pReg = &pChannel->ComparatorLimit;
            OdmProtected = pChannel->ChannelPolicy.HwLimitCritOdmProtected;
            break;

        case NvOdmTmonConfigParam_SampleMs:
            OdmProtected = pChannel->ChannelPolicy.RateOdmProtected;
            return Adt7461ConfigureSampleInterval(
                pPrivData, OdmProtected, pSetting);

        default:        // unsupported parameter
            *pSetting = ODM_TMON_PARAMETER_UNSPECIFIED;
            return NV_TRUE;
    }

    // Common processing for temperature limits configuration
    if ((OdmProtected) ||
        ((*pSetting) == ODM_TMON_PARAMETER_UNSPECIFIED))
    {
        // Read ADT7461 register and convert data to current parameter value
        if(!Adt7461ReadReg(pPrivData, pReg, &Data))
            return NV_FALSE;

        *pSetting = ADT7461_T_DATA_TO_VALUE(ExtRange, Data);
    }
    else
    {
        // Clip target setting to temperature range 
        if ((*pSetting) > ADT7461_T_RANGE_LIMIT_HIGH(ExtRange))
            *pSetting = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange);
        else if ((*pSetting) < ADT7461_T_RANGE_LIMIT_LOW(ExtRange))
            *pSetting = ADT7461_T_RANGE_LIMIT_LOW(ExtRange);

        // Convert new configuration setting and write to ADT7461 register
        Data = ADT7461_T_VALUE_TO_DATA(ExtRange, *pSetting);
        if(!Adt7461WriteReg(pPrivData, pReg, Data))
            return NV_FALSE;
    }
    return NV_TRUE;
}
예제 #5
0
NvBool Adt7461Init(NvOdmTmonDeviceHandle hTmon)
{
    NvU8 Data;
    NvBool ExtRange;
    NvU32 i = 0;
    NvU32 I2cInstance = 0;
    NvOdmIoModule I2cModule = NvOdmIoModule_Num;    // Inavlid module
    const ADT7461RegisterInfo* pReg = NULL;
    ADT7461PrivData* pPrivData = NULL;
    
    NV_ASSERT(hTmon && hTmon->pConn && hTmon->pConn->AddressList);
    
    // Allocate and clear priavte data
    pPrivData = (ADT7461PrivData*) NvOdmOsAlloc(sizeof(ADT7461PrivData));
    if (pPrivData == NULL)
    {
        NVODM_ADT7461_PRINTF(("ADT7461: Error Allocating PrivData. \n"));
        return NV_FALSE;
    }
    NvOdmOsMemset(pPrivData, 0, sizeof(ADT7461PrivData));
    hTmon->pPrivate = pPrivData;

    // Register for PMU services
    pPrivData->hOdmPmuSevice = NvOdmServicesPmuOpen();
    if (pPrivData->hOdmPmuSevice == NULL)
    {
        NVODM_ADT7461_PRINTF(("ADT7461: Error Open PMU service. \n"));
        goto fail;
    }

    // Register for GPIO services
    pPrivData->hGpio = NvOdmGpioOpen();
    if (pPrivData->hOdmPmuSevice == NULL)
    {
        NVODM_ADT7461_PRINTF(("ADT7461: Error Open GPIO service. \n"));
        goto fail;
    }

    /*
     * Parse connectivity data: turn On power to the device, acquire I2C
     * interface and GPIO interrupt (optional); map device channels to
     * thermal zones
     */
    for (i = 0; i < hTmon->pConn->NumAddress; i ++)
    {
        const NvOdmIoAddress* pIoAddress = &hTmon->pConn->AddressList[i];
        if (pIoAddress->Interface == NvOdmIoModule_I2c_Pmu)
        {
            I2cModule   = NvOdmIoModule_I2c_Pmu;
            I2cInstance = pIoAddress->Instance;
            NV_ASSERT(pIoAddress->Address != 0);
            pPrivData->DeviceI2cAddr = pIoAddress->Address;
        }
        else if (pIoAddress->Interface == NvOdmIoModule_Tsense)
        {
            NV_ASSERT(pIoAddress->Instance < NvOdmTmonZoneID_Num);
            NV_ASSERT(pIoAddress->Address < ADT7461ChannelID_Num);
            pPrivData->ConnectivityMap[pIoAddress->Instance] =
                pIoAddress->Address;
        }
        else if (pIoAddress->Interface == NvOdmIoModule_Vdd)
        {
            NvU32 usec = 0;
            NvU32 RailAddress = pIoAddress->Address;
            NvOdmServicesPmuVddRailCapabilities RailCapabilities;
            NvOdmServicesPmuGetCapabilities(
                pPrivData->hOdmPmuSevice, RailAddress, &RailCapabilities);
            NvOdmServicesPmuSetVoltage(pPrivData->hOdmPmuSevice, RailAddress,
                              RailCapabilities.requestMilliVolts, &usec);
            NvOdmOsWaitUS(usec + (ADT7461_POWERUP_DELAY_MS * 1000));
        }
        else if (pIoAddress->Interface == NvOdmIoModule_Gpio)
        {
            NvU32 port = pIoAddress->Instance;
            NvU32 pin = pIoAddress->Address;
            pPrivData->hGpioPin = NvOdmGpioAcquirePinHandle(
                pPrivData->hGpio, port, pin);
        }

    }
    NV_ASSERT(I2cModule == NvOdmIoModule_I2c_Pmu);
    pPrivData->hOdmI2C = NvOdmI2cOpen(I2cModule, I2cInstance);
    if (pPrivData->hOdmI2C == NULL)
    {
        NVODM_ADT7461_PRINTF(("ADT7461: Error Open I2C device. \n"));     
        goto fail;
    }

    /*
     * Initialize device info and configuration. Force standby mode to avoid
     * glitch on shutdown comparator output when temperature range and/or
     * comparator limit is changing during initialization. The Adt7461Run()
     * call from the hal that follows initialization will switch device to
     * run mode and re-start temperature monitoring (note that out of limit
     * interrupt is always masked during and after initialization)
     */
    pPrivData->pDeviceInfo = &s_Adt7461Info;
    pPrivData->ShadowRegPtr = ADT7461_INVALID_ADDR;

    pReg = &pPrivData->pDeviceInfo->Config;
    if (!Adt7461ReadReg(pPrivData, pReg, &Data))
        goto fail;
    if ((Data & ADT7461ConfigBits_ExtendedRange) !=
        (ADT7461_INITIAL_CONFIG & ADT7461ConfigBits_ExtendedRange))
    {
        // Only switch from standard to extended range is supported
        NV_ASSERT((Data & ADT7461ConfigBits_ExtendedRange) == 0);
        Data |= ADT7461ConfigBits_Standby;
        if(!Adt7461WriteReg(pPrivData, pReg, Data))
            goto fail;
    }
    Data = ADT7461_INITIAL_CONFIG | ADT7461ConfigBits_Standby;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;
    pPrivData->ShadowConfig = Data;
#if PRE_ER_GMT_THERMALSENSOR
    ExtRange = 0; /* not support ADT thermal sensor*/
#else
    ExtRange = ((Data & ADT7461ConfigBits_ExtendedRange) != 0);	
#endif
    // Program shutdown comparators settings
    Data = ADT7461_T_VALUE_TO_DATA(
        ExtRange, ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_VALUE);
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Local].ComparatorLimit;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;

    Data = ADT7461_T_VALUE_TO_DATA(
        ExtRange, ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_VALUE);
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Remote].ComparatorLimit;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;

    // Set interrupt limits to the range boundaries to prevent out of limit
    // interrupt
    Data = ADT7461_T_VALUE_TO_DATA(
        ExtRange, ADT7461_T_RANGE_LIMIT_HIGH(ExtRange)); 
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Local].IntrLimitHigh;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Remote].IntrLimitHigh;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;

    Data = ADT7461_T_VALUE_TO_DATA(
            ExtRange, ADT7461_T_RANGE_LIMIT_LOW(ExtRange));
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Local].IntrLimitLow;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Remote].IntrLimitLow;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;

    // Set initial rate
    Data = ADT7461_INITIAL_RATE_SETTING;  
    pReg = &pPrivData->pDeviceInfo->Rate;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;
    pPrivData->ShadowRate = Data;

    // Set remote channel offset (8-bit 2's complement value for any range)
    Data = ((NvU8)ADT7461_ODM_REMOTE_OFFSET_VALUE);
    pReg = &pPrivData->pDeviceInfo->Channels[
        ADT7461ChannelID_Remote].Toffset;
    if(!Adt7461WriteReg(pPrivData, pReg, Data))
        goto fail;

    // Read ADT7461 status and ARA (clear pending Alert interrupt, if any)
    pReg = &pPrivData->pDeviceInfo->Status;
    if (!Adt7461ReadReg(pPrivData, pReg, &Data))
        goto fail;
    // TODO: check open remote circuit error

    Adt7461ReadAra(pPrivData);

    return NV_TRUE;

fail:
    Adt7461FreePrivData(pPrivData);
    hTmon->pPrivate = NULL;
    return NV_FALSE;
}