summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-02-14 15:25:20 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:06:08 -0700
commit51363a7755feda711605e009debd967df655729d (patch)
treefa01a6c8b6af789b5799351d4bc25927fc07d5a5 /drivers/rtc
parent6596ae01c673645388f03bd41a10b1bcb1177f35 (diff)
rtc: palmas: Clear all interrupt of RTC during init
There is a false wakeup from Palma RTC in suspend state of system. Following changes are done to fix this issue: - Clear all intrruprs of RTC during initialization, - make RTC interrupt as early resume and - do not enable the interrupt in suspend, as the interrupt get enabled when user sets the alarm. Add debug prints on rtc callbacks for tracing the activity happen with RTC hardware to catch any false setting/alarm/wakeup. bug 1227717 (Cherrypicked from commit 0adcd0943ee3fd4982056d879ef3621d14fd4040) Change-Id: I18a5a0a845dcf036d6ffea8a350f5d32fef83e5d Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/200736 Reviewed-on: http://git-master/r/215099
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-palmas.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index 148868abd726..1179c8a15bfd 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -1,7 +1,7 @@
/*
* rtc-palmas.c -- Palmas Real Time Clock interface
*
- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012 - 2013, NVIDIA CORPORATION. All rights reserved.
* Author: Kasoju Mallikarjun <mkasoju@nvidia.com>
*
* This program is free software; you can redistribute it and/or
@@ -92,6 +92,8 @@ static int palmas_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
struct palmas *palmas = dev_get_drvdata(dev->parent);
u8 val = 0;
+ dev_info(dev, "%s(): enabled %u\n", __func__, enabled);
+
if (enabled)
val = PALMAS_RTC_INTERRUPTS_REG_IT_ALARM;
@@ -136,6 +138,9 @@ static int palmas_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
tm->tm_year = bcd2bin(rtc_data[5]) + 100;
+ dev_info(dev, "%s() %d %d %d %d %d %d\n",
+ __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
return ret;
}
@@ -152,6 +157,10 @@ static int palmas_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_data[4] = bin2bcd(tm->tm_mon + 1);
rtc_data[5] = bin2bcd(tm->tm_year - 100);
+ dev_info(dev, "%s() %d %d %d %d %d %d\n",
+ __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
/* Stop RTC while updating the RTC time registers */
ret = palmas_rtc_update_bits(palmas, PALMAS_RTC_CTRL_REG,
PALMAS_RTC_CTRL_REG_STOP_RTC, 0);
@@ -201,6 +210,10 @@ static int palmas_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
+ dev_info(dev, "%s() %d %d %d %d %d %d\n", __func__,
+ alm->time.tm_year, alm->time.tm_mon, alm->time.tm_mday,
+ alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec);
+
ret = palmas_rtc_read(palmas, PALMAS_RTC_INTERRUPTS_REG,
&int_val);
if (ret < 0)
@@ -218,6 +231,7 @@ static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
struct palmas *palmas = dev_get_drvdata(dev->parent);
int ret;
+ dev_info(dev, "%s()\n", __func__);
ret = palmas_rtc_alarm_irq_enable(dev, 0);
if (ret)
return ret;
@@ -229,6 +243,10 @@ static int palmas_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
+ dev_info(dev, "%s() %d %d %d %d %d %d\n", __func__,
+ alm->time.tm_year, alm->time.tm_mon, alm->time.tm_mday,
+ alm->time.tm_hour, alm->time.tm_min, alm->time.tm_sec);
+
/* update all the alarm registers in one shot */
ret = palmas_rtc_bulk_write(palmas,
PALMAS_ALARM_SECONDS_REG, alarm_data, NUM_TIME_REGS);
@@ -252,11 +270,15 @@ static irqreturn_t palmas_rtc_interrupt(int irq, void *rtc)
int ret;
u32 rtc_reg;
+ dev_info(dev, "RTC ISR\n");
+
ret = palmas_rtc_read(palmas, PALMAS_RTC_STATUS_REG,
&rtc_reg);
if (ret)
return IRQ_NONE;
+ dev_info(dev, "RTC ISR status 0x%02x\n", rtc_reg);
+
if (rtc_reg & PALMAS_RTC_STATUS_REG_ALARM)
events = RTC_IRQF | RTC_AF;
@@ -334,6 +356,13 @@ static int __devinit palmas_rtc_probe(struct platform_device *pdev)
}
}
+ ret = palmas_rtc_write(palmas, PALMAS_RTC_INTERRUPTS_REG, 0);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "RTC_INTERRUPTS_REG write failed: %d\n",
+ ret);
+ return ret;
+ }
+
/* Clear pending interrupts */
ret = palmas_rtc_read(palmas, PALMAS_RTC_STATUS_REG,
&rtc_reg);
@@ -361,13 +390,15 @@ static int __devinit palmas_rtc_probe(struct platform_device *pdev)
palmas_rtc->irq = platform_get_irq(pdev, 0);
dev_info(&pdev->dev, "RTC interrupt %d\n", palmas_rtc->irq);
ret = request_threaded_irq(palmas_rtc->irq, NULL,
- palmas_rtc_interrupt, IRQF_TRIGGER_LOW,
+ palmas_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_ONESHOT |
+ IRQF_EARLY_RESUME,
"palmas-rtc", &pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "IRQ is not free.\n");
return ret;
}
device_init_wakeup(&pdev->dev, 1);
+ platform_set_drvdata(pdev, palmas_rtc);
palmas_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
&palmas_rtc_ops, THIS_MODULE);
@@ -378,8 +409,6 @@ static int __devinit palmas_rtc_probe(struct platform_device *pdev)
return ret;
}
- platform_set_drvdata(pdev, palmas_rtc);
-
return 0;
}
@@ -403,21 +432,11 @@ static int palmas_rtc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
- u8 alarm = PALMAS_RTC_INTERRUPTS_REG_IT_ALARM;
- int ret;
if (device_may_wakeup(dev))
enable_irq_wake(palmas->rtc->irq);
- /* Store current list of enabled interrupts*/
- ret = palmas_rtc_read(palmas, PALMAS_RTC_INTERRUPTS_REG,
- &palmas->rtc->irqstat);
- if (ret < 0)
- return ret;
-
- /* Enable RTC ALARM interrupt only */
- return palmas_rtc_write(palmas,
- PALMAS_RTC_INTERRUPTS_REG, alarm);
+ return 0;
}
static int palmas_rtc_resume(struct device *dev)
@@ -428,9 +447,7 @@ static int palmas_rtc_resume(struct device *dev)
if (device_may_wakeup(dev))
disable_irq_wake(palmas->rtc->irq);
- /* Restore list of enabled interrupts before suspend */
- return palmas_rtc_write(palmas,
- PALMAS_RTC_INTERRUPTS_REG, palmas->rtc->irqstat);
+ return 0;
}
static const struct dev_pm_ops palmas_rtc_pm_ops = {