diff options
author | Gerrit Code Review <gerrit2@git-master.nvidia.com> | 2010-01-23 00:20:09 +0200 |
---|---|---|
committer | Gerrit Code Review <gerrit2@git-master.nvidia.com> | 2010-01-23 00:20:09 +0200 |
commit | 8aeb9598c52279d0127d8e567df2f2bdff6fc15e (patch) | |
tree | f42d3f84dba1b2f012e2e93664f5dbd93efb64d5 | |
parent | 14da3c0dbb2ed251c2679900ba5d29f096c03c60 (diff) | |
parent | 7b29cc4a7bcee5f0ca927baaa45a90931b45d88c (diff) |
Merge change I07377e14 into android-tegra-2.6.29
* changes:
tegra2 rtc: date/time non-persistent on boards
3 files changed, 285 insertions, 165 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..50afb66beba3 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,215 @@ * */ +#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 + 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; + // struct rtc_time tm; - 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)) + 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; + + // Convert BCT time into decimal values + Hours = ((BcdHours & 0xF0)>>4)*10 + (BcdHours & 0xF); + Minutes = ((BcdMinutes & 0xF0)>>4)*10 + (BcdMinutes & 0xF); + Seconds = ((BcdSeconds & 0xF0)>>4)*10 + (BcdSeconds & 0xF); + + // Read day, month, yy1 and yy2 data from RTC registers + if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data)) { - - 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); - - *Count = (Hours * MAX8907B_SECONDS_PER_HOUR) + - (Minutes * MAX8907B_SECONDS_PER_MINUTE) + Seconds; + 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 bct day/month/year data to decimal values + YY2 = ((BcdYY2 & 0xF0)>>4)*10 + (BcdYY2 & 0xF); + YY1 = ((BcdYY1 & 0xF0)>>4)*10 + (BcdYY1 & 0xF); + YYYY = (YY2 * 100 + YY1) & 0xFFFF; + MM = ((BcdMM & 0xF0)>>4)*10 + (BcdMM & 0xF); + DD = ((BcdDD & 0xF0)>>4)*10 + (BcdDD & 0xF); + // 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; - - BcdHours = BcdMinutes = BcdSeconds = 0; - - RtcDays = Count / MAX8907B_SECONDS_PER_DAY; - - 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); + NvU8 BcdDD, BcdMM, BcdYY1, BcdYY2; + NvU16 YYYY; + struct rtc_time tm; + NvU32 data1; + + 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)); + + // Convert time to bcd format + BcdHours = ((tm.tm_hour / 10) << 4) | (tm.tm_hour % 10); + BcdMinutes = ((tm.tm_min/10) << 4) | (tm.tm_min%10); + BcdSeconds = ((tm.tm_sec/10) << 4) | (tm.tm_sec%10); 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 bct format + BcdDD = (((NvU8)tm.tm_mday / 10) << 4) | ((NvU8)tm.tm_mday % 10); + BcdMM = (((NvU8)tm.tm_mon / 10) << 4) | ((NvU8)tm.tm_mon % 10); + YYYY = (NvU16)tm.tm_year + LINUX_RTC_BASE_YEAR; + BcdYY1 = (((NvU8)(YYYY % 100) / 10) << 4) | ((NvU8)(YYYY % 100) % 10); + BcdYY2 = (((NvU8)(YYYY / 100) / 10) << 4) | ((NvU8)(YYYY / 100) % 10); + 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..29f52e2d7ae0 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 SHIFT_TO_2009 if 1, uses 2009 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 SHIFT_TO_2009 1 +#if SHIFT_TO_2009 +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,76 @@ 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 SHIFT_TO_2009 + // 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 SHIFT_TO_2009 + // 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 + // 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 +146,9 @@ Tps6586xRtcAlarmCountRead( /* Write RTC alarm count register */ -NvBool +NvBool Tps6586xRtcAlarmCountWrite( - NvOdmPmuDeviceHandle hDevice, + NvOdmPmuDeviceHandle hDevice, NvU32 Count) { return NV_FALSE; @@ -125,7 +156,7 @@ Tps6586xRtcAlarmCountWrite( /* Reads RTC alarm interrupt mask status */ -NvBool +NvBool Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice) { return NV_FALSE; @@ -133,9 +164,9 @@ Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice) /* Enables / Disables the RTC alarm interrupt */ -NvBool +NvBool Tps6586xRtcAlarmIntEnable( - NvOdmPmuDeviceHandle hDevice, + NvOdmPmuDeviceHandle hDevice, NvBool Enable) { return NV_FALSE; @@ -143,7 +174,7 @@ Tps6586xRtcAlarmIntEnable( /* Checks if boot was from nopower / powered state */ -NvBool +NvBool Tps6586xRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice) { NvU32 Data = 0; |