summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/odm_kit/adaptations/tmon
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-05-14 10:36:33 -0700
committerGary King <gking@nvidia.com>2010-05-14 20:04:06 -0700
commit106de33bf7f410bade659e110a5a7b187b46b8b2 (patch)
tree4d8231dc38fb3c05b6ccb911ff1e3b840d1d444b /arch/arm/mach-tegra/odm_kit/adaptations/tmon
parente0426ba3077eae7e326c56487f34719f9638ddb5 (diff)
[ARM/tegra] add NvRm, ODM services, ODM kit for harmony & whistler
add power rail support to GPIO driver Change-Id: I45d4c1110a635047d68fb14f3e72a28f99acbe1b
Diffstat (limited to 'arch/arm/mach-tegra/odm_kit/adaptations/tmon')
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile11
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile13
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c934
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h199
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h58
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h203
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c304
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h86
8 files changed, 1808 insertions, 0 deletions
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
+ * <b>NVIDIA Tegra ODM Kit:
+ * Abstraction layer stub for Temperature Monitor adaptations</b>
+ */
+
+#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