diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-02-14 15:25:20 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:06:08 -0700 |
commit | 51363a7755feda711605e009debd967df655729d (patch) | |
tree | fa01a6c8b6af789b5799351d4bc25927fc07d5a5 /drivers/rtc | |
parent | 6596ae01c673645388f03bd41a10b1bcb1177f35 (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.c | 53 |
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 = { |