summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilson Chen <wichen@nvidia.com>2010-05-27 22:51:56 +0800
committerJanne Hellsten <jhellsten@nvidia.com>2010-06-01 03:13:32 -0700
commit5645d492c7ddb74c23f10b4daa479b333069516b (patch)
tree2b09819852417c45fdcc42ca5c9ce625bfa1f3e3
parente5fb37702feb532b4e58660d9719c76fa7d8a79a (diff)
tegra: [RTC Alarm Clock] implement TI pmu tps6586x by PMIC (pwr_int) pin
Bug 631330 Bug 690351 Bug 690993 Tested on Ap20/Harmony. Change-Id: Id29c5fc8f5078ad4cb3aa1e43d0440c21ddd1a96 Reviewed-on: http://git-master/r/1725 Reviewed-by: Janne Hellsten <jhellsten@nvidia.com> Tested-by: Janne Hellsten <jhellsten@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/include/nvodm_pmu.h24
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c28
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h4
-rwxr-xr-xarch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c11
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h2
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c30
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c118
-rw-r--r--arch/arm/mach-tegra/odm_kit/query/harmony/nvodm_query.c4
-rw-r--r--drivers/rtc/rtc-tegra-odm.c89
9 files changed, 297 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/include/nvodm_pmu.h b/arch/arm/mach-tegra/include/nvodm_pmu.h
index 2b768edbe5b4..b20f536ebb82 100644
--- a/arch/arm/mach-tegra/include/nvodm_pmu.h
+++ b/arch/arm/mach-tegra/include/nvodm_pmu.h
@@ -449,6 +449,30 @@ NvOdmPmuWriteRtc(
NvU32 Count);
/**
+ * Gets the alarm count in seconds of the current external RTC (in PMU).
+ *
+ * @param hDevice A handle to the PMU.
+ * @param Count A pointer to where to return the current counter in sec.
+ * @return NV_TRUE if successful, or NV_FALSE otherwise.
+ */
+NvBool
+NvOdmPmuReadAlarm(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32* Count);
+
+/**
+ * Updates alarm count value.
+ *
+ * @param hDevice A handle to the PMU.
+ * @param Count data with which to update the current counter in sec.
+ * @return NV_TRUE if successful, or NV_FALSE otherwise.
+ */
+NvBool
+NvOdmPmuWriteAlarm(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32 Count);
+
+/**
* Returns whether or not the RTC is initialized.
*
* @param hDevice A handle to the PMU.
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c
index ec62ac6c4c17..ffe0b584340d 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c
@@ -70,6 +70,8 @@ GetPmuInstance(NvOdmPmuDeviceHandle hDevice)
Pmu.pfnInterruptHandler = Tps6586xInterruptHandler;
Pmu.pfnReadRtc = Tps6586xReadRtc;
Pmu.pfnWriteRtc = Tps6586xWriteRtc;
+ Pmu.pfnReadAlarm = Tps6586xReadAlarm;
+ Pmu.pfnWriteAlarm = Tps6586xWriteAlarm;
Pmu.pfnIsRtcInitialized = Tps6586xIsRtcInitialized;
}
else if (NvOdmPeripheralGetGuid(NV_ODM_GUID('p','c','f','_','p','m','u','0')))
@@ -89,6 +91,8 @@ GetPmuInstance(NvOdmPmuDeviceHandle hDevice)
Pmu.pfnInterruptHandler = Pcf50626InterruptHandler;
Pmu.pfnReadRtc = Pcf50626RtcCountRead;
Pmu.pfnWriteRtc = Pcf50626RtcCountWrite;
+ Pmu.pfnReadAlarm = NULL;
+ Pmu.pfnWriteAlarm = NULL;
Pmu.pfnIsRtcInitialized = Pcf50626IsRtcInitialized;
Pmu.pPrivate = NULL;
Pmu.Hal = NV_TRUE;
@@ -111,6 +115,8 @@ GetPmuInstance(NvOdmPmuDeviceHandle hDevice)
Pmu.pfnInterruptHandler = Max8907bInterruptHandler;
Pmu.pfnReadRtc = Max8907bRtcCountRead;
Pmu.pfnWriteRtc = Max8907bRtcCountWrite;
+ Pmu.pfnReadAlarm = NULL;
+ Pmu.pfnWriteAlarm = NULL;
Pmu.pfnIsRtcInitialized = Max8907bIsRtcInitialized;
Pmu.pPrivate = NULL;
Pmu.Hal = NV_TRUE;
@@ -341,6 +347,28 @@ NvBool NvOdmPmuWriteRtc(
return NV_FALSE;
}
+NvBool NvOdmPmuReadAlarm(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32 *Count)
+{
+ NvOdmPmuDevice *pmu = GetPmuInstance(hDevice);
+
+ if (pmu && pmu->pfnReadAlarm)
+ return pmu->pfnReadAlarm(pmu, Count);
+ return NV_FALSE;
+}
+
+NvBool NvOdmPmuWriteAlarm(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32 Count)
+{
+ NvOdmPmuDevice *pmu = GetPmuInstance(hDevice);
+
+ if (pmu && pmu->pfnWriteAlarm)
+ return pmu->pfnWriteAlarm(pmu, Count);
+ return NV_FALSE;
+}
+
NvBool
NvOdmPmuIsRtcInitialized(NvOdmPmuDeviceHandle hDevice)
{
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h
index 05cdea828a20..23a02f9bf6a9 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h
@@ -63,6 +63,8 @@ typedef void (*pfnPmuInterruptHandler)(NvOdmPmuDeviceHandle);
typedef NvBool (*pfnPmuReadRtc)(NvOdmPmuDeviceHandle, NvU32*);
typedef NvBool (*pfnPmuWriteRtc)(NvOdmPmuDeviceHandle, NvU32);
typedef NvBool (*pfnPmuIsRtcInitialized)(NvOdmPmuDeviceHandle);
+typedef NvBool (*pfnPmuReadAlarm)(NvOdmPmuDeviceHandle, NvU32*);
+typedef NvBool (*pfnPmuWriteAlarm)(NvOdmPmuDeviceHandle, NvU32);
typedef struct NvOdmPmuDeviceRec
{
@@ -80,6 +82,8 @@ typedef struct NvOdmPmuDeviceRec
pfnPmuInterruptHandler pfnInterruptHandler;
pfnPmuReadRtc pfnReadRtc;
pfnPmuWriteRtc pfnWriteRtc;
+ pfnPmuReadAlarm pfnReadAlarm;
+ pfnPmuWriteAlarm pfnWriteAlarm;
pfnPmuIsRtcInitialized pfnIsRtcInitialized;
void *pPrivate;
NvBool Hal;
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c
index 197a2c227e1d..781a13d448f8 100755
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c
@@ -2030,6 +2030,17 @@ NvBool Tps6586xWriteRtc( NvOdmPmuDeviceHandle hDevice, NvU32 Count)
return (Tps6586xRtcCountWrite(hDevice, Count));
}
+NvBool Tps6586xReadAlarm( NvOdmPmuDeviceHandle hDevice, NvU32 *Count)
+{
+ *Count = 0;
+ return (Tps6586xRtcAlarmCountRead(hDevice, Count));
+}
+
+NvBool Tps6586xWriteAlarm( NvOdmPmuDeviceHandle hDevice, NvU32 Count)
+{
+ return (Tps6586xRtcAlarmCountWrite(hDevice, Count));
+}
+
NvBool Tps6586xIsRtcInitialized( NvOdmPmuDeviceHandle hDevice)
{
return ((Tps6586xRtcWasStartUpFromNoPower(hDevice))? NV_FALSE: NV_TRUE);
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h
index 0c1f4fb2b9af..5fdcd563115b 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h
@@ -94,6 +94,8 @@ NvBool Tps6586xSetChargingCurrent( NvOdmPmuDeviceHandle hDevice, NvOdmPmuChargin
void Tps6586xInterruptHandler( NvOdmPmuDeviceHandle hDevice);
NvBool Tps6586xReadRtc( NvOdmPmuDeviceHandle hDevice, NvU32 *Count);
NvBool Tps6586xWriteRtc( NvOdmPmuDeviceHandle hDevice, NvU32 Count);
+NvBool Tps6586xReadAlarm( NvOdmPmuDeviceHandle hDevice, NvU32 *Count);
+NvBool Tps6586xWriteAlarm( NvOdmPmuDeviceHandle hDevice, NvU32 Count);
NvBool Tps6586xIsRtcInitialized( NvOdmPmuDeviceHandle hDevice);
#if defined(__cplusplus)
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c
index b3ac0b954a4e..f50d120ff386 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c
@@ -37,13 +37,17 @@
#include "nvodm_services.h"
#include "nvodm_pmu_tps6586x_batterycharger.h"
+/* INT_MASK3 */
#define TPS6586X_INT_BATT_INST 0x01
#define TPS6586X_INT_PACK_COLD_DET 0x02
#define TPS6586X_INT_PACK_HOT_DET 0x04
-
-#define TPS6586X_INT_USB_DETECTION 0x04
-#define TPS6586X_INT_AC_DETECTION 0x08
-#define TPS6586X_INT_LOWSYS_DETECTION 0x40
+/* INT_MASK4 */
+#define TPS6586X_INT_ALM2_INST 0x02
+/* INT_MASK5 */
+#define TPS6586X_INT_USB_DETECTION 0x04
+#define TPS6586X_INT_AC_DETECTION 0x08
+#define TPS6586X_INT_ALM1_DETECTION 0x10
+#define TPS6586X_INT_LOWSYS_DETECTION 0x40
NvBool Tps6586xSetupInterrupt(NvOdmPmuDeviceHandle hDevice,
TPS6586xStatus *pmuStatus)
@@ -114,18 +118,25 @@ void Tps6586xInterruptHandler_int(NvOdmPmuDeviceHandle hDevice,
pmuStatus->powerGood |= ((data & 0xFF)<<8);
/* INT_ACK3 */
- /* LOW SYS */
if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB7_INT_ACK3, &data))
{
return;
}
if (data != 0)
{
+ /* ACK_RTCALM1 */
+ if (data&0x01)
+ {
+ /* printk("%s ACK_RTC_ALM_1 detect!!!\n", __func__); */
+ }
+
+ /* ACK_CHGTEMP */
if (data&0x40)
{
pmuStatus->highTemp = NV_TRUE;
}
- if (data&0xc0)
+ /* ACK_ACDET & ACK_USBDET */
+ if (data&0x0C)
{
pmuStatus->mChgPresent = NV_TRUE;
#if !defined(CONFIG_TEGRA_ODM_HARMONY)
@@ -135,13 +146,18 @@ void Tps6586xInterruptHandler_int(NvOdmPmuDeviceHandle hDevice,
}
/* INT_ACK4 */
- /* CHG TEMP */
if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB8_INT_ACK4, &data))
{
return;
}
if (data != 0)
{
+ /* ACK_RTCALM2 */
+ if (data&0x04)
+ {
+ /* printk("%s ACK_RTC_ALM_2 detect!!!\n", __func__); */
+ }
+ /* LOW SYS */
if (data&0x02)
{
pmuStatus->lowBatt = NV_TRUE;
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c
index 889cf2bbc6ff..80942c232c83 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c
@@ -41,9 +41,15 @@
#define OFFSET_BASE_YEAR 1
#if OFFSET_BASE_YEAR
static unsigned long epoch = 2009;
+#define epoch_end 2037L
static unsigned long epoch_sec = 0;
#endif
+#define RTC_LIMITED 1
+
+static NvBool rtc_alarm_active = NV_FALSE; /* RTC_ALARM_ACTIVE */
+static NvBool ALARM1_used = NV_FALSE;
+
static NvBool bRtcNotInitialized = NV_TRUE;
/* Read RTC count register */
@@ -61,8 +67,13 @@ Tps6586xRtcCountRead(
if (Tps6586xRtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized)
{
+#if RTC_LIMITED
+ Tps6586xRtcCountWrite(hDevice, (NvU32)mktime(epoch,1,1,0,0,0));
+ *Count = 0;
+#else /* RTC_LIMITED */
Tps6586xRtcCountWrite(hDevice, 0);
*Count = 0;
+#endif /* RTC_LIMITED */
}
else
{
@@ -81,7 +92,7 @@ Tps6586xRtcCountRead(
// calculate epoch_sec once
if (!epoch_sec)
epoch_sec = mktime(epoch,1,1,0,0,0);
- *Count += epoch_sec;
+ *Count += (NvU32)epoch_sec;
#endif
return NV_TRUE;
@@ -105,11 +116,20 @@ Tps6586xRtcCountWrite(
pr_warning("\n Date being set cannot be earlier than least "
"year=%d. Setting as least year. ", (int)epoch);
// base year seconds count is 0
+#if RTC_LIMITED
+ Count = (NvU32)epoch_sec; //reset RTC count to 2010/01/01 00:00:00
+#else /* RTC_LIMITED */
Count = 0;
+#endif /* RTC_LIMITED */
}
else
Count -= (NvU32)epoch_sec;
-#endif
+#if RTC_LIMITED
+ if (Count > (NvU32)mktime(epoch_end,12,31,23,59,59))
+ Count = (NvU32)epoch_sec; //reset RTC count to 2010/01/01 00:00:00
+#endif /* RTC_LIMITED */
+
+#endif /*OFFSET_BASE_YEAR */
// Switch to 32KHz crystal oscillator
// POR_SRC_SEL=1 and OSC_SRC_SEL=1
@@ -147,7 +167,30 @@ Tps6586xRtcAlarmCountRead(
NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
- return NV_FALSE;
+ NvU32 Counter;
+ NvU32 ReadBuffer[3];
+
+ if ( rtc_alarm_active ) {
+
+ if ( ALARM1_used ) {
+ Tps6586xI2cRead8(hDevice, TPS6586x_RC3_RTC_ALARM1_LO, &ReadBuffer[2]);
+ Tps6586xI2cRead8(hDevice, TPS6586x_RC2_RTC_ALARM1_MID, &ReadBuffer[1]);
+ Tps6586xI2cRead8(hDevice, TPS6586x_RC1_RTC_ALARM1_HI, &ReadBuffer[0]);
+ Counter = (ReadBuffer[0] << 16) + (ReadBuffer[1] << 8) + ReadBuffer[2];
+ *Count = Counter >> 10;
+ } else { //( ALARM1_used )
+ Tps6586xI2cRead8(hDevice, TPS6586x_RC5_RTC_ALARM2_LO, &ReadBuffer[1]);
+ Tps6586xI2cRead8(hDevice, TPS6586x_RC4_RTC_ALARM2_HI, &ReadBuffer[0]);
+ Counter = (ReadBuffer[0]<<8) + ReadBuffer[1];
+ *Count = Counter << 2;
+ } //( ALARM1_used )
+
+ return NV_TRUE;
+
+ } else { // ( rtc_alarm_active )
+ return NV_FALSE;
+ } // ( rtc_alarm_active )
+
}
/* Write RTC alarm count register */
@@ -157,7 +200,74 @@ Tps6586xRtcAlarmCountWrite(
NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
- return NV_FALSE;
+ NvU32 ReadBuffer32;
+ NvU32 Counter;
+ NvU32 temp;
+
+ NvU32 alarm1_start_sec;
+ NvU32 alarm1_end_sec;
+ NvU32 alarm2_start_sec;
+ NvU32 alarm2_end_sec;
+
+ alarm1_start_sec = 0; //2^(10-10)-1 = 2^0-1 = 0
+ alarm1_end_sec = 16384; //2^(24-10) = 2^14 =16384 sec = 273 min 4 sec = 4 hr 33min 4 sec
+
+ alarm2_start_sec = 3; //2^(12-10)-1 = 2^2-1 = 3
+ alarm2_end_sec = 262144; //2^(28-10)= 2^18 = 262144sec = 4369min 4sec = 72hr 49min 4sec = 3day 0hr 49min 4sec
+
+ if ( Count < alarm2_end_sec && Count > alarm1_start_sec ) {
+ rtc_alarm_active = NV_TRUE;
+ if ( Count < alarm1_end_sec )
+ ALARM1_used = NV_TRUE;
+ else
+ ALARM1_used = NV_FALSE;
+ }
+
+ if ( rtc_alarm_active ) {
+
+ if ( ALARM1_used ) {
+
+ if (Count >= alarm1_end_sec || Count <= alarm1_start_sec)
+ return NV_FALSE;
+
+ Tps6586xI2cRead32(hDevice, TPS6586x_RC6_RTC_COUNT4, &ReadBuffer32);
+ Tps6586xI2cRead8(hDevice, TPS6586x_RCA_RTC_COUNT0, &temp);
+ ReadBuffer32 &= 0x0000ffff; //bit[23:08]
+ Counter = (ReadBuffer32<<8)+ temp;
+ Counter += Count << 10;
+
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RC3_RTC_ALARM1_LO, ((Counter >> 0) & 0xFF));
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RC2_RTC_ALARM1_MID, ((Counter >> 8) & 0xFF));
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RC1_RTC_ALARM1_HI, ((Counter >> 16) & 0xFF));
+ //FIXME:
+ Tps6586xI2cRead8(hDevice, TPS6586x_RB4_INT_MASK5, &temp);
+ temp = temp & 0xEF;
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RB4_INT_MASK5, temp);
+
+ } else { //( ALARM1_used )
+
+ if (Count >= alarm2_end_sec || Count <= alarm2_start_sec)
+ return NV_FALSE;
+
+ Tps6586xI2cRead32(hDevice, TPS6586x_RC6_RTC_COUNT4, &ReadBuffer32);
+ Tps6586xI2cRead8(hDevice, TPS6586x_RCA_RTC_COUNT0, &temp);
+ ReadBuffer32 &= 0x000ffff0; //bit[27:12]
+ Counter = ReadBuffer32 >> 4;
+ Counter += Count >>2; //(Count*4sec)
+
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RC5_RTC_ALARM2_LO, ((Counter >> 0) & 0xFF));
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RC4_RTC_ALARM2_HI, ((Counter >> 8) & 0xFF));
+ //FIXME:
+ Tps6586xI2cRead8(hDevice, TPS6586x_RB3_INT_MASK4, &temp);
+ temp = temp & 0xFD;
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RB3_INT_MASK4, temp);
+
+ } //( ALARM1_used )
+ return NV_TRUE;
+ } else { // ( rtc_alarm_active )
+ return NV_FALSE;
+ } // ( rtc_alarm_active )
+
}
/* Reads RTC alarm interrupt mask status */
diff --git a/arch/arm/mach-tegra/odm_kit/query/harmony/nvodm_query.c b/arch/arm/mach-tegra/odm_kit/query/harmony/nvodm_query.c
index 5040e7004a77..958efb6d4b55 100644
--- a/arch/arm/mach-tegra/odm_kit/query/harmony/nvodm_query.c
+++ b/arch/arm/mach-tegra/odm_kit/query/harmony/nvodm_query.c
@@ -316,7 +316,7 @@ static NvOdmWakeupPadInfo s_NvOdmWakeupPadInfo[] =
#else
{NV_FALSE, 17, NvOdmWakeupPadPolarity_High},
#endif
- {NV_FALSE, 18, NvOdmWakeupPadPolarity_Low}, // Wake Event 18 - pwr_int (PMIC_INT)
+ {NV_TRUE, 18, NvOdmWakeupPadPolarity_Low}, // Wake Event 18 - pwr_int (PMIC_INT)
{NV_FALSE, 19, NvOdmWakeupPadPolarity_AnyEdge}, // Wake Event 19 - usb_vbus_wakeup[0]
{NV_FALSE, 20, NvOdmWakeupPadPolarity_High}, // Wake Event 20 - usb_vbus_wakeup[1]
{NV_FALSE, 21, NvOdmWakeupPadPolarity_Low}, // Wake Event 21 - usb_iddig[0]
@@ -668,7 +668,7 @@ NvOdmQueryPinAttributes(const NvOdmPinAttrib** pPinAttributes)
NvBool NvOdmQueryGetPmuProperty(NvOdmPmuProperty* pPmuProperty)
{
- pPmuProperty->IrqConnected = NV_FALSE;
+ pPmuProperty->IrqConnected = NV_TRUE;
pPmuProperty->PowerGoodCount = 0x7E7E;
pPmuProperty->IrqPolarity = NvOdmInterruptPolarity_Low;
pPmuProperty->CorePowerReqPolarity = NvOdmCorePowerReqPolarity_Low;
diff --git a/drivers/rtc/rtc-tegra-odm.c b/drivers/rtc/rtc-tegra-odm.c
index a5ff518c5aa6..becfe334cb4a 100644
--- a/drivers/rtc/rtc-tegra-odm.c
+++ b/drivers/rtc/rtc-tegra-odm.c
@@ -33,6 +33,8 @@
#include <nvodm_pmu.h>
+#define PMU_IOCTL_ENABLE 1
+
/* Create a custom rtc structrue and move this to that structure */
static NvOdmPmuDeviceHandle hPmu = NULL;
@@ -71,9 +73,96 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0;
}
+#if (PMU_IOCTL_ENABLE)
+static int tegra_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct rtc_wkalrm wkalrm;
+ NvU32 count = 0;
+
+ switch (cmd) {
+ case RTC_ALM_READ:
+ NvOdmPmuReadAlarm(hPmu, &count);
+ wkalrm.time.tm_hour = count / 3600;
+ wkalrm.time.tm_min = (count - (wkalrm.time.tm_hour * 3600)) / 60;
+ wkalrm.time.tm_sec = (count - (wkalrm.time.tm_min * 60) - (wkalrm.time.tm_hour * 3600) );
+ if (copy_to_user(argp, &count, sizeof(count)))
+ return -EFAULT;
+ break;
+
+ case RTC_ALM_SET:
+ if (copy_from_user(&wkalrm, argp, sizeof(wkalrm)))
+ return -EFAULT;
+ count = wkalrm.time.tm_hour * 3600 + wkalrm.time.tm_min * 60 + wkalrm.time.tm_sec;
+ NvOdmPmuWriteAlarm(hPmu, count);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+
+ struct rtc_time *time = &wkalrm->time;
+
+ NvU32 alarm_sec = 0;
+ NvOdmPmuReadAlarm(hPmu, &alarm_sec);
+
+ rtc_time_to_tm(alarm_sec, time);
+
+ return 0;
+}
+
+static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct rtc_time *time = &wkalrm->time;
+ NvU32 now;
+ NvU32 alarm_sec;
+ struct rtc_time now_time;
+
+ pr_debug("wkalrm->enabled = %d\n", wkalrm->enabled);
+ if (wkalrm->enabled == 0)
+ return 0;
+
+ if (!NvOdmPmuReadRtc(hPmu, &now)) {
+ pr_debug("NvOdmPmuReadRtc failed\n");
+ return -1;
+ }
+
+ rtc_time_to_tm(now, &now_time);
+ pr_debug( "read now_time %02d:%02d:%02d %02d/%02d/%04d\n",
+ now_time.tm_hour, now_time.tm_min, now_time.tm_sec,
+ now_time.tm_mon + 1, now_time.tm_mday, now_time.tm_year + 1900);
+
+ pr_debug("write alarm_time %02d:%02d:%02d %02d/%02d/%04d\n",
+ time->tm_hour, time->tm_min, time->tm_sec,
+ time->tm_mon+1, time->tm_mday, time->tm_yday+1900);
+
+ alarm_sec = (NvU32)mktime(now_time.tm_year + 1900, time->tm_mon+1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ if (alarm_sec < now)
+ alarm_sec = (NvU32)mktime(now_time.tm_year + 1901, time->tm_mon+1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+
+ pr_debug("alarm_sec = %u\n", alarm_sec);
+
+ NvOdmPmuWriteAlarm(hPmu, alarm_sec-now);
+
+ return 0;
+}
+#endif
+
static struct rtc_class_ops tegra_rtc_ops = {
.read_time = tegra_rtc_read_time,
.set_time = tegra_rtc_set_time,
+#if (PMU_IOCTL_ENABLE)
+ .ioctl = tegra_rtc_ioctl,
+ .read_alarm = tegra_rtc_read_alarm,
+ .set_alarm = tegra_rtc_set_alarm,
+#endif
};
static int __init tegra_rtc_probe(struct platform_device *pdev)