summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorBitan Biswas <bbiswas@nvidia.com>2010-01-14 13:56:12 +0530
committerBitan Biswas <bbiswas@nvidia.com>2010-01-27 21:59:45 +0530
commit6f22dfd98979b723b6021a3b882e6944cfac79b6 (patch)
tree713f7c0b8110c967b010e306e07c948ba2db3a83 /arch
parent98b49ac44d0ce8be847f6272d97dedfd166b6a6d (diff)
tegra2 rtc: date/time non-persistent on boards
Multi-stage Changes are as follows: Change1: 1) TPS6586x PMU RTC(harmony) cannot store more than 34 years duration. Hence, RTC driver has been modified to use year 2009 as reference instead of the year 1970(used in linux by default). Change in tps6586x rtc implementation. Issue was Fixed in Bug 621031 earlier and checked into p4 by modifying tegra rtc driver. We are using a different approach now by only modifying tps6586x rtc driver. This way rtc drivers for other PMU like max8907b which can store as much 9999 years in RTC do not need to change. 2) MAX8907B PMU RTC(whistler) driver was not storing day/month/year data earlier. Further, on every boot the RTC was being cleared. Fixed this in file max8907b_rtc.c Implementation specific to linux as uses library functions: mktime and rtc_time_to_tm 3) MAX8907B PMU I2C read API implementation was not reading 4th byte. Changed this as DD, MM, YY1, YY2 information is being read now. Changed max8907b_i2c.c Further, changes are as follows: Change2: 1) TPS6586x PMU RTC(harmony) driver modified to select crystal oscillator as source for RTC. After this change find that RTC counts even when harmony is powered off. 2) MAX8907B PMU RTC(whistler) driver modified to incorporate review comments a) renamed macro SHIFT_TO_2009 as OFFSET_BASE_YEAR b) used a macro for BCD to decimal conversion for better readability. Change set 1 was committed but was reverted because of bugs 645312 and 645286. Further tests showed that if the date is set before testing gallery app the issue is not seen. Trying to re-submit reverted checkin for change1 along with change2 as a new change. Change3: a) decimal to bcd expresssion converted to macro b) corrected spelling Bug 625990 : [Firefly2/Harmony] Date & Time is not persisting after reboot Tested on : Harmony + whistler. Date/time persists. Note: Whistler rechargable battery needs to be charged to 2.4V for RTC data to persist. Harmony has non-rechargable battery. Change-Id: Icc543261096ee4c89cc1e394e2b3868ac370f8e9
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c177
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c195
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c87
3 files changed, 297 insertions, 162 deletions
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c
index 6e61ddd95135..0f7a09446876 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c
@@ -37,6 +37,9 @@
#define MAX8907B_I2C_SPEED_KHZ 400
#define MAX8907B_I2C_RETRY_CNT 2
+// Maximum i2c transaction count
+#define MAX_TRANSACTION_COUNT 5
+
NvBool Max8907bI2cWrite8(
NvOdmPmuDeviceHandle hDevice,
NvU8 Addr,
@@ -45,14 +48,14 @@ NvBool Max8907bI2cWrite8(
NvU32 i;
NvU8 WriteBuffer[2];
NvOdmI2cTransactionInfo TransactionInfo;
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
WriteBuffer[0] = Addr & 0xFF; // PMU offset
WriteBuffer[1] = Data & 0xFF; // written data
-
+
TransactionInfo.Address = hPmu->DeviceAddr;
TransactionInfo.Buf = &WriteBuffer[0];
TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
@@ -69,12 +72,12 @@ NvBool Max8907bI2cWrite8(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -86,28 +89,30 @@ NvBool Max8907bI2cRead8(
{
NvU32 i;
NvU8 ReadBuffer = 0;
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo[2];
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
+ NvU32 TransactionCount = 0;
// Write the PMU offset
ReadBuffer = Addr & 0xFF;
- TransactionInfo[0].Address = hPmu->DeviceAddr;
- TransactionInfo[0].Buf = &ReadBuffer;
- TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
- TransactionInfo[0].NumBytes = 1;
+ TransactionInfo[TransactionCount].Address = hPmu->DeviceAddr;
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer;
+ TransactionInfo[TransactionCount].Flags =
+ NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
- TransactionInfo[1].Address = (hPmu->DeviceAddr | 0x1);
- TransactionInfo[1].Buf = &ReadBuffer;
- TransactionInfo[1].Flags = 0;
- TransactionInfo[1].NumBytes = 1;
+ TransactionInfo[TransactionCount].Address = (hPmu->DeviceAddr | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer;
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
// Read data from PMU at the specified offset
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2,
- MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0],
+ TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
{
@@ -120,12 +125,12 @@ NvBool Max8907bI2cRead8(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -137,13 +142,13 @@ NvBool Max8907bI2cWrite32(
{
NvU32 i;
NvU8 WriteBuffer[5];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo;
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
- WriteBuffer[0] = (NvU8)(Addr & 0xFF);
+ WriteBuffer[0] = (NvU8)(Addr & 0xFF);
WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF);
WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF);
WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF);
@@ -154,7 +159,7 @@ NvBool Max8907bI2cWrite32(
TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
TransactionInfo.NumBytes = 5;
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
@@ -165,12 +170,12 @@ NvBool Max8907bI2cWrite32(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -182,30 +187,32 @@ NvBool Max8907bI2cRead32(
{
NvU32 i;
NvU8 ReadBuffer[5];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo[2];
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
+ NvU32 TransactionCount = 0;
ReadBuffer[0] = Addr & 0xFF;
- TransactionInfo[0].Address = hPmu->DeviceAddr;
- TransactionInfo[0].Buf = &ReadBuffer[0];
- TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
- TransactionInfo[0].NumBytes = 1;
+ TransactionInfo[TransactionCount].Address = hPmu->DeviceAddr;
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags =
+ NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
- TransactionInfo[1].Address = (hPmu->DeviceAddr | 0x1);
- TransactionInfo[1].Buf = &ReadBuffer[0];
- TransactionInfo[1].Flags = 0;
- TransactionInfo[1].NumBytes = 4;
+ TransactionInfo[TransactionCount].Address = (hPmu->DeviceAddr | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 4;
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2,
- MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0],
+ TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
{
- *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
+ *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
(ReadBuffer[2] << 8) | ReadBuffer[3];
return NV_TRUE;
@@ -216,12 +223,12 @@ NvBool Max8907bI2cRead32(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -233,13 +240,14 @@ NvBool Max8907bRtcI2cWriteTime(
{
NvU32 i;
NvU8 WriteBuffer[5];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo;
+ NVODMPMU_PRINTF(("\n RTC I2C write: Addr=0x%x, Data=0x%x ", Addr, Data));
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
- WriteBuffer[0] = (NvU8)(Addr & 0xFF);
+ WriteBuffer[0] = (NvU8)(Addr & 0xFF);
WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF);
WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF);
WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF);
@@ -250,7 +258,7 @@ NvBool Max8907bRtcI2cWriteTime(
TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
TransactionInfo.NumBytes = 5;
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
@@ -261,12 +269,12 @@ NvBool Max8907bRtcI2cWriteTime(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -278,46 +286,63 @@ NvBool Max8907bRtcI2cReadTime(
{
NvU32 i;
NvU8 ReadBuffer[4];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
- NvOdmI2cTransactionInfo TransactionInfo[4];
+ NvOdmI2cTransactionInfo TransactionInfo[MAX_TRANSACTION_COUNT];
+ NVODMPMU_PRINTF(("\n RTC I2C read: Addr=0x%x ", Addr));
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
- ReadBuffer[0] = Addr++ & 0xFF;
- ReadBuffer[1] = Addr++ & 0xFF;
- ReadBuffer[2] = Addr++ & 0xFF;
- ReadBuffer[3] = 0;
-
- TransactionInfo[0].Address = MAX8907B_RTC_SLAVE_ADDR;
- TransactionInfo[0].Buf = &ReadBuffer[0];
- TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
- TransactionInfo[0].NumBytes = 1;
-
- // Seconds
- TransactionInfo[1].Address = (MAX8907B_RTC_SLAVE_ADDR | 0x1);
- TransactionInfo[1].Buf = &ReadBuffer[0];
- TransactionInfo[1].Flags = 0;
- TransactionInfo[1].NumBytes = 1;
-
- // Minutes
- TransactionInfo[2].Address = (MAX8907B_RTC_SLAVE_ADDR | 0x1);
- TransactionInfo[2].Buf = &ReadBuffer[1];
- TransactionInfo[2].Flags = 0;
- TransactionInfo[2].NumBytes = 1;
-
- // Hours
- TransactionInfo[3].Address = (MAX8907B_RTC_SLAVE_ADDR | 0x1);
- TransactionInfo[3].Buf = &ReadBuffer[2];
- TransactionInfo[3].Flags = 0;
- TransactionInfo[3].NumBytes = 1;
-
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 4,
- MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ NvU32 TransactionCount = 0;
+ ReadBuffer[0] = Addr & 0xFF;
+ TransactionInfo[TransactionCount].Address = MAX8907B_RTC_SLAVE_ADDR;
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags =
+ NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Seconds / day
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Minutes / month
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[1];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Hours / YY1
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[2];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Weekday / YY2
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[3];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0],
+ TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
{
- *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
+ *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
(ReadBuffer[2] << 8) | ReadBuffer[3];
return NV_TRUE;
@@ -328,12 +353,12 @@ NvBool Max8907bRtcI2cReadTime(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
index 0c179efdf21c..88bfa06fa940 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
@@ -30,151 +30,224 @@
*
*/
+#include <linux/time.h>
+#include <linux/rtc.h>
#include "max8907b.h"
#include "max8907b_rtc.h"
#include "max8907b_i2c.h"
#include "max8907b_reg.h"
-/**
+/**
* The Maxim 8907B does not have an RTC that simply counts
* seconds from some time t0 (as defined by the OS API).
* Instead, this RTC contains several BCD (Binary Coded Decimal)
* registers, including: seconds, minutes, hours, days, day of
* week, date, etc... These registers account for leap year and
* the various days of the month as well.
-*
+*
* Since the OS interpretation of seconds to a particular
* date/time from some OS-defined t0 is unknown at this level of
* the implementation, it is not possible to translate the given
* seconds into these registers (at least, not without a
* dependency on some OS-specific information).
-*
-* Therefore, this implementation contains a static variable
-* (RtcDays) which is derived from the number of seconds given
-* when Max8907bRtcCountWrite() is called. The seconds, minutes
-* and hours are then programmed to the RTC and used to keep
-* track of the current time within the day.
-*
-* TO DO: Increment the day whenever it rolls over (requires
-* handling an interrupt at midnight each day).
+*
*/
#define MAX8907B_SECONDS_PER_DAY (60*60*24)
#define MAX8907B_SECONDS_PER_HOUR (60*60)
#define MAX8907B_SECONDS_PER_MINUTE (60)
+#define LINUX_RTC_BASE_YEAR 1900
+
+/* Macro for conversion of BCD number to decimal format */
+#define BCD_TO_DECIMAL(BCD) \
+ ((((BCD) & 0xF0) >> 4) * 10 + ((BCD) & 0xF))
+/* Macro for conversion of decimal number to BCD format */
+#define DECIMAL_TO_BCD(DEC) \
+ ((((DEC) / 10) << 4) | ((DEC) % 10))
+
static NvBool bRtcNotInitialized = NV_TRUE;
-static NvU32 RtcDays = 0;
-NvBool
+NvBool
Max8907bRtcCountRead(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
NvU32 data = 0;
NvU32 BcdHours, BcdMinutes, BcdSeconds;
NvU32 Hours, Minutes, Seconds;
+ NvU32 BcdDD, BcdMM, BcdYY1, BcdYY2;
+ NvU32 DD, MM, YY1, YY2, YYYY;
+#if NV_DEBUG
+ struct rtc_time tm;
+#endif
- if (Max8907bRtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized)
- {
- Max8907bRtcCountWrite(hDevice, 0);
- *Count = 0;
- }
- else
+ *Count = 0;
+ // Read seconds, minute, hour and weekday data from RTC registers
+ if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_SEC, &data))
{
- if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_SEC, &data))
- {
-
- BcdHours = (data >> 8) & 0xFF;
- BcdMinutes = (data >> 16) & 0xFF;
- BcdSeconds = (data >> 24) & 0xFF;
+ NVODMPMU_PRINTF(("\n Read time data-sec=0x%x ", data));
+ // Extract seconds, minute and hour data from RTC registers read
+ BcdHours = (data >> 8) & 0xFF;
+ BcdMinutes = (data >> 16) & 0xFF;
+ BcdSeconds = (data >> 24) & 0xFF;
- Hours = ((BcdHours & 0xF0)>>4)*10 + (BcdHours & 0xF);
- Minutes = ((BcdMinutes & 0xF0)>>4)*10 + (BcdMinutes & 0xF);
- Seconds = ((BcdSeconds & 0xF0)>>4)*10 + (BcdSeconds & 0xF);
+ // Convert BCD time into decimal values
+ Hours = BCD_TO_DECIMAL(BcdHours);
+ Minutes = BCD_TO_DECIMAL(BcdMinutes);
+ Seconds = BCD_TO_DECIMAL(BcdSeconds);
- *Count = (Hours * MAX8907B_SECONDS_PER_HOUR) +
- (Minutes * MAX8907B_SECONDS_PER_MINUTE) + Seconds;
+ // Read day, month, yy1 and yy2 data from RTC registers
+ if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data))
+ {
+ NVODMPMU_PRINTF(("\n Read time data-year=0x%x ", data));
+ // Extract day, month, yy1 and yy2 data from RTC registers read
+ BcdYY2 = (data & 0xFF);
+ BcdYY1 = (data >> 8) & 0xFF;
+ BcdMM = (data >> 16) & 0xFF;
+ BcdDD = (data >> 24) & 0xFF;
+ // convert bcd day/month/year data to decimal values
+ YY2 = BCD_TO_DECIMAL(BcdYY2);
+ YY1 = BCD_TO_DECIMAL(BcdYY1);
+ YYYY = (YY2 * 100 + YY1) & 0xFFFF;
+ MM = BCD_TO_DECIMAL(BcdMM);
+ DD = BCD_TO_DECIMAL(BcdDD);
+ // get seconds since reference time value given
+ // year, month, day, hour, minutes and seconds
+ // NOTE: Using linux specific API mktime for conversion
+ *Count = mktime(YYYY, (MM + 1), DD, Hours, Minutes, Seconds);
+ NVODMPMU_PRINTF(("\n Rtc read count=0x%x ", *Count));
+ NVODMPMU_PRINTF(("\n mktime: YYYY=%d MM=%d DD=%d Hr=%d Min=%d "
+ "Sec=%d, *Count=0x%x ", YYYY, (MM + 1), DD, Hours, Minutes,
+ Seconds, *Count));
+#if NV_DEBUG
+ // Call to verify that reverse conversion of seconds matches date
+ rtc_time_to_tm(*Count, &tm);
+ // Check if Local_rtc_time_to_tm can return values sent to mktime
+ NVODMPMU_PRINTF(("\n rtc_time_to_tm: YYYY=%d MM=%d DD=%d Hr=%d "
+ "Min=%d Sec=%d, *Count=0x%x ", (tm.tm_year +
+ LINUX_RTC_BASE_YEAR), tm.tm_mon, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec, *Count));
+#endif
}
else
{
- NvOdmOsDebugPrintf("Max8907bRtcCountRead() error. ");
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. "));
return NV_FALSE;
}
}
+ else
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. "));
+ return NV_FALSE;
+ }
+ NVODMPMU_PRINTF(("\n *Count=0x%x ", *Count));
return NV_TRUE;
}
-NvBool
+NvBool
Max8907bRtcAlarmCountRead(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
return NV_FALSE;
}
-NvBool
+NvBool
Max8907bRtcCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
- NvU32 Hours, Minutes, Seconds;
NvU32 BcdHours, BcdMinutes, BcdSeconds;
NvU32 data = 0;
+ NvU8 BcdDD, BcdMM, BcdYY1, BcdYY2;
+ NvU16 YYYY;
+ struct rtc_time tm;
+ NvU32 data1;
- BcdHours = BcdMinutes = BcdSeconds = 0;
-
- RtcDays = Count / MAX8907B_SECONDS_PER_DAY;
+ NVODMPMU_PRINTF(("\n Rtc write count=0x%x ", Count));
+ // convert seconds since reference time into date
+ // NOTE: using linux specific convert function rtc_time_to_tm
+ rtc_time_to_tm(Count, &tm);
+ NVODMPMU_PRINTF(("\n rtc_time_to_tm: YYYY=%d MM=%d DD=%d Hr=%d Min=%d "
+ "Sec=%d, *Count=0x%x ", (tm.tm_year + LINUX_RTC_BASE_YEAR),
+ (tm.tm_mon + 1), tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, Count));
- Hours = (Count % MAX8907B_SECONDS_PER_DAY) / MAX8907B_SECONDS_PER_HOUR;
- Minutes = ((Count % MAX8907B_SECONDS_PER_DAY) % MAX8907B_SECONDS_PER_HOUR) / MAX8907B_SECONDS_PER_MINUTE;
- Seconds = Count % MAX8907B_SECONDS_PER_MINUTE;
-
- BcdHours = (( Hours/10) << 4) | ( Hours%10);
- BcdMinutes = ((Minutes/10) << 4) | (Minutes%10);
- BcdSeconds = ((Seconds/10) << 4) | (Seconds%10);
+ // Convert time to bcd format
+ BcdHours = DECIMAL_TO_BCD(tm.tm_hour);
+ BcdMinutes = DECIMAL_TO_BCD(tm.tm_min);
+ BcdSeconds = DECIMAL_TO_BCD(tm.tm_sec);
data = (BcdSeconds << 24) | (BcdMinutes << 16) | (BcdHours << 8);
+ // write time - seconds, minutes and hours in a day to RTC registers
if (Max8907bRtcI2cWriteTime(hDevice, MAX8907B_RTC_SEC, data))
{
- bRtcNotInitialized = NV_FALSE;
- return NV_TRUE;
+ // set the day, month, year
+ // Assuming we get the days since 1 Jan 1970
+
+ // convert date to bcd format
+ BcdDD = DECIMAL_TO_BCD((NvU8)tm.tm_mday);
+ BcdMM = DECIMAL_TO_BCD((NvU8)tm.tm_mon);
+ YYYY = (NvU16)tm.tm_year + LINUX_RTC_BASE_YEAR;
+ BcdYY1 = DECIMAL_TO_BCD((NvU8)(YYYY % 100));
+ BcdYY2 = DECIMAL_TO_BCD((NvU8)(YYYY / 100));
+ data = (NvU32)((BcdDD << 24) | (BcdMM << 16) | (BcdYY1 << 8) | BcdYY2);
+ // write date - day, month, and year to RTC registers
+ if (!(Max8907bRtcI2cWriteTime(hDevice, MAX8907B_RTC_DATE, data)))
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. "));
+ return NV_FALSE;
+ }
+#if NV_DEBUG
+ // verify that read back values from RTC matches written values
+ if (!(Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data1)))
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. "));
+ return NV_FALSE;
+ }
+ if (data1 == data)
+ {
+ NVODMPMU_PRINTF(("\n Write read Success. "));
+ return NV_TRUE;
+ }
+ else
+ {
+ // return error when read data does not match written data
+ NVODMPMU_PRINTF(("\n Error: write data=0x%x, rd data=0x%x. ", data, data1));
+ return NV_FALSE;
+ }
+#endif
}
else
{
- NvOdmOsDebugPrintf("Max8907bRtcCountWrite() error. ");
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. "));
return NV_FALSE;
}
}
-NvBool
+NvBool
Max8907bRtcAlarmCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
return NV_FALSE;
}
-NvBool
+NvBool
Max8907bRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
{
return NV_FALSE;
}
-NvBool
+NvBool
Max8907bRtcAlarmIntEnable(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvBool Enable)
{
return NV_FALSE;
}
-NvBool
-Max8907bRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice)
-{
- return NV_TRUE;
-}
-
NvBool
Max8907bIsRtcInitialized(NvOdmPmuDeviceHandle hDevice)
{
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 d897eb9f4ee3..889cf2bbc6ff 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
@@ -30,10 +30,20 @@
*
*/
+#include <linux/time.h>
#include "nvodm_pmu_tps6586x_rtc.h"
#include "nvodm_pmu_tps6586x_i2c.h"
#include "tps6586x_reg.h"
+// macro OFFSET_BASE_YEAR if 1, uses epoch as reference year instead of 1970
+// This is because RTC in PMU TPS6586x can store duration of 34 years,
+// else we cannot retain date beyond 2004
+#define OFFSET_BASE_YEAR 1
+#if OFFSET_BASE_YEAR
+static unsigned long epoch = 2009;
+static unsigned long epoch_sec = 0;
+#endif
+
static NvBool bRtcNotInitialized = NV_TRUE;
/* Read RTC count register */
@@ -43,12 +53,12 @@ Tps6586xRtcCountRead(
NvU32* Count)
{
NvU32 ReadBuffer[2];
-
+
// 1) The I2C address pointer must not be left pointing in the range 0xC6 to 0xCA
// 2) The maximum time for the address pointer to be in this range is 1ms
// 3) Always read RTC_ALARM2 in the following order to prevent the address pointer
- // from stopping at 0xC6: RTC_ALARM2_LO, then RTC_ALARM2_HI
-
+ // from stopping at 0xC6: RTC_ALARM2_LO, then RTC_ALARM2_HI
+
if (Tps6586xRtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized)
{
Tps6586xRtcCountWrite(hDevice, 0);
@@ -59,55 +69,82 @@ Tps6586xRtcCountRead(
// The unit of the RTC count is second!!! 1024 tick = 1s.
// Read all 40 bit and right move 10 = Read the hightest 32bit and right move 2
Tps6586xI2cRead32(hDevice, TPS6586x_RC6_RTC_COUNT4, &ReadBuffer[0]);
-
+
Tps6586xI2cRead8(hDevice, TPS6586x_RCA_RTC_COUNT0, &ReadBuffer[1]);
-
+
Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer[1]);
-
+
// return second
*Count = ReadBuffer[0]>>2;
}
-
+#if OFFSET_BASE_YEAR
+ // calculate epoch_sec once
+ if (!epoch_sec)
+ epoch_sec = mktime(epoch,1,1,0,0,0);
+ *Count += epoch_sec;
+#endif
+
return NV_TRUE;
}
/* Write RTC count register */
-NvBool
+NvBool
Tps6586xRtcCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
NvU32 ReadBuffer = 0;
-
+#if OFFSET_BASE_YEAR
+ // calculate epoch_sec once
+ if (!epoch_sec)
+ epoch_sec = mktime(epoch,1,1,0,0,0);
+ if (Count < (NvU32)epoch_sec)
+ {
+ // prevent setting date earlier than 'epoch'
+ 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
+ Count = 0;
+ }
+ else
+ Count -= (NvU32)epoch_sec;
+#endif
+
+ // Switch to 32KHz crystal oscillator
+ // POR_SRC_SEL=1 and OSC_SRC_SEL=1
+ Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer);
+ ReadBuffer = ReadBuffer | 0xC0;
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer);
+
// To enable incrementing of the RTC_COUNT[39:0] from an initial value set by the host,
- // the RTC_ENABLE bit should be written to 1 only after the RTC_OUT voltage reaches
+ // the RTC_ENABLE bit should be written to 1 only after the RTC_OUT voltage reaches
// the operating range
-
+
// Clear RTC_ENABLE before writing RTC_COUNT
Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer);
ReadBuffer = ReadBuffer & 0xDF;
Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer);
-
+
Tps6586xI2cWrite32(hDevice, TPS6586x_RC6_RTC_COUNT4, (Count<<2));
- Tps6586xI2cWrite8(hDevice, TPS6586x_RCA_RTC_COUNT0, 0);
-
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RCA_RTC_COUNT0, 0);
+
// Set RTC_ENABLE after writing RTC_COUNT
Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer);
ReadBuffer = ReadBuffer | 0x20;
Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer);
-
+
if (bRtcNotInitialized)
bRtcNotInitialized = NV_FALSE;
-
+
return NV_TRUE;
}
/* Read RTC alarm count register */
-NvBool
+NvBool
Tps6586xRtcAlarmCountRead(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
return NV_FALSE;
@@ -115,9 +152,9 @@ Tps6586xRtcAlarmCountRead(
/* Write RTC alarm count register */
-NvBool
+NvBool
Tps6586xRtcAlarmCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
return NV_FALSE;
@@ -125,7 +162,7 @@ Tps6586xRtcAlarmCountWrite(
/* Reads RTC alarm interrupt mask status */
-NvBool
+NvBool
Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
{
return NV_FALSE;
@@ -133,9 +170,9 @@ Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
/* Enables / Disables the RTC alarm interrupt */
-NvBool
+NvBool
Tps6586xRtcAlarmIntEnable(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvBool Enable)
{
return NV_FALSE;
@@ -143,7 +180,7 @@ Tps6586xRtcAlarmIntEnable(
/* Checks if boot was from nopower / powered state */
-NvBool
+NvBool
Tps6586xRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice)
{
NvU32 Data = 0;