summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-02-14 15:25:20 +0530
committerMrutyunjay Sawant <msawant@nvidia.com>2013-02-15 09:53:29 -0800
commit0adcd0943ee3fd4982056d879ef3621d14fd4040 (patch)
tree09dd79a2f75df8b39583df29de2bf5c39730c2ce /drivers/rtc
parent5c65bd6be7a642e813d8561573067bf959d68a0d (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 Change-Id: I18a5a0a845dcf036d6ffea8a350f5d32fef83e5d Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/200736 Reviewed-by: Automatic_Commit_Validation_User
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 aed71f5a87e6..e82cc8040fc3 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);
@@ -371,13 +400,15 @@ static int __devinit palmas_rtc_probe(struct platform_device *pdev)
palmas_rtc->irq += PALMAS_RTC_ALARM_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);
@@ -388,8 +419,6 @@ static int __devinit palmas_rtc_probe(struct platform_device *pdev)
return ret;
}
- platform_set_drvdata(pdev, palmas_rtc);
-
return 0;
}
@@ -413,21 +442,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)
@@ -438,9 +457,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 = {