summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
authorKen Chang <kenc@nvidia.com>2011-05-24 10:57:00 +0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:43:15 -0800
commitfe47ef3cb50ba7455f0457b2c82536bdf788db0c (patch)
tree331ce5c58800b37ee2596c4e9ba8cce5098f57c3 /drivers/rtc
parent755bcb6dd81a3669a6109b08f9ba361c0427d6ac (diff)
rtc: tps6586x: fix alarm1 overflow
tps6586 alarm1 has a 24-bit register, however LSB 10 bits [9:0] are used as a counter of ticks per second. Therefore, the valid range is within 0x3FFF seconds (14-bit width). Check the value set to alarm1. Change the value to (current rtc[23:10] minus 1) if the target value is larger than 0x3FFF (4 hours). If no such fix, there might be overflow issues when alarm1 is enabled, and the system might wakes up unexpectedly. This change is to keep the system in suspend state as long as possible if alarm is enabled. Bug 827056 Original-Change-Id: Icb310132e08b56642179d92dfe00a34bfd28982a Reviewed-on: http://git-master/r/32700 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Ken Chang <kenc@nvidia.com> Reviewed-by: Yu-Fong (Foster) Cho <ycho@nvidia.com> Reviewed-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-by: ChihJen Hsu <chhsu@nvidia.com> Rebase-Id: Receaa52de2019ef4a02403312afa1385e5642caf
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-tps6586x.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index 729d71ecc754..c74d7db832ef 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -40,6 +40,7 @@
#define RTC_ALARM1_HI 0xc1
#define RTC_COUNT4 0xc6
#define RTC_COUNT4_DUMMYREAD 0xc5 /* start a PMU RTC access by reading the register prior to the RTC_COUNT4 */
+#define ALM1_VALID_RANGE_IN_SEC 0x3FFF /*only 14-bits width in second*/
struct tps6586x_rtc {
unsigned long epoch_start;
@@ -133,8 +134,11 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long seconds;
unsigned long ticks;
+ unsigned long long rticks = 0;
u8 buff[3];
+ u8 rbuff[6];
int err;
+ int i;
if (rtc->irq == -1)
return -EIO;
@@ -155,6 +159,22 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
seconds -= rtc->epoch_start;
+
+ if (seconds > ALM1_VALID_RANGE_IN_SEC) {
+ err = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(rbuff), rbuff);
+ if (err < 0) {
+ dev_err(dev, "failed to read counter\n");
+ return err;
+ }
+
+ for (i = 1; i < sizeof(rbuff); i++) {
+ rticks <<= 8;
+ rticks |= rbuff[i];
+ }
+
+ seconds = (rticks >> 10) - 1;
+ }
+
ticks = (unsigned long long)seconds << 10;
buff[0] = (ticks >> 16) & 0xff;