linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: tip-bot for Benjamin Gaignard <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: hpa@zytor.com, linux-kernel@vger.kernel.org,
	torvalds@linux-foundation.org, mingo@kernel.org,
	mcoquelin.stm32@gmail.com, tglx@linutronix.de,
	peterz@infradead.org, alexandre.torgue@st.com,
	benjamin.gaignard@st.com, daniel.lezcano@linaro.org
Subject: [tip:timers/core] clocksource/drivers/stm32: Add oneshot mode
Date: Mon, 8 Jan 2018 09:32:38 -0800	[thread overview]
Message-ID: <tip-8e82df381b676ae5f6c93ab4a75f56d8f61babc4@git.kernel.org> (raw)
In-Reply-To: <1515418139-23276-16-git-send-email-daniel.lezcano@linaro.org>

Commit-ID:  8e82df381b676ae5f6c93ab4a75f56d8f61babc4
Gitweb:     https://git.kernel.org/tip/8e82df381b676ae5f6c93ab4a75f56d8f61babc4
Author:     Benjamin Gaignard <benjamin.gaignard@st.com>
AuthorDate: Mon, 8 Jan 2018 14:28:55 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 8 Jan 2018 17:57:26 +0100

clocksource/drivers/stm32: Add oneshot mode

The stm32 timer block is able to have a counter and a comparator.

Instead of using the auto-reload register for periodic events, we switch
to oneshot mode by using the comparator register.

The timer is able to generate an interrupt when the counter overflows but
we don't want that as this counter will be use as a clocksource in the next
patches. So it is disabled by the UDIS bit of the control register.

Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1515418139-23276-16-git-send-email-daniel.lezcano@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 drivers/clocksource/timer-stm32.c | 56 ++++++++++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 928ac28..882037f 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -24,14 +24,18 @@
 #define TIM_DIER	0x0c
 #define TIM_SR		0x10
 #define TIM_EGR		0x14
+#define TIM_CNT		0x24
 #define TIM_PSC		0x28
 #define TIM_ARR		0x2c
+#define TIM_CCR1	0x34
 
 #define TIM_CR1_CEN	BIT(0)
+#define TIM_CR1_UDIS	BIT(1)
 #define TIM_CR1_OPM	BIT(3)
 #define TIM_CR1_ARPE	BIT(7)
 
 #define TIM_DIER_UIE	BIT(0)
+#define TIM_DIER_CC1IE	BIT(1)
 
 #define TIM_SR_UIF	BIT(0)
 
@@ -40,33 +44,57 @@
 #define TIM_PSC_MAX	USHRT_MAX
 #define TIM_PSC_CLKRATE	10000
 
+static void stm32_clock_event_disable(struct timer_of *to)
+{
+	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
+}
+
+static void stm32_clock_event_enable(struct timer_of *to)
+{
+	writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+}
+
 static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
 
-	writel_relaxed(0, timer_of_base(to) + TIM_CR1);
+	stm32_clock_event_disable(to);
 
 	return 0;
 }
 
-static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+static int stm32_clock_event_set_next_event(unsigned long evt,
+					    struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
+	unsigned long now, next;
+
+	next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
+	writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
+	now = readl_relaxed(timer_of_base(to) + TIM_CNT);
+
+	if ((next - now) > evt)
+		return -ETIME;
 
-	writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
-	writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+	writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
 
 	return 0;
 }
 
-static int stm32_clock_event_set_next_event(unsigned long evt,
-					    struct clock_event_device *clkevt)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+{
+	struct timer_of *to = to_timer_of(clkevt);
+
+	stm32_clock_event_enable(to);
+
+	return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
+}
+
+static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
 {
 	struct timer_of *to = to_timer_of(clkevt);
 
-	writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
-	writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
-		       timer_of_base(to) + TIM_CR1);
+	stm32_clock_event_enable(to);
 
 	return 0;
 }
@@ -78,6 +106,11 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
 
 	writel_relaxed(0, timer_of_base(to) + TIM_SR);
 
+	if (clockevent_state_periodic(clkevt))
+		stm32_clock_event_set_periodic(clkevt);
+	else
+		stm32_clock_event_shutdown(clkevt);
+
 	clkevt->event_handler(clkevt);
 
 	return IRQ_HANDLED;
@@ -108,9 +141,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 
 	to->clkevt.name = to->np->full_name;
 	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
 	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
 	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
-	to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
+	to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
 	to->clkevt.tick_resume = stm32_clock_event_shutdown;
 	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
 
@@ -129,12 +163,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
 		prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
 		to->clkevt.rating = 100;
 	}
-	writel_relaxed(0, timer_of_base(to) + TIM_ARR);
 
 	writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
 	writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
 	writel_relaxed(0, timer_of_base(to) + TIM_SR);
