From 106de33bf7f410bade659e110a5a7b187b46b8b2 Mon Sep 17 00:00:00 2001 From: Gary King Date: Fri, 14 May 2010 10:36:33 -0700 Subject: [ARM/tegra] add NvRm, ODM services, ODM kit for harmony & whistler add power rail support to GPIO driver Change-Id: I45d4c1110a635047d68fb14f3e72a28f99acbe1b --- .../mach-tegra/odm_kit/adaptations/tmon/Makefile | 11 + .../odm_kit/adaptations/tmon/adt7461/Makefile | 13 + .../adaptations/tmon/adt7461/nvodm_tmon_adt7461.c | 934 +++++++++++++++++++++ .../adaptations/tmon/adt7461/nvodm_tmon_adt7461.h | 199 +++++ .../tmon/adt7461/nvodm_tmon_adt7461_channel.h | 58 ++ .../tmon/adt7461/nvodm_tmon_adt7461_reg.h | 203 +++++ .../mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c | 304 +++++++ .../mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h | 86 ++ 8 files changed, 1808 insertions(+) create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c create mode 100644 arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h (limited to 'arch/arm/mach-tegra/odm_kit/adaptations/tmon') diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile new file mode 100644 index 000000000000..d2245a6505fa --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile @@ -0,0 +1,11 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +obj-y += tmon_hal.o +obj-y += adt7461/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile new file mode 100644 index 000000000000..03f222cbeee4 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile @@ -0,0 +1,13 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/tmon +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461 + +obj-y += nvodm_tmon_adt7461.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c new file mode 100644 index 000000000000..dc76869f6dec --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "nvodm_tmon_adt7461.h" +#include "tmon_hal.h" + +// TODO: Always Disable before check-in +// Always debug module: 0=disable, 1=enable +#define NV_ADT7461_DEBUG (0) + +#if (NV_DEBUG || NV_ADT7461_DEBUG) +#define NVODM_ADT7461_PRINTF(x) NvOdmOsDebugPrintf x +#else +#define NVODM_ADT7461_PRINTF(x) +#endif + +#define ADT7461_ALERT_DEBOUNCE (1) + +// ADT7461 Descrriptor +static const ADT7461Info s_Adt7461Info = +{ + // TMON device conversion channels + { + // Invalid channel + {0}, + + // Local channel + { + ADT7461ChannelID_Local, + { + ADT7461_ODM_LOCAL_RATE_PROTECTED, + ADT7461_ODM_LOCAL_INTR_LIMITS_PROTECTED, + ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_PROTECTED + }, + { + ADT7461_LOCAL_INTR_LIMIT_HIGH_RD_ADDR, + ADT7461_LOCAL_INTR_LIMIT_HIGH_WR_ADDR, + }, + { + ADT7461_LOCAL_INTR_LIMIT_LOW_RD_ADDR, + ADT7461_LOCAL_INTR_LIMIT_LOW_WR_ADDR, + }, + { + ADT7461_LOCAL_COMPARATOR_LIMIT_ADDR, + ADT7461_LOCAL_COMPARATOR_LIMIT_ADDR, + }, + { + ADT7461_INVALID_ADDR, // Local offset does not exist + ADT7461_INVALID_ADDR, + }, + { + ADT7461_LOCAL_TDATA_RD_ADDR, + ADT7461_INVALID_ADDR, + }, + }, + + // Remote channel + { + ADT7461ChannelID_Remote, + { + ADT7461_ODM_REMOTE_RATE_PROTECTED, + ADT7461_ODM_REMOTE_INTR_LIMITS_PROTECTED, + ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_PROTECTED + }, + { + ADT7461_REMOTE_INTR_LIMIT_HIGH_RD_ADDR, + ADT7461_REMOTE_INTR_LIMIT_HIGH_WR_ADDR, + }, + { + ADT7461_REMOTE_INTR_LIMIT_LOW_RD_ADDR, + ADT7461_REMOTE_INTR_LIMIT_LOW_WR_ADDR, + }, + { + ADT7461_REMOTE_COMPARATOR_LIMIT_ADDR, + ADT7461_REMOTE_COMPARATOR_LIMIT_ADDR, + }, + { + ADT7461_REMOTE_TOFFSET_ADDR, + ADT7461_REMOTE_TOFFSET_ADDR, + }, + { + ADT7461_REMOTE_TDATA_RD_ADDR, + ADT7461_INVALID_ADDR, + }, + } + }, + + // TMON device common status/control registers + { + ADT7461_STATUS_RD_ADDR, + ADT7461_INVALID_ADDR, + }, + { + ADT7461_CONFIG_RD_ADDR, + ADT7461_CONFIG_WR_ADDR, + }, + { + ADT7461_RATE_RD_ADDR, + ADT7461_RATE_WR_ADDR, + }, + { + ADT7461_INVALID_ADDR, + ADT7461_ONE_SHOT_WR_ADDR, + }, + { + ADT7461_COMPARATOR_HYSTERESIS_ADDR, + ADT7461_COMPARATOR_HYSTERESIS_ADDR, + }, + { + ADT7461_INTR_CNT_DELAY_ADDR, + ADT7461_INTR_CNT_DELAY_ADDR, + }, +}; + +// ADT7461 sample intervals +static const NvS32 s_Adt7461SampleIntervalsMS[] = +{ + ADT7461_SAMPLE_INTERVALS_MS +}; + +// ADT7461 converison times +static const NvS32 s_Adt7461ConversionTimesMS[] = +{ + ADT7461_CONVERSION_TIME_MS +}; + +NV_CT_ASSERT(NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS) == + NV_ARRAY_SIZE(s_Adt7461ConversionTimesMS)); + +/*****************************************************************************/ + +#define ADT7461_T_DATA_TO_VALUE(ExtRange, data) \ + ( (ExtRange) ? \ + ((NvS32)((NvU32)(data) - ADT7461_RANGE_EXTENDED_DATA_OFFSET)) : \ + ((NvS32)((NvS8)data)) \ + ) + +#define ADT7461_T_VALUE_TO_DATA(ExtRange, val) \ + ( (ExtRange) ? \ + ((NvU8)((NvU32)(val) + ADT7461_RANGE_EXTENDED_DATA_OFFSET)) : \ + ((NvU8)(val)) \ + ) + +#define ADT7461_T_RANGE_LIMIT_HIGH(ExtRange) \ + ( (ExtRange) ? \ + ADT7461_RANGE_EXTENDED_LIMIT_HIGH : \ + ADT7461_RANGE_STANDARD_LIMIT_HIGH \ + ) + +#define ADT7461_T_RANGE_LIMIT_LOW(ExtRange) \ + ( (ExtRange) ? \ + ADT7461_RANGE_EXTENDED_LIMIT_LOW : \ + ADT7461_RANGE_STANDARD_LIMIT_LOW \ + ) + +/*****************************************************************************/ + +static NvBool +Adt7461WriteReg( + ADT7461PrivData* pPrivData, + const ADT7461RegisterInfo* pReg, + NvU8 Data) +{ + NvU32 i; + NvU8 WriteBuffer[2]; + NvOdmI2cStatus status; + NvOdmI2cTransactionInfo TransactionInfo; + + NV_ASSERT(pPrivData && pReg); + NV_ASSERT(pReg->WrAddr != ADT7461_INVALID_ADDR); + + for (i = 0; i < ADT7461_I2C_RETRY_CNT; i++) + { + WriteBuffer[0] = pReg->WrAddr; + WriteBuffer[1] = Data; + + TransactionInfo.Address = pPrivData->DeviceI2cAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(pPrivData->hOdmI2C, &TransactionInfo, 1, + ADT7461_I2C_SPEED_KHZ, ADT7461_I2C_TIMEOUT_MS); + if (status == NvOdmI2cStatus_Success) + break; + } + + switch (status) + { + case NvOdmI2cStatus_Success: + pPrivData->ShadowRegPtr = pReg->WrAddr; + return NV_TRUE; + + case NvOdmI2cStatus_Timeout: + NVODM_ADT7461_PRINTF(("ADT7461: WriteReg Timeout\n")); + return NV_FALSE; + + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODM_ADT7461_PRINTF(("ADT7461: WriteReg SlaveNotFound\n")); + return NV_FALSE; + } +} + +static NvBool +Adt7461ReadReg( + ADT7461PrivData* pPrivData, + const ADT7461RegisterInfo* pReg, + NvU8* pData) +{ + NvU32 i; + NvU8 Buffer = 0; + NvOdmI2cStatus status; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + NV_ASSERT(pPrivData && pReg && pData); + NV_ASSERT(pReg->RdAddr != ADT7461_INVALID_ADDR); + + // TODO: possible optimization - is shadow pointer matches register + // address, just send one read transaction (can be done only if Read/Wr + // Reg routines are serialized). + + for (i = 0; i < ADT7461_I2C_RETRY_CNT; i++) + { + Buffer = pReg->RdAddr; + + TransactionInfo[0].Address = pPrivData->DeviceI2cAddr; + TransactionInfo[0].Buf = &Buffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + + TransactionInfo[1].Address = (pPrivData->DeviceI2cAddr | 0x1); + TransactionInfo[1].Buf = &Buffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + status = NvOdmI2cTransaction(pPrivData->hOdmI2C, &TransactionInfo[0], 2, + ADT7461_I2C_SPEED_KHZ, ADT7461_I2C_TIMEOUT_MS); + if (status == NvOdmI2cStatus_Success) + break; + } + + switch (status) + { + case NvOdmI2cStatus_Success: + pPrivData->ShadowRegPtr = pReg->RdAddr; + *pData = Buffer; + return NV_TRUE; + + case NvOdmI2cStatus_Timeout: + NVODM_ADT7461_PRINTF(("ADT7461: ReadReg Timeout\n")); + return NV_FALSE; + + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODM_ADT7461_PRINTF(("ADT7461: ReadReg SlaveNotFound\n")); + return NV_FALSE; + } +} + +static void Adt7461ReadAra(ADT7461PrivData* pPrivData) +{ + NvU32 i; + NvU8 Buffer = 0; + NvOdmI2cStatus status; + NvOdmI2cTransactionInfo TransactionInfo; + + NV_ASSERT(pPrivData); + + for (i = 0; i < ADT7461_ARA_RETRY_CNT; i++) + { + TransactionInfo.Address = (ADT7461_ARA | 0x1); + TransactionInfo.Buf = &Buffer; + TransactionInfo.Flags = 0; + TransactionInfo.NumBytes = 1; + + status = NvOdmI2cTransaction(pPrivData->hOdmI2C, &TransactionInfo, 1, + ADT7461_I2C_SPEED_KHZ, ADT7461_I2C_TIMEOUT_MS); + if ((status == NvOdmI2cStatus_SlaveNotFound) || // False alarm + ((status == NvOdmI2cStatus_Success) && + ((Buffer & 0xFE) == (NvU8)pPrivData->DeviceI2cAddr)) // Cleared ARA + ) + break; + } +} + +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; +} + +/*****************************************************************************/ + +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); +} + +static void Adt7461FreePrivData(ADT7461PrivData* pPrivData) +{ + if (pPrivData) + { + if (pPrivData->hGpioIntr) + { + NvOdmGpioInterruptUnregister( + pPrivData->hGpio, pPrivData->hGpioPin, pPrivData->hGpioIntr); + } + NvOdmI2cClose(pPrivData->hOdmI2C); + NvOdmGpioReleasePinHandle(pPrivData->hGpio, pPrivData->hGpioPin); + NvOdmGpioClose(pPrivData->hGpio); + NvOdmServicesPmuClose(pPrivData->hOdmPmuSevice); + NvOdmOsFree(pPrivData); + } +} + +/*****************************************************************************/ + +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 = {0}; + 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; + ExtRange = ((Data & ADT7461ConfigBits_ExtendedRange) != 0); + + // 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; +} + +void Adt7461Deinit(NvOdmTmonDeviceHandle hTmon) +{ + if (hTmon && hTmon->pPrivate) + { + ADT7461PrivData* pPrivData = hTmon->pPrivate; + (void)Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, + ADT7461_INITIAL_CONFIG); //leave device in default configuration + // with power rail ON (forever) + Adt7461FreePrivData(pPrivData); + hTmon->pPrivate = NULL; + } +} + +/*****************************************************************************/ + +NvBool Adt7461Run(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId) +{ + NvU8 Data; + NvBool IsRunning; + ADT7461PrivData* pPrivData; + + NV_ASSERT(hTmon && hTmon->pPrivate); + pPrivData = hTmon->pPrivate; + IsRunning = (pPrivData->ShadowConfig & ADT7461ConfigBits_Standby) == 0; + + if (!IsRunning) + { + Data = pPrivData->ShadowConfig & (~ADT7461ConfigBits_Standby); + if(!Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + return NV_FALSE; + pPrivData->ShadowConfig = Data; + } + pPrivData->RunRefCount++; + return NV_TRUE; +} + +NvBool Adt7461Stop(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId) +{ + NvU8 Data; + NvBool IsRunning; + ADT7461PrivData* pPrivData; + + NV_ASSERT(hTmon && hTmon->pPrivate); + pPrivData = hTmon->pPrivate; + IsRunning = (pPrivData->ShadowConfig & ADT7461ConfigBits_Standby) == 0; + + if (ADT7461_ODM_STANDBY_ENABLED && + IsRunning && (pPrivData->RunRefCount == 1)) + { + Data = pPrivData->ShadowConfig | ADT7461ConfigBits_Standby; + if(!Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + return NV_FALSE; + pPrivData->ShadowConfig = Data; + } + if (pPrivData->RunRefCount != 0) + { + pPrivData->RunRefCount--; + return NV_TRUE; + } + NV_ASSERT(!"RunRefCount balance failed"); + NVODM_ADT7461_PRINTF(("ADT7461: RunRefCount balance failed. \n")); + return NV_FALSE; +} + +/*****************************************************************************/ +// ADT7461 aborts and restarts conversion cycle when temperature is read +// (actually on any I2C access for that matter, but other accesses are rare). +// TODO: add time stamps and implement refresh policy to make sure that +// frequent temperature reads would not stall the conversion forever. + +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); + return NV_TRUE; +} + +/*****************************************************************************/ + +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; +} + +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; + ExtRange = ((pPrivData->ShadowConfig & + ADT7461ConfigBits_ExtendedRange) != 0); + 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); +} + +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; + ExtRange = ((pPrivData->ShadowConfig & + ADT7461ConfigBits_ExtendedRange) != 0); + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + + switch (ParamId) + { + case NvOdmTmonConfigParam_IntrLimitHigh: + pReg = &pChannel->IntrLimitHigh; + OdmProtected = pChannel->ChannelPolicy.IntrLimitsOdmProtected; + break; + + case NvOdmTmonConfigParam_IntrLimitLow: + pReg = &pChannel->IntrLimitLow; + OdmProtected = pChannel->ChannelPolicy.IntrLimitsOdmProtected; + break; + + case NvOdmTmonConfigParam_HwLimitCrit: + 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; +} + +/*****************************************************************************/ + +NvOdmTmonIntrHandle +Adt7461IntrRegister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmInterruptHandler Callback, + void* CallbackArg) +{ + NvU8 Data; + ADT7461PrivData* pPrivData; + const ADT7461ChannelInfo* pChannel; + NvOdmServicesGpioIntrHandle hGpioIntr = NULL; + + NV_ASSERT(hTmon && hTmon->pPrivate && Callback && CallbackArg); + pPrivData = hTmon->pPrivate; + + // No registration, if no GPIO pin available or interrupt already registred + if (!pPrivData->hGpioPin || pPrivData->hGpioIntr) + return NULL; + + // No registration for other than remote channel + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + if (pChannel->ChannelId != ADT7461ChannelID_Remote) + return NULL; + + // Register GPIO interrupt (will be enabled at SoC IC, but still disabled + // at ADT7461 device) + pPrivData->Callback = Callback; + pPrivData->CallbackArg = CallbackArg; + if (!NvOdmGpioInterruptRegister( + pPrivData->hGpio, &hGpioIntr, pPrivData->hGpioPin, + ADT7461_ODM_INTR_POLARITY, Adt7461Isr, (void *)pPrivData, 0)) + { + pPrivData->Callback = NULL; + pPrivData->CallbackArg = NULL; + return NULL; + } + NV_ASSERT(hGpioIntr); + pPrivData->hGpioIntr = hGpioIntr; + + // Finally enable ADT7461 device interrupt output (interrupt may or may + // not be generated depending on temperature and limt settings). + Data = pPrivData->ShadowConfig & (~ADT7461ConfigBits_IntrDisabled); + if(!Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + { + NvOdmGpioInterruptUnregister( + pPrivData->hGpio, pPrivData->hGpioPin, hGpioIntr); + pPrivData->Callback = NULL; + pPrivData->CallbackArg = NULL; + pPrivData->hGpioIntr = NULL; + return NULL; + } + pPrivData->ShadowConfig = Data; + + return (NvOdmTmonIntrHandle)hGpioIntr; +} + +void +Adt7461IntrUnregister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonIntrHandle hIntr) +{ + NvU8 Data; + ADT7461PrivData* pPrivData; + const ADT7461ChannelInfo* pChannel; + + // Ignore invalid handles + if(!hIntr || !hTmon || !hTmon->pPrivate) + return; + + pPrivData = hTmon->pPrivate; + if (hIntr != ((NvOdmTmonIntrHandle)pPrivData->hGpioIntr)) + return; + + // Ignore any channel other than remote + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + if (pChannel->ChannelId != ADT7461ChannelID_Remote) + return; + + // Disable ADT7461 interrupt output + Data = pPrivData->ShadowConfig | ADT7461ConfigBits_IntrDisabled; + if(Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + pPrivData->ShadowConfig = Data; + + // Unregister GPIO interrupt, clear callbacks and handle + NvOdmGpioInterruptUnregister( + pPrivData->hGpio, pPrivData->hGpioPin, pPrivData->hGpioIntr); + + pPrivData->Callback = NULL; + pPrivData->CallbackArg = NULL; + pPrivData->hGpioIntr = NULL; +} + +/*****************************************************************************/ + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h new file mode 100644 index 000000000000..ffe4bf15dbec --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_TMON_ADT7461_H +#define INCLUDED_NVODM_TMON_ADT7461_H + +#include "nvodm_tmon.h" +#include "nvodm_tmon_adt7461_reg.h" +#include "nvodm_tmon_adt7461_channel.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct ADT7461RegisterInfoRec +{ + NvU8 RdAddr; // Invalid if WO + NvU8 WrAddr; // Invalid if RO +} ADT7461RegisterInfo; + +typedef struct ADT7461ChannelOdmPolicyRec +{ + NvBool RateOdmProtected; + NvBool IntrLimitsOdmProtected; + NvBool HwLimitCritOdmProtected; +} ADT7461ChannelOdmPolicy; + +typedef struct ADT7461ChannelInfoRec +{ + // TMON device conversion channel ID + ADT7461ChannelID ChannelId; + + // ODM channel policy + ADT7461ChannelOdmPolicy ChannelPolicy; + + // Alert Interrupt limits registers + ADT7461RegisterInfo IntrLimitHigh; + ADT7461RegisterInfo IntrLimitLow; + + // Thermal comparator limit register + ADT7461RegisterInfo ComparatorLimit; + + // Temperature measurement offset + ADT7461RegisterInfo Toffset; + + // Temperature Data register + ADT7461RegisterInfo Tdata; +} ADT7461ChannelInfo; + +typedef struct ADT7461InfoRec +{ + // TMON device conversion channels + ADT7461ChannelInfo Channels[ADT7461ChannelID_Num]; + + // Chip status register + ADT7461RegisterInfo Status; + + // Common configration controls + ADT7461RegisterInfo Config; + + // Common conversion rate + ADT7461RegisterInfo Rate; + + // One-shot trigger register + ADT7461RegisterInfo OneShot; + + // Common comparator hysteresis + ADT7461RegisterInfo ComparatorHysteresis; + + // Number of consecutive limit violation before + // interrupt is generated + ADT7461RegisterInfo IntrCntDelay; +} ADT7461Info; + +typedef struct ADT7461PrivDataRec +{ + // ADT7461 device registers descriptors + const ADT7461Info* pDeviceInfo; + + // ADT7461 I2C device Address + NvU32 DeviceI2cAddr; + + // The handle to the I2C controller + NvOdmServicesI2cHandle hOdmI2C; + + // The odm pmu service handle + NvOdmServicesPmuHandle hOdmPmuSevice; + + // Zone => Channel map + ADT7461ChannelID ConnectivityMap[NvOdmTmonZoneID_Num]; + + // ADR7461 run mode reference count + NvU32 RunRefCount; + + // Shadow of ADT7461 internal configuration register + NvU8 ShadowConfig; + + // Shadow of ADT7461 internal rate settings + NvU8 ShadowRate; + + // Shadow of ADT7461 internal address pointer + NvU8 ShadowRegPtr; + + // The odm GPIO service handle + NvOdmServicesGpioHandle hGpio; + + // SoC GPIO dedicated for ADT7461 out of limit interrupt + NvOdmGpioPinHandle hGpioPin; + + // The ADT7461 interrupt handle + NvOdmServicesGpioIntrHandle hGpioIntr; + + // The ADT7461 interrupt callback + NvOdmInterruptHandler Callback; + + // The ADT7461 interrupt callback context + void* CallbackArg; +} ADT7461PrivData; + +NvBool Adt7461Init(NvOdmTmonDeviceHandle hTmon); +void Adt7461Deinit(NvOdmTmonDeviceHandle hTmon); +NvBool Adt7461Run(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId); +NvBool Adt7461Stop(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId); + +NvBool +Adt7461TemperatureGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvS32* pDegreesC); + +void +Adt7461CapabilitiesGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonCapabilities* pCaps); + +void +Adt7461ParameterCapsGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonConfigParam ParamId, + NvOdmTmonParameterCaps* pCaps); + +NvBool +Adt7461ParameterConfig( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonConfigParam ParamId, + NvS32* pSetting); + +NvOdmTmonIntrHandle +Adt7461IntrRegister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmInterruptHandler Callback, + void* arg); + +void +Adt7461IntrUnregister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonIntrHandle hIntr); + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADT7461_H + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h new file mode 100644 index 000000000000..8d9f9bb22d95 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_TMON_ADT7461_CHANNEL_H +#define INCLUDED_NVODM_TMON_ADT7461_CHANNEL_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef enum +{ + // Local sensor + ADT7461ChannelID_Local = 1, + + // Remote sensor + ADT7461ChannelID_Remote, + + ADT7461ChannelID_Num, + ADT7461ChannelID_Force32 = 0x7FFFFFFFUL +} ADT7461ChannelID; + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADT7461_CHANNEL_H + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h new file mode 100644 index 000000000000..e0e930e79fe7 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_TMON_ADT7461_REG_H +#define INCLUDED_NVODM_TMON_ADT7461_REG_H + +#include "nvodm_tmon_adt7461.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// ODM policy: use ADT7461 extended=1 (standard=0) range +#define ADT7461_ODM_EXTENDED_RANGE (1) + +// ODM policy: enable=1 (disable=0) ADT7461 standby mode +#define ADT7461_ODM_STANDBY_ENABLED (0) + +// ODM policy: protect=1 (not=0) thermal limits from being overwritten by API +#define ADT7461_ODM_LOCAL_INTR_LIMITS_PROTECTED (1) +#define ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_PROTECTED (1) + +#define ADT7461_ODM_REMOTE_INTR_LIMITS_PROTECTED (0) +#define ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_PROTECTED (1) + +// ODM policy: protect=1 (not=0) sample rate from being overwritten by API +#define ADT7461_ODM_LOCAL_RATE_PROTECTED (1) +#define ADT7461_ODM_REMOTE_RATE_PROTECTED (0) + +// ODM policy: comparator limit values for critical shutdown (in degrees C) +#define ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_VALUE (120L) +#define ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_VALUE (115L) + +// ODM ADT7461 remote channel measurement offset +#define ADT7461_ODM_REMOTE_OFFSET_VALUE (6L) + +// ODM ADT7461 interrupt polarity +#define ADT7461_ODM_INTR_POLARITY (NvOdmGpioPinMode_InputInterruptLow) + +// ADT7461 Register POR settings +#define ADT7461_LOCAL_TDATA_POR (0x00) +#define ADT7461_REMOTE_TDATA_POR (0x00) +// #define ADT7461_STATUS_POR unknown +#define ADT7461_CONFIG_POR (0x00) +#define ADT7461_RATE_POR (0x08) +#define ADT7461_LOCAL_INTR_LIMIT_HIGH_POR (0x55) +#define ADT7461_LOCAL_INTR_LIMIT_LOW_POR (0x00) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_POR (0x55) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_POR (0x00) +// #define ADT7461_ONE_SHOT_POR unknown +#define ADT7461_REMOTE_TDATA_FRACTION_POR (0x00) +#define ADT7461_REMOTE_TOFFSET_POR (0x00) +#define ADT7461_REMOTE_TOFFSET_FRACTION_POR (0x00) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_FRACTION_POR (0x00) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_FRACTION_POR (0x00) +#define ADT7461_REMOTE_COMPARATOR_LIMIT_POR (0x55) +#define ADT7461_LOCAL_COMPARATOR_LIMIT_POR (0x55) +#define ADT7461_COMPARATOR_HYSTERESIS_POR (0x0A) +#define ADT7461_INTR_CNT_DELAY_POR (0x01) +#define ADT7461_CHIP_ID_POR (0x41) +#define ADT7461_CHIP_REV_POR (0x51) + + +// ADT7461 Register Addresses +#define ADT7461_LOCAL_TDATA_RD_ADDR (0x00) +#define ADT7461_REMOTE_TDATA_RD_ADDR (0x01) + +#define ADT7461_STATUS_RD_ADDR (0x02) +#define ADT7461_CONFIG_RD_ADDR (0x03) +#define ADT7461_CONFIG_WR_ADDR (0x09) +#define ADT7461_RATE_RD_ADDR (0x04) +#define ADT7461_RATE_WR_ADDR (0x0A) + +#define ADT7461_LOCAL_INTR_LIMIT_HIGH_RD_ADDR (0x05) +#define ADT7461_LOCAL_INTR_LIMIT_HIGH_WR_ADDR (0x0B) +#define ADT7461_LOCAL_INTR_LIMIT_LOW_RD_ADDR (0x06) +#define ADT7461_LOCAL_INTR_LIMIT_LOW_WR_ADDR (0x0C) + +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_RD_ADDR (0x07) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_WR_ADDR (0x0D) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_RD_ADDR (0x08) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_WR_ADDR (0x0E) + +#define ADT7461_ONE_SHOT_WR_ADDR (0x0F) + +#define ADT7461_REMOTE_TDATA_FRACTION_RD_ADDR (0x10) +#define ADT7461_REMOTE_TOFFSET_ADDR (0x11) +#define ADT7461_REMOTE_TOFFSET_FRACTION_ADDR (0x12) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_FRACTION_ADDR (0x13) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_FRACTION_ADDR (0x14) + +#define ADT7461_REMOTE_COMPARATOR_LIMIT_ADDR (0x19) +#define ADT7461_LOCAL_COMPARATOR_LIMIT_ADDR (0x20) +#define ADT7461_COMPARATOR_HYSTERESIS_ADDR (0x21) + +#define ADT7461_INTR_CNT_DELAY_ADDR (0x22) +#define ADT7461_CHIP_ID_RD_ADDR (0xFE) +#define ADT7461_CHIP_REV_RD_ADDR (0xFF) + +#define ADT7461_INVALID_ADDR (0xF0) + + +// ADT7461 conversion range (signed values) +#define ADT7461_RANGE_STANDARD_LIMIT_HIGH (127L) +#define ADT7461_RANGE_STANDARD_LIMIT_LOW (0L) +#define ADT7461_RANGE_EXTENDED_LIMIT_HIGH (150L) +#define ADT7461_RANGE_EXTENDED_LIMIT_LOW (-64L) + +// ADT7461 data reading offsets (unsigned data) +#define ADT7461_RANGE_STANDARD_DATA_OFFSET (0UL) +#define ADT7461_RANGE_EXTENDED_DATA_OFFSET (64UL) + + +// ADT7461 Configuration Register bitfields +typedef enum +{ + // If set - extended temperature range (-55C to 150C); data offset 64C + // If cleared - stnadard temperature range (0C to 127C); data offset 0 + ADT7461ConfigBits_ExtendedRange = (0x1 << 2), + + // If set - interrupt output works as second auto cleared comparator + // If cleared - interrupt output works as level out of limit interrupt, + // cleared by (a) reading status and (b) alert response protocol over I2C + ADT7461ConfigBits_IntrAutoClear = (0x1 << 5), + + // If set - put device in stanby mode + // If cleared - put device in running mode + ADT7461ConfigBits_Standby = (0x1 << 6), + + // If set - interrupt from device is disabled + // If cleared - interrupt from device is enabled + ADT7461ConfigBits_IntrDisabled = (0x1 << 7), +} ADT7461ConfigBits; + +// ADT7461 initial configuration set by adaptation: +// ADT7461 THERM1 output is dedicated for critical h/w shutdown, and ADT7461 +// ALERT/THERM2 output is always configured as out of limit ALERT interrupt. +// Monitor is in running mode, in the range selected per ODM policy. +#define ADT7461_INITIAL_CONFIG \ + ((ADT7461ConfigBits_IntrDisabled) | \ + (ADT7461_ODM_EXTENDED_RANGE ? ADT7461ConfigBits_ExtendedRange : 0)) + + +// ADT7461 sample intervals and conversion time limits rounded to the nearest +// milliseconds, in descending order indexed by rate register DATA settings + +// RATE: 1/16 1/8 1/4 1/2 1 2 4 8 16 32 64 (1/s) +// DATA: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A +#define ADT7461_SAMPLE_INTERVALS_MS \ + 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 63, 31, 16 +#define ADT7461_CONVERSION_TIME_MS \ + 115, 115, 115, 115, 115, 115, 115, 115, 13, 13, 13 + +#define ADT7461_INITIAL_RATE_SETTING (0x0A) + + +// ADT7461 I2C (SMBus) clock speed, bus timeout, retries, and fixed +// Alert Response Address (ARA). +#define ADT7461_I2C_SPEED_KHZ (400) +#define ADT7461_I2C_TIMEOUT_MS (500) +#define ADT7461_I2C_RETRY_CNT (2) +#define ADT7461_ARA_RETRY_CNT (4) +#define ADT7461_ARA (0x18) + +// ADT7461 power up delay (TODO: get spec for delay from vendor) +#define ADT7461_POWERUP_DELAY_MS (5) + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADT7461_REG_H + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c new file mode 100644 index 000000000000..acabf8492c35 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "tmon_hal.h" +#include "adt7461/nvodm_tmon_adt7461.h" + +/* + * TMON adaptation is a singleton linked directly with NVRM only. + * Thread safety for TMON APIs is provided by NVRM as well. + */ + + +// Temperature Monitors suported under hal +#define TMON_ADT7461_ID (NV_ODM_GUID('a','d','t','7','4','6','1',' ')) + +#define TMON_ZONE_PSEUDOHANDLE(h, z) \ + ( (NvOdmTmonDeviceHandle)((((NvU32)(h)) << 16) | (z)) ) +#define TMON_PSEUDOHANDLE_ZONE(h) ( ((NvU32)(h)) & 0xFFFF ) + +/*****************************************************************************/ + +static NvOdmTmonDevice* +TmonGetInstance(NvOdmTmonZoneID ZoneId) +{ + static NvOdmTmonDevice s_TmonArray[NvOdmTmonZoneID_Num]; + static NvOdmTmonDevice* s_TmonMap[NvOdmTmonZoneID_Num]; + static NvBool s_Initialized = NV_FALSE; + + NvU32 i, j; + NvOdmTmonDevice* pTmon = NULL; + const NvOdmPeripheralConnectivity* pConn = NULL; + + // Check for invalid zone + if (ZoneId == 0) + return NULL; + + if (!s_Initialized) + { + NvOdmOsMemset(s_TmonArray, 0, sizeof(s_TmonArray)); + NvOdmOsMemset(s_TmonMap, 0, sizeof(s_TmonMap)); + s_Initialized = NV_TRUE; + i = 0; // allocation index + + pConn = NvOdmPeripheralGetGuid(TMON_ADT7461_ID); + if (pConn) + { + pTmon = &s_TmonArray[i++]; + pTmon->pfnInit = Adt7461Init; + pTmon->pfnDeinit = Adt7461Deinit; + pTmon->pfnTemperatureGet = Adt7461TemperatureGet; + pTmon->pfnCapabilitiesGet = Adt7461CapabilitiesGet; + pTmon->pfnParameterCapsGet = Adt7461ParameterCapsGet; + pTmon->pfnParameterConfig = Adt7461ParameterConfig; + pTmon->pfnRun = Adt7461Run; + pTmon->pfnStop = Adt7461Stop; + pTmon->pfnIntrRegister = Adt7461IntrRegister; + pTmon->pfnIntrUnregister = Adt7461IntrUnregister; + pTmon->pConn = pConn; + pTmon->RefCount = 0; + pTmon->pPrivate = NULL; + + // Fill in Zones => TMON devices map + NV_ASSERT(pConn->AddressList); + for (j = 0; j < pConn->NumAddress; j++) + { + if (pConn->AddressList[j].Interface == NvOdmIoModule_Tsense) + s_TmonMap[pConn->AddressList[j].Instance] = pTmon; + } + } + } + // Find TMON instance for the given zone + if(ZoneId < NvOdmTmonZoneID_Num) + { + pTmon = s_TmonMap[ZoneId]; + if (pTmon && pTmon->pConn) + return pTmon; + } + return NULL; +} + +/*****************************************************************************/ + +NvOdmTmonDeviceHandle +NvOdmTmonDeviceOpen(NvOdmTmonZoneID ZoneId) +{ + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon) + { + NV_ASSERT(pTmon->pfnInit && pTmon->pfnRun); + // Init TMON device on the 1st open + if (pTmon->RefCount == 0) + { + if (!pTmon->pfnInit(pTmon)) + return NULL; + } + // Make sure targeted zone is monitored + if (pTmon->pfnRun(pTmon, ZoneId)) + { + pTmon->RefCount++; + return TMON_ZONE_PSEUDOHANDLE(pTmon, ZoneId); + } + } + return NULL; +} + +void NvOdmTmonDeviceClose(NvOdmTmonDeviceHandle hTmon) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon) + { + NV_ASSERT(pTmon->pfnDeinit && pTmon->pfnStop); + (void)pTmon->pfnStop(pTmon, ZoneId); + if (pTmon->RefCount == 1) + pTmon->pfnDeinit(pTmon); + + if (pTmon->RefCount) + { + pTmon->RefCount--; + return; + } + NV_ASSERT(!"RefCount balance failed"); + } +} + +NvBool NvOdmTmonSuspend(NvOdmTmonDeviceHandle hTmon) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnStop); + if (pTmon->pfnStop(pTmon, ZoneId)) + return NV_TRUE; + } + return NV_FALSE; +} + +NvBool NvOdmTmonResume(NvOdmTmonDeviceHandle hTmon) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnRun); + if (pTmon->pfnRun(pTmon, ZoneId)) + return NV_TRUE; + } + return NV_FALSE; +} + +/*****************************************************************************/ + +NvBool +NvOdmTmonTemperatureGet( + NvOdmTmonDeviceHandle hTmon, + NvS32* pDegreesC) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnTemperatureGet); + if (pTmon->pfnTemperatureGet(pTmon, ZoneId, pDegreesC)) + return NV_TRUE; + } + return NV_FALSE; +} + +/*****************************************************************************/ + +void +NvOdmTmonCapabilitiesGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonCapabilities* pCaps) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnCapabilitiesGet); + pTmon->pfnCapabilitiesGet(pTmon, ZoneId, pCaps); + } + else if (pCaps) + { + NvOdmOsMemset(pCaps, 0, sizeof(NvOdmTmonCapabilities)); + pCaps->Tmax = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->Tmin = ODM_TMON_PARAMETER_UNSPECIFIED; + } +} + +void +NvOdmTmonParameterCapsGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonConfigParam ParamId, + NvOdmTmonParameterCaps* pCaps) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnParameterCapsGet); + pTmon->pfnParameterCapsGet(pTmon, ZoneId, ParamId, pCaps); + } + else if (pCaps) + { + NvOdmOsMemset(pCaps, 0, sizeof(NvOdmTmonParameterCaps)); + pCaps->MaxValue = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->MinValue = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->OdmProtected = NV_TRUE; + } +} + +NvBool +NvOdmTmonParameterConfig( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonConfigParam ParamId, + NvS32* pSetting) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnParameterConfig); + if (pTmon->pfnParameterConfig(pTmon, ZoneId, ParamId, pSetting)) + return NV_TRUE; + } + return NV_FALSE; +} + +/*****************************************************************************/ + +NvOdmTmonIntrHandle +NvOdmTmonIntrRegister( + NvOdmTmonDeviceHandle hTmon, + NvOdmInterruptHandler Callback, + void* CallbackArg) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + NvOdmTmonIntrHandle hIntr = NULL; + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnIntrRegister); + hIntr = pTmon->pfnIntrRegister( + pTmon, ZoneId, Callback, CallbackArg); + } + return hIntr; +} + +void +NvOdmTmonIntrUnregister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonIntrHandle hIntr) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnIntrUnregister); + pTmon->pfnIntrUnregister(pTmon, ZoneId, hIntr); + } +} + +/*****************************************************************************/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h new file mode 100644 index 000000000000..5e5e1141c584 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * NVIDIA Tegra ODM Kit: + * Abstraction layer stub for Temperature Monitor adaptations + */ + +#ifndef INCLUDED_NVODM_TMON_ADAPTATION_HAL_H +#define INCLUDED_NVODM_TMON_ADAPTATION_HAL_H + +#include "nvcommon.h" +#include "nvodm_tmon.h" +#include "nvodm_query_discovery.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef NvBool (*pfnTmonInit)(NvOdmTmonDeviceHandle); +typedef void (*pfnTmonDeinit)(NvOdmTmonDeviceHandle); +typedef NvBool (*pfnTmonTemperatureGet)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvS32*); +typedef void (*pfnTmonCapabilitiesGet)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonCapabilities*); +typedef void (*pfnTmonParameterCapsGet) + (NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonConfigParam, NvOdmTmonParameterCaps*); +typedef NvBool (*pfnTmonParameterConfig)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonConfigParam, NvS32*); +typedef NvBool (*pfnTmonRun)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID); +typedef NvBool (*pfnTmonStop)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID); +typedef NvOdmTmonIntrHandle + (*pfnTmonIntrRegister)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmInterruptHandler, void*); +typedef void (*pfnTmonIntrUnregister)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonIntrHandle); + +typedef struct NvOdmTmonDeviceRec +{ + pfnTmonInit pfnInit; + pfnTmonDeinit pfnDeinit; + pfnTmonTemperatureGet pfnTemperatureGet; + pfnTmonCapabilitiesGet pfnCapabilitiesGet; + pfnTmonParameterCapsGet pfnParameterCapsGet; + pfnTmonParameterConfig pfnParameterConfig; + pfnTmonRun pfnRun; + pfnTmonStop pfnStop; + pfnTmonIntrRegister pfnIntrRegister; + pfnTmonIntrUnregister pfnIntrUnregister; + + const NvOdmPeripheralConnectivity* pConn; + NvU32 RefCount; + void *pPrivate; +} NvOdmTmonDevice; + +#ifdef __cplusplus +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADAPTATION_HAL_H -- cgit v1.2.3