summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorGary King <GKing@nvidia.com>2010-02-03 11:26:50 -0800
committerGary King <GKing@nvidia.com>2010-02-03 11:30:48 -0800
commit970c0d3605484adcf2166cd6e93f3b04d02cc8f6 (patch)
tree8e7e29dd43ddb652bedede5ac5f8dd4010c1a35b /drivers
parentfd8f187e0da2ff6732d6f4022c4ffc583de2caef (diff)
tegra rtc: work-around Y2038 issue with uninitialized PMUs
an uninitialized PMU may return a completely random value for the number of seconds; when this value is interpreted as number of seconds since 1970, this can cause severe instability if the value is >= 0x80000000UL (which is January 2038, sign-overflowing the 32b signed time_t value used in the kernel) to work-around this issue, when the RTC driver is probed, it performs an initial read of the PMU's time; if the value returned would result in a negative time_t value, the PMU RTC is reset to 0. bug 648967 Change-Id: Icee9940b5433e7e22edf98f9fcd5c7193b5c4f1f
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rtc/rtc-tegra-odm.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/drivers/rtc/rtc-tegra-odm.c b/drivers/rtc/rtc-tegra-odm.c
index 49a48c60fc84..a5ff518c5aa6 100644
--- a/drivers/rtc/rtc-tegra-odm.c
+++ b/drivers/rtc/rtc-tegra-odm.c
@@ -33,9 +33,6 @@
#include <nvodm_pmu.h>
-#define SET_YEAR(Y) (Y-1900)
-#define SET_MONTH(M) (M-1)
-
/* Create a custom rtc structrue and move this to that structure */
static NvOdmPmuDeviceHandle hPmu = NULL;
@@ -51,20 +48,7 @@ static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
return -1;
}
- if (!now) {
- tm->tm_sec = 0;
- tm->tm_min = 0;
- tm->tm_hour = 0;
- tm->tm_mday = 1;
- tm->tm_mon = SET_MONTH(5);
- tm->tm_year = SET_YEAR(2009);
- tm->tm_wday = 0;
- tm->tm_yday = 0;
- tm->tm_isdst = 0;
- } else {
- rtc_time_to_tm(now, tm);
- }
-
+ rtc_time_to_tm(now, tm);
return 0;
}
@@ -95,12 +79,23 @@ static struct rtc_class_ops tegra_rtc_ops = {
static int __init tegra_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtc;
+ NvU32 initial;
if (NvOdmPmuDeviceOpen(&hPmu) == NV_FALSE) {
pr_debug("%s: NvOdmPmuDeviceOpen failed\n", pdev->name);
return -ENXIO;
}
+ /* if the SoCs PMU has't been properly initialized, a bogus large
+ * value may be returned which triggers the Y2038 bug in the kernel.
+ * work-around this issue by checking the initial value of the PMU
+ * and then clobbering it if the value is bogus */
+
+ if (NvOdmPmuReadRtc(hPmu, &initial) && ((time_t)initial < 0))
+ NvOdmPmuWriteRtc(hPmu, 0);
+
+
+
rtc = rtc_device_register(pdev->name, &pdev->dev,
&tegra_rtc_ops, THIS_MODULE);