From: Doug Berger <opendmb@gmail.com>
To: Alessandro Zummo <a.zummo@towertech.it>,
Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Brian Norris <computersforpeace@gmail.com>,
Markus Mayer <mmayer@broadcom.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Florian Fainelli <f.fainelli@gmail.com>,
Broadcom internal kernel review list
<bcm-kernel-feedback-list@broadcom.com>,
linux-rtc@vger.kernel.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Doug Berger <opendmb@gmail.com>
Subject: [PATCH 6/6] rtc: brcmstb-waketimer: allow use as non-wake alarm
Date: Fri, 20 Jan 2023 11:01:47 -0800 [thread overview]
Message-ID: <20230120190147.718976-7-opendmb@gmail.com> (raw)
In-Reply-To: <20230120190147.718976-1-opendmb@gmail.com>
The wake interrupt only fires when the system is in a suspend
state. Fortunately we have another interrupt that fires in a
non-suspend state at the L2 controller UPG_AUX_AON. Add support
for this interrupt line so we can use the alarm in a non-wake
context.
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/rtc/rtc-brcmstb-waketimer.c | 55 +++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index e25f9fcd6ed1..1efa81cecc27 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -28,6 +28,7 @@ struct brcmstb_waketmr {
struct device *dev;
void __iomem *base;
unsigned int wake_irq;
+ unsigned int alarm_irq;
struct notifier_block reboot_notifier;
struct clk *clk;
u32 rate;
@@ -56,6 +57,8 @@ static inline void brcmstb_waketmr_clear_alarm(struct brcmstb_waketmr *timer)
{
u32 reg;
+ if (timer->alarm_en && timer->alarm_irq)
+ disable_irq(timer->alarm_irq);
timer->alarm_en = false;
reg = readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER);
writel_relaxed(reg - 1, timer->base + BRCMSTB_WKTMR_ALARM);
@@ -88,7 +91,25 @@ static irqreturn_t brcmstb_waketmr_irq(int irq, void *data)
{
struct brcmstb_waketmr *timer = data;
- pm_wakeup_event(timer->dev, 0);
+ if (!timer->alarm_irq)
+ pm_wakeup_event(timer->dev, 0);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t brcmstb_alarm_irq(int irq, void *data)
+{
+ struct brcmstb_waketmr *timer = data;
+
+ /* Ignore spurious interrupts */
+ if (!brcmstb_waketmr_is_pending(timer))
+ return IRQ_HANDLED;
+
+ if (timer->alarm_en) {
+ if (!device_may_wakeup(timer->dev))
+ writel_relaxed(WKTMR_ALARM_EVENT,
+ timer->base + BRCMSTB_WKTMR_EVENT);
+ rtc_update_irq(timer->rtc, 1, RTC_IRQF | RTC_AF);
+ }
return IRQ_HANDLED;
}
@@ -114,7 +135,7 @@ static void wktmr_read(struct brcmstb_waketmr *timer,
static int brcmstb_waketmr_prepare_suspend(struct brcmstb_waketmr *timer)
{
struct device *dev = timer->dev;
- int ret = 0;
+ int ret;
if (device_may_wakeup(dev)) {
ret = enable_irq_wake(timer->wake_irq);
@@ -122,9 +143,17 @@ static int brcmstb_waketmr_prepare_suspend(struct brcmstb_waketmr *timer)
dev_err(dev, "failed to enable wake-up interrupt\n");
return ret;
}
+ if (timer->alarm_en && timer->alarm_irq) {
+ ret = enable_irq_wake(timer->alarm_irq);
+ if (ret) {
+ dev_err(dev, "failed to enable rtc interrupt\n");
+ disable_irq_wake(timer->wake_irq);
+ return ret;
+ }
+ }
}
- return ret;
+ return 0;
}
/* If enabled as a wakeup-source, arm the timer when powering off */
@@ -192,7 +221,11 @@ static int brcmstb_waketmr_alarm_enable(struct device *dev,
!brcmstb_waketmr_is_pending(timer))
return -EINVAL;
timer->alarm_en = true;
+ if (timer->alarm_irq)
+ enable_irq(timer->alarm_irq);
} else if (!enabled && timer->alarm_en) {
+ if (timer->alarm_irq)
+ disable_irq(timer->alarm_irq);
timer->alarm_en = false;
}
@@ -269,6 +302,19 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
if (ret < 0)
goto err_clk;
+ brcmstb_waketmr_clear_alarm(timer);
+
+ /* Attempt to initialize non-wake irq */
+ ret = platform_get_irq(pdev, 1);
+ if (ret > 0) {
+ timer->alarm_irq = (unsigned int)ret;
+ ret = devm_request_irq(dev, timer->alarm_irq, brcmstb_alarm_irq,
+ IRQF_NO_AUTOEN, "brcmstb-waketimer-rtc",
+ timer);
+ if (ret < 0)
+ timer->alarm_irq = 0;
+ }
+
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
register_reboot_notifier(&timer->reboot_notifier);
@@ -317,6 +363,8 @@ static int brcmstb_waketmr_resume(struct device *dev)
return 0;
ret = disable_irq_wake(timer->wake_irq);
+ if (timer->alarm_en && timer->alarm_irq)
+ disable_irq_wake(timer->alarm_irq);
brcmstb_waketmr_clear_alarm(timer);
@@ -346,4 +394,5 @@ module_platform_driver(brcmstb_waketmr_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Brian Norris");
MODULE_AUTHOR("Markus Mayer");
+MODULE_AUTHOR("Doug Berger");
MODULE_DESCRIPTION("Wake-up timer driver for STB chips");
--
2.25.1
WARNING: multiple messages have this Message-ID (diff)
From: Doug Berger <opendmb@gmail.com>
To: Alessandro Zummo <a.zummo@towertech.it>,
Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Brian Norris <computersforpeace@gmail.com>,
Markus Mayer <mmayer@broadcom.com>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Florian Fainelli <f.fainelli@gmail.com>,
Broadcom internal kernel review list
<bcm-kernel-feedback-list@broadcom.com>,
linux-rtc@vger.kernel.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Doug Berger <opendmb@gmail.com>
Subject: [PATCH 6/6] rtc: brcmstb-waketimer: allow use as non-wake alarm
Date: Fri, 20 Jan 2023 11:01:47 -0800 [thread overview]
Message-ID: <20230120190147.718976-7-opendmb@gmail.com> (raw)
In-Reply-To: <20230120190147.718976-1-opendmb@gmail.com>
The wake interrupt only fires when the system is in a suspend
state. Fortunately we have another interrupt that fires in a
non-suspend state at the L2 controller UPG_AUX_AON. Add support
for this interrupt line so we can use the alarm in a non-wake
context.
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/rtc/rtc-brcmstb-waketimer.c | 55 +++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index e25f9fcd6ed1..1efa81cecc27 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -28,6 +28,7 @@ struct brcmstb_waketmr {
struct device *dev;
void __iomem *base;
unsigned int wake_irq;
+ unsigned int alarm_irq;
struct notifier_block reboot_notifier;
struct clk *clk;
u32 rate;
@@ -56,6 +57,8 @@ static inline void brcmstb_waketmr_clear_alarm(struct brcmstb_waketmr *timer)
{
u32 reg;
+ if (timer->alarm_en && timer->alarm_irq)
+ disable_irq(timer->alarm_irq);
timer->alarm_en = false;
reg = readl_relaxed(timer->base + BRCMSTB_WKTMR_COUNTER);
writel_relaxed(reg - 1, timer->base + BRCMSTB_WKTMR_ALARM);
@@ -88,7 +91,25 @@ static irqreturn_t brcmstb_waketmr_irq(int irq, void *data)
{
struct brcmstb_waketmr *timer = data;
- pm_wakeup_event(timer->dev, 0);
+ if (!timer->alarm_irq)
+ pm_wakeup_event(timer->dev, 0);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t brcmstb_alarm_irq(int irq, void *data)
+{
+ struct brcmstb_waketmr *timer = data;
+
+ /* Ignore spurious interrupts */
+ if (!brcmstb_waketmr_is_pending(timer))
+ return IRQ_HANDLED;
+
+ if (timer->alarm_en) {
+ if (!device_may_wakeup(timer->dev))
+ writel_relaxed(WKTMR_ALARM_EVENT,
+ timer->base + BRCMSTB_WKTMR_EVENT);
+ rtc_update_irq(timer->rtc, 1, RTC_IRQF | RTC_AF);
+ }
return IRQ_HANDLED;
}
@@ -114,7 +135,7 @@ static void wktmr_read(struct brcmstb_waketmr *timer,
static int brcmstb_waketmr_prepare_suspend(struct brcmstb_waketmr *timer)
{
struct device *dev = timer->dev;
- int ret = 0;
+ int ret;
if (device_may_wakeup(dev)) {
ret = enable_irq_wake(timer->wake_irq);
@@ -122,9 +143,17 @@ static int brcmstb_waketmr_prepare_suspend(struct brcmstb_waketmr *timer)
dev_err(dev, "failed to enable wake-up interrupt\n");
return ret;
}
+ if (timer->alarm_en && timer->alarm_irq) {
+ ret = enable_irq_wake(timer->alarm_irq);
+ if (ret) {
+ dev_err(dev, "failed to enable rtc interrupt\n");
+ disable_irq_wake(timer->wake_irq);
+ return ret;
+ }
+ }
}
- return ret;
+ return 0;
}
/* If enabled as a wakeup-source, arm the timer when powering off */
@@ -192,7 +221,11 @@ static int brcmstb_waketmr_alarm_enable(struct device *dev,
!brcmstb_waketmr_is_pending(timer))
return -EINVAL;
timer->alarm_en = true;
+ if (timer->alarm_irq)
+ enable_irq(timer->alarm_irq);
} else if (!enabled && timer->alarm_en) {
+ if (timer->alarm_irq)
+ disable_irq(timer->alarm_irq);
timer->alarm_en = false;
}
@@ -269,6 +302,19 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
if (ret < 0)
goto err_clk;
+ brcmstb_waketmr_clear_alarm(timer);
+
+ /* Attempt to initialize non-wake irq */
+ ret = platform_get_irq(pdev, 1);
+ if (ret > 0) {
+ timer->alarm_irq = (unsigned int)ret;
+ ret = devm_request_irq(dev, timer->alarm_irq, brcmstb_alarm_irq,
+ IRQF_NO_AUTOEN, "brcmstb-waketimer-rtc",
+ timer);
+ if (ret < 0)
+ timer->alarm_irq = 0;
+ }
+
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
register_reboot_notifier(&timer->reboot_notifier);
@@ -317,6 +363,8 @@ static int brcmstb_waketmr_resume(struct device *dev)
return 0;
ret = disable_irq_wake(timer->wake_irq);
+ if (timer->alarm_en && timer->alarm_irq)
+ disable_irq_wake(timer->alarm_irq);
brcmstb_waketmr_clear_alarm(timer);
@@ -346,4 +394,5 @@ module_platform_driver(brcmstb_waketmr_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Brian Norris");
MODULE_AUTHOR("Markus Mayer");
+MODULE_AUTHOR("Doug Berger");
MODULE_DESCRIPTION("Wake-up timer driver for STB chips");
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-01-20 19:02 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-20 19:01 [PATCH 0/6] rtc: brcmstb-waketimer: add RTC alarm irq Doug Berger
2023-01-20 19:01 ` Doug Berger
2023-01-20 19:01 ` [PATCH 1/6] rtc: brcmstb-waketimer: introduce WKTMR_ALARM_EVENT flag Doug Berger
2023-01-20 19:01 ` Doug Berger
2023-01-23 19:20 ` Florian Fainelli
2023-01-23 19:20 ` Florian Fainelli
2023-01-20 19:01 ` [PATCH 2/6] rtc: brcmstb-waketimer: non-functional code changes Doug Berger
2023-01-20 19:01 ` Doug Berger
2023-01-23 19:20 ` Florian Fainelli
2023-01-23 19:20 ` Florian Fainelli
2023-01-20 19:01 ` [PATCH 3/6] rtc: brcmstb-waketimer: compensate for lack of wktmr disable Doug Berger
2023-01-20 19:01 ` Doug Berger
2023-01-23 19:21 ` Florian Fainelli
2023-01-23 19:21 ` Florian Fainelli
2023-01-20 19:01 ` [PATCH 4/6] rtc: brcmstb-waketimer: rename irq to wake_irq Doug Berger
2023-01-20 19:01 ` Doug Berger
2023-01-23 19:21 ` Florian Fainelli
2023-01-23 19:21 ` Florian Fainelli
2023-01-20 19:01 ` [PATCH 5/6] dt-bindings: rtc: brcm,brcmstb-waketimer: add alarm interrupt Doug Berger
2023-01-20 19:01 ` Doug Berger
2023-01-21 19:00 ` Krzysztof Kozlowski
2023-01-21 19:00 ` Krzysztof Kozlowski
2023-01-20 19:01 ` Doug Berger [this message]
2023-01-20 19:01 ` [PATCH 6/6] rtc: brcmstb-waketimer: allow use as non-wake alarm Doug Berger
2023-01-23 19:22 ` Florian Fainelli
2023-01-23 19:22 ` Florian Fainelli
2023-01-23 23:08 ` (subset) [PATCH 0/6] rtc: brcmstb-waketimer: add RTC alarm irq Alexandre Belloni
2023-01-23 23:08 ` Alexandre Belloni
2023-01-24 17:42 ` Florian Fainelli
2023-01-24 17:42 ` Florian Fainelli
2023-01-24 18:45 ` Alexandre Belloni
2023-01-24 18:45 ` Alexandre Belloni
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=20230120190147.718976-7-opendmb@gmail.com \
--to=opendmb@gmail.com \
--cc=a.zummo@towertech.it \
--cc=alexandre.belloni@bootlin.com \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=computersforpeace@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=f.fainelli@gmail.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=mmayer@broadcom.com \
--cc=robh+dt@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.