summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
diff options
context:
space:
mode:
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.c192
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)
{