示例#1
0
static void Adt7461Isr(void* arg)
{
    NvU8 Data;
    ADT7461PrivData* pPrivData = (ADT7461PrivData*)arg;
    NvOdmInterruptHandler volatile Callback = pPrivData->Callback;
    void* volatile CallbackArg = pPrivData->CallbackArg;
    const ADT7461RegisterInfo* pReg = NULL;

    if (Callback && CallbackArg)
    {
        Callback(CallbackArg);
    }
#if ADT7461_ALERT_DEBOUNCE
    // New range limits set by callback are not guaranteed to take effect
    // before the next temperature conversion is completed, and interrupt
    // can not be cleared until then. Hence, the debounce delay below.
    NvOdmOsSleepMS(s_Adt7461SampleIntervalsMS[pPrivData->ShadowRate] +
                   s_Adt7461ConversionTimesMS[pPrivData->ShadowRate] + 1);
#endif
    // Read status and ARA to finish clearing interrupt after callback
    pReg = &pPrivData->pDeviceInfo->Status;
    (void)Adt7461ReadReg(pPrivData, pReg, &Data);
    Adt7461ReadAra(pPrivData);

    // Re-enable interrupt
    if (pPrivData->hGpioIntr)
        NvOdmGpioInterruptDone(pPrivData->hGpioIntr);
}
NvBool 
Adt7461TemperatureGet(
    NvOdmTmonDeviceHandle hTmon,
    NvOdmTmonZoneID ZoneId,
    NvS32* pDegreesC)
{
    NvU8 Data;
    NvBool ExtRange;
    ADT7461ChannelID ChannelId;
    ADT7461PrivData* pPrivData;
    const ADT7461RegisterInfo* pReg;

    NV_ASSERT(hTmon && hTmon->pPrivate && pDegreesC);
    pPrivData = hTmon->pPrivate;
    ExtRange = ((pPrivData->ShadowConfig &
                 ADT7461ConfigBits_ExtendedRange) != 0);
    ChannelId = pPrivData->ConnectivityMap[ZoneId];
    pReg = &pPrivData->pDeviceInfo->Channels[ChannelId].Tdata;

    if(!Adt7461ReadReg(pPrivData, pReg, &Data))
        return NV_FALSE;

    *pDegreesC = ADT7461_T_DATA_TO_VALUE(ExtRange, Data);
	/*
    NVODM_ADT7461_PRINTF(("Adt7461TemperatureGet ChannelId=%d,ExtRange=%d,Data=%d,ZoneId=%d,t=%d\n",ChannelId,ExtRange,Data,ZoneId,*pDegreesC));

    pReg = &pPrivData->pDeviceInfo->Channels[1].Tdata;

    if(!Adt7461ReadReg(pPrivData, pReg, &Data))
        return NV_FALSE;
    NVODM_ADT7461_PRINTF(("Adt7461TemperatureGet ChannelId=1,Data=%d\n",Data));//*/

    return NV_TRUE;
}
示例#3
0
static NvBool
Adt7461ConfigureSampleInterval(
    ADT7461PrivData* pPrivData,
    NvBool OdmProtected,
    NvS32* pTargetMs)
{
    NvU8 i;
    NvS32 Delta;
    const ADT7461RegisterInfo* pReg = &pPrivData->pDeviceInfo->Rate;

    if (OdmProtected ||
        ((*pTargetMs) == ODM_TMON_PARAMETER_UNSPECIFIED))
    {
        // Read ADT7461 rate register (fail the call if returned data
        // does not make sense)
        if(!Adt7461ReadReg(pPrivData, pReg, &i))
            return NV_FALSE;
        if (i >= NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS))
            return NV_FALSE;
    }
    else
    {
        // Find and set the best floor approximation of the target sample
        // interval. Note the descending order of sample intervals array.
        for (i = 0; i < NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS); i++)
        {
            Delta = (*pTargetMs) - s_Adt7461SampleIntervalsMS[i];
            if(Delta >= 0)
                break;
        }
        if (i == NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS))
            i--;    // min interval is the best we can do

        if(!Adt7461WriteReg(pPrivData, pReg, i))
            return NV_FALSE;
        pPrivData->ShadowRate = i;
    }
    *pTargetMs = s_Adt7461SampleIntervalsMS[i];
    return NV_TRUE;
}
示例#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 
Adt7461TemperatureGet(
    NvOdmTmonDeviceHandle hTmon,
    NvOdmTmonZoneID ZoneId,
    NvS32* pDegreesC)
{
    NvU8 Data;
    NvBool ExtRange;
    ADT7461ChannelID ChannelId;
    ADT7461PrivData* pPrivData;
    const ADT7461RegisterInfo* pReg;
#if (DEBUG_THERMALSENSOR || CONFIG_TEGRA_TMON_PROC)
	ADT7461RegisterInfo reg;
	int i;
#endif

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

    if(!Adt7461ReadReg(pPrivData, pReg, &Data))
        return NV_FALSE;

    *pDegreesC = ADT7461_T_DATA_TO_VALUE(ExtRange, Data);

#if CONFIG_TEGRA_TMON_PROC
	reg.RdAddr = pReg->RdAddr - 1;	/* local temperature register address */
	reg.WrAddr = pReg->WrAddr - 1;

	if(!Adt7461ReadReg(pPrivData, &reg, &Data))
		return NV_FALSE;
       /* export temperature to /proc/localtmon */
	localTemperatureC = (NvS32)ADT7461_T_DATA_TO_VALUE(ExtRange, Data);
	   
#endif

#if DEBUG_THERMALSENSOR
	printk("ChannelId:0x%x\n", ChannelId);	
	printk("Temperature Data register pReg:0x%x\n", pReg);
	printk("Temperature *pDegreesC:0x%x\n", *pDegreesC);
	i = 0 ; 
	reg.RdAddr = pReg->RdAddr - 1;
	reg.WrAddr = pReg->WrAddr - 1;
	while(i < 40 ){
		if(!Adt7461ReadReg(pPrivData, &reg, &Data))
			return NV_FALSE;
		printk("register pReg:0x%x\n", reg.RdAddr);
		printk("Data:0x%x, %d\n", ADT7461_T_DATA_TO_VALUE(ExtRange, Data), (NvS32)ADT7461_T_DATA_TO_VALUE(ExtRange, Data));
		i++;
		reg.RdAddr++;
	}
#endif

    return NV_TRUE;
}
示例#6
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;
}