diff options
Diffstat (limited to 'arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c')
-rw-r--r-- | arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c | 192 |
1 files changed, 128 insertions, 64 deletions
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) { |