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.c260
1 files changed, 260 insertions, 0 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
new file mode 100644
index 000000000000..1c4d61a01a98
--- /dev/null
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2009 NVIDIA Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NVIDIA Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#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).
+*
+*/
+
+#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;
+
+NvBool
+Max8907bRtcCountRead(
+ 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
+
+ *Count = 0;
+ // Read seconds, minute, hour and weekday data from RTC registers
+ 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 BCD time into decimal values
+ Hours = BCD_TO_DECIMAL(BcdHours);
+ Minutes = BCD_TO_DECIMAL(BcdMinutes);
+ Seconds = BCD_TO_DECIMAL(BcdSeconds);
+
+ // 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
+ {
+ 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
+Max8907bRtcAlarmCountRead(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32* Count)
+{
+ return NV_FALSE;
+}
+
+NvBool
+Max8907bRtcCountWrite(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32 Count)
+{
+ NvU32 BcdHours, BcdMinutes, BcdSeconds;
+ NvU32 data = 0;
+ NvU8 BcdDD, BcdMM, BcdYY1, BcdYY2;
+ NvU16 YYYY;
+ struct rtc_time tm;
+#if NV_DEBUG
+ NvU32 data1;
+#endif
+
+ 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 = 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))
+ {
+ // 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
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. "));
+ return NV_FALSE;
+ }
+
+ return NV_TRUE;
+}
+
+NvBool
+Max8907bRtcAlarmCountWrite(
+ NvOdmPmuDeviceHandle hDevice,
+ NvU32 Count)
+{
+ return NV_FALSE;
+}
+
+NvBool
+Max8907bRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
+{
+ return NV_FALSE;
+}
+
+NvBool
+Max8907bRtcAlarmIntEnable(
+ NvOdmPmuDeviceHandle hDevice,
+ NvBool Enable)
+{
+ return NV_FALSE;
+}
+
+NvBool
+Max8907bIsRtcInitialized(NvOdmPmuDeviceHandle hDevice)
+{
+ return (!bRtcNotInitialized);
+}
+