-	writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
 
 	/* Adjust rate and period given the prescaler value */
 	to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);

  reply	other threads:[~2018-01-08 17:37 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-08 13:27 [PULL] clockevents for 4.16 Daniel Lezcano
2018-01-08 13:28 ` [PATCH 01/20] dt-bindings: timer: Add Actions Semi S700 Daniel Lezcano
2018-01-08 13:28   ` [PATCH 02/20] clocksource/drivers/owl: Adopt TIMER_OF_DECLARE() Daniel Lezcano
2018-01-08 13:28   ` [PATCH 03/20] clocksource/drivers/owl: Add the S700 Daniel Lezcano
2018-01-08 13:28   ` [PATCH 04/20] clocksource/drivers/tcb_clksrc: Fix clock speed message Daniel Lezcano
2018-01-08 17:27     ` [tip:timers/core] " tip-bot for Romain Izard
2018-01-08 13:28   ` [PATCH 05/20] clocksource/drivers/timer-of: Fix function names Daniel Lezcano
2018-01-08 17:27     ` [tip:timers/core] " tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 06/20] clocksource/drivers/timer-of: Add kernel documentation Daniel Lezcano
2018-01-08 17:28     ` [tip:timers/core] " tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 07/20] dt-bindings: clocksource: Add Spreadtrum SC9860 timer Daniel Lezcano
2018-01-08 17:28     ` [tip:timers/core] dt-bindings/clocksource: Add Spreadtrum SC9860 timer documentation tip-bot for Baolin Wang
2018-01-08 13:28   ` [PATCH 08/20] clocksource/drivers/spreadtrum: Add timer driver for Spreadtrum SC9860 platform Daniel Lezcano
2018-01-08 17:29     ` [tip:timers/core] clocksource/drivers/spreadtrum: Add timer driver for the " tip-bot for Baolin Wang
2018-01-08 13:28   ` [PATCH 09/20] clocksource/drivers/timer-of: Store the device node pointer Daniel Lezcano
2018-01-08 17:29     ` [tip:timers/core] clocksource/drivers/timer-of: Store the device node pointer in 'struct timer_of' tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 10/20] clocksource/drivers/timer-of: Don't request the resource by name Daniel Lezcano
2018-01-08 17:30     ` [tip:timers/core] " tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 11/20] clocksource/drivers/stm32: Fix kernel panic with multiple timers Daniel Lezcano
2018-01-08 17:30     ` [tip:timers/core] " tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 12/20] clocksource/drivers/stm32: Convert the driver to timer-of Daniel Lezcano
2018-01-08 17:30     ` [tip:timers/core] clocksource/drivers/stm32: Convert the driver to timer_of primitives tip-bot for Benjamin Gaignard
2018-01-08 13:28   ` [PATCH 13/20] clocksource/drivers/stm32: Use the node name as timer name Daniel Lezcano
2018-01-08 17:31     ` [tip:timers/core] " tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 14/20] clocksource/drivers/stm32: Encapsulate the timer width sorting out function Daniel Lezcano
2018-01-08 17:31     ` [tip:timers/core] clocksource/drivers/stm32: Factor out the timer width sorting code tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 15/20] clocksource/drivers/stm32: Compute a prescaler value with a targeted rate Daniel Lezcano
2018-01-08 17:32     ` [tip:timers/core] " tip-bot for Benjamin Gaignard
2018-01-08 13:28   ` [PATCH 16/20] clocksource/drivers/stm32: Add the oneshot mode Daniel Lezcano
2018-01-08 17:32     ` tip-bot for Benjamin Gaignard [this message]
2018-01-08 13:28   ` [PATCH 17/20] clocksource/drivers/stm32: Encapsulate more the clockevent code Daniel Lezcano
2018-01-08 17:33     ` [tip:timers/core] clocksource/drivers/stm32: Factor out more of " tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 18/20] clocksource/drivers/stm32: Add the clocksource Daniel Lezcano
2018-01-08 17:33     ` [tip:timers/core] clocksource/drivers/stm32: Add clocksource functionality tip-bot for Benjamin Gaignard
2018-01-08 13:28   ` [PATCH 19/20] clocksource/drivers/stm32: Add the timer delay Daniel Lezcano
2018-01-08 17:33     ` [tip:timers/core] clocksource/drivers/stm32: Add the timer delay callback tip-bot for Daniel Lezcano
2018-01-08 13:28   ` [PATCH 20/20] clocksource/drivers/stm32: Start the timer's counter sooner Daniel Lezcano
2018-01-08 17:34     ` [tip:timers/core] " tip-bot for Daniel Lezcano
2018-01-08 16:58 ` [PULL] clockevents for 4.16 Ingo Molnar
2018-01-08 17:07   ` Daniel Lezcano

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=tip-8e82df381b676ae5f6c93ab4a75f56d8f61babc4@git.kernel.org \
    --to=tipbot@zytor.com \
    --cc=alexandre.torgue@st.com \
    --cc=benjamin.gaignard@st.com \
    --cc=daniel.lezcano@linaro.org \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.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).