From: boris.brezillon@free-electrons.com (Boris Brezillon)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 3/6] rtc: at91rm9200: rework wakeup and interrupt handling
Date: Mon, 2 Mar 2015 10:18:15 +0100 [thread overview]
Message-ID: <1425287898-15093-4-git-send-email-boris.brezillon@free-electrons.com> (raw)
In-Reply-To: <1425287898-15093-1-git-send-email-boris.brezillon@free-electrons.com>
The IRQ line used by the RTC device is usually shared with the system
timer (PIT) on at91 platforms.
Since timers are registering their handlers with IRQF_NO_SUSPEND, we
should expect being called in suspended state, and properly wake the
system up when this is the case.
Set IRQF_COND_SUSPEND flag when registering the IRQ handler to inform
irq core that it can safely be called while the system is suspended.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
drivers/rtc/rtc-at91rm9200.c | 62 ++++++++++++++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 14 deletions(-)
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 70a5d94..b4f7744 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/suspend.h>
#include <linux/uaccess.h>
#include "rtc-at91rm9200.h"
@@ -54,6 +55,10 @@ static void __iomem *at91_rtc_regs;
static int irq;
static DEFINE_SPINLOCK(at91_rtc_lock);
static u32 at91_rtc_shadow_imr;
+static bool suspended;
+static DEFINE_SPINLOCK(suspended_lock);
+static unsigned long cached_events;
+static u32 at91_rtc_imr;
static void at91_rtc_write_ier(u32 mask)
{
@@ -290,7 +295,9 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
struct rtc_device *rtc = platform_get_drvdata(pdev);
unsigned int rtsr;
unsigned long events = 0;
+ int ret = IRQ_NONE;
+ spin_lock(&suspended_lock);
rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read_imr();
if (rtsr) { /* this interrupt is shared! Is it ours? */
if (rtsr & AT91_RTC_ALARM)
@@ -304,14 +311,22 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
at91_rtc_write(AT91_RTC_SCCR, rtsr); /* clear status reg */
- rtc_update_irq(rtc, 1, events);
+ if (!suspended) {
+ rtc_update_irq(rtc, 1, events);
- dev_dbg(&pdev->dev, "%s(): num=%ld, events=0x%02lx\n", __func__,
- events >> 8, events & 0x000000FF);
+ dev_dbg(&pdev->dev, "%s(): num=%ld, events=0x%02lx\n",
+ __func__, events >> 8, events & 0x000000FF);
+ } else {
+ cached_events |= events;
+ at91_rtc_write_idr(at91_rtc_imr);
+ pm_system_wakeup();
+ }
- return IRQ_HANDLED;
+ ret = IRQ_HANDLED;
}
- return IRQ_NONE; /* not handled */
+ spin_lock(&suspended_lock);
+
+ return ret;
}
static const struct at91_rtc_config at91rm9200_config = {
@@ -401,8 +416,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
AT91_RTC_CALEV);
ret = devm_request_irq(&pdev->dev, irq, at91_rtc_interrupt,
- IRQF_SHARED,
- "at91_rtc", pdev);
+ IRQF_SHARED | IRQF_COND_SUSPEND,
+ "at91_rtc", pdev);
if (ret) {
dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);
return ret;
@@ -454,8 +469,6 @@ static void at91_rtc_shutdown(struct platform_device *pdev)
/* AT91RM9200 RTC Power management control */
-static u32 at91_rtc_imr;
-
static int at91_rtc_suspend(struct device *dev)
{
/* this IRQ is shared with DBGU and other hardware which isn't
@@ -464,21 +477,42 @@ static int at91_rtc_suspend(struct device *dev)
at91_rtc_imr = at91_rtc_read_imr()
& (AT91_RTC_ALARM|AT91_RTC_SECEV);
if (at91_rtc_imr) {
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
+ unsigned long flags;
+
enable_irq_wake(irq);
- else
+
+ spin_lock_irqsave(&suspended_lock, flags);
+ suspended = true;
+ spin_unlock_irqrestore(&suspended_lock, flags);
+ } else {
at91_rtc_write_idr(at91_rtc_imr);
+ }
}
return 0;
}
static int at91_rtc_resume(struct device *dev)
{
+ struct rtc_device *rtc = dev_get_drvdata(dev);
+
if (at91_rtc_imr) {
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&suspended_lock, flags);
+
+ if (cached_events) {
+ rtc_update_irq(rtc, 1, cached_events);
+ cached_events = 0;
+ }
+
+ suspended = false;
+ spin_unlock_irqrestore(&suspended_lock, flags);
+
disable_irq_wake(irq);
- else
- at91_rtc_write_ier(at91_rtc_imr);
+ }
+ at91_rtc_write_ier(at91_rtc_imr);
}
return 0;
}
--
1.9.1
next prev parent reply other threads:[~2015-03-02 9:18 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-02 9:18 [PATCH v2 0/6] ARM: at91: fix irq_pm_install_action WARNING Boris Brezillon
2015-03-02 9:18 ` [PATCH v2 1/6] PM / wakeup: export pm_system_wakeup symbol Boris Brezillon
2015-03-02 9:18 ` [PATCH v2 2/6] rtc: at91sam9: rework wakeup and interrupt handling Boris Brezillon
2015-03-04 18:23 ` Mark Rutland
2015-03-02 9:18 ` Boris Brezillon [this message]
2015-03-02 9:18 ` [PATCH v2 4/6] clk: at91: implement suspend/resume for the PMC irqchip Boris Brezillon
2015-03-09 22:34 ` Mike Turquette
2015-03-02 9:18 ` [PATCH v2 5/6] watchdog: at91sam9: request the irq with IRQF_NO_SUSPEND Boris Brezillon
2015-03-02 14:10 ` Guenter Roeck
2015-03-04 18:38 ` Mark Rutland
2015-03-04 21:41 ` Rafael J. Wysocki
2015-03-05 10:57 ` Mark Rutland
2015-03-05 15:10 ` Rafael J. Wysocki
2015-03-05 16:32 ` Mark Rutland
2015-03-06 0:29 ` Rafael J. Wysocki
2015-03-06 11:06 ` Mark Rutland
2015-03-06 12:39 ` Rafael J. Wysocki
2015-03-06 13:10 ` Mark Rutland
2015-03-07 9:12 ` Peter Zijlstra
2015-03-07 9:06 ` Peter Zijlstra
2015-03-05 8:53 ` Boris Brezillon
2015-03-05 10:53 ` Mark Rutland
2015-03-05 11:17 ` Boris Brezillon
2015-03-05 11:31 ` Boris Brezillon
2015-03-05 11:53 ` Mark Rutland
2015-03-07 9:18 ` Peter Zijlstra
2015-03-07 10:20 ` Sylvain Rochet
2015-03-07 10:39 ` Pavel Machek
2015-03-07 10:59 ` Sylvain Rochet
2015-03-07 11:06 ` Alexandre Belloni
2015-03-07 11:29 ` Pavel Machek
2015-03-07 11:46 ` Sylvain Rochet
2015-03-08 1:12 ` Rafael J. Wysocki
2015-03-09 7:55 ` Alexandre Belloni
2015-03-09 14:30 ` Rafael J. Wysocki
2015-03-10 21:33 ` Alexandre Belloni
2015-03-10 22:31 ` Rafael J. Wysocki
2015-03-10 22:33 ` Alexandre Belloni
2015-03-11 1:03 ` Rafael J. Wysocki
2015-03-11 7:33 ` Boris Brezillon
2015-03-08 1:11 ` Rafael J. Wysocki
2015-03-11 8:38 ` Boris Brezillon
2015-03-11 11:17 ` Nicolas Ferre
2015-03-02 9:18 ` [PATCH v2 6/6] tty: serial: atmel: rework interrupt and wakeup handling Boris Brezillon
2015-03-03 8:56 ` [PATCH v2 0/6] ARM: at91: fix irq_pm_install_action WARNING Alexandre Belloni
2015-03-03 15:35 ` Nicolas Ferre
2015-03-04 1:43 ` Rafael J. Wysocki
2015-03-04 18:43 ` Mark Rutland
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1425287898-15093-4-git-send-email-boris.brezillon@free-electrons.com \
--to=boris.brezillon@free-electrons.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).