All of lore.kernel.org
 help / color / mirror / Atom feed
From: tip-bot for Benjamin Gaignard <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: torvalds@linux-foundation.org, peterz@infradead.org,
	linux-kernel@vger.kernel.org, hpa@zytor.com,
	mcoquelin.stm32@gmail.com, daniel.lezcano@linaro.org,
	tglx@linutronix.de, benjamin.gaignard@st.com,
	alexandre.torgue@st.com, mingo@kernel.org
Subject: [tip:timers/core] clocksource/drivers/stm32: Convert the driver to timer_of primitives
Date: Mon, 8 Jan 2018 09:30:56 -0800	[thread overview]
Message-ID: <tip-d04af4908a7283bc6ae0dd9475ccf807d094f8ba@git.kernel.org> (raw)
In-Reply-To: <1515418139-23276-12-git-send-email-daniel.lezcano@linaro.org>

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

clocksource/drivers/stm32: Convert the driver to timer_of primitives

Convert the driver to use the timer_of() helpers. This allows the removal of
a custom private structure, factors out and simplifies the code.

[Daniel Lezcano]: Respin against the critical fix patch and massaged the changelog.

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-12-git-send-email-daniel.lezcano@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 drivers/clocksource/Kconfig       |   1 +
 drivers/clocksource/timer-stm32.c | 187 +++++++++++++++-----------------------
 2 files changed, 74 insertions(+), 114 deletions(-)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 0359812..b3b4ed9 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -269,6 +269,7 @@ config CLKSRC_STM32
 	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
 	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
 	select CLKSRC_MMIO
+	select TIMER_OF
 
 config CLKSRC_MPS2
 	bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 4bfeb99..3e4ab07 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,9 @@
 #include <linux/of_irq.h>
 #include <linux/clk.h>
 #include <linux/reset.h>
+#include <linux/slab.h>
+
+#include "timer-of.h"
 
 #define TIM_CR1		0x00
 #define TIM_DIER	0x0c
@@ -34,162 +37,118 @@
 
 #define TIM_EGR_UG	BIT(0)
 
-struct stm32_clock_event_ddata {
-	struct clock_event_device evtdev;
-	unsigned periodic_top;
-	void __iomem *base;
-};
-
-static int stm32_clock_event_shutdown(struct clock_event_device *evtdev)
+static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
 {
-	struct stm32_clock_event_ddata *data =
-		container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
-	void *base = data->base;
+	struct timer_of *to = to_timer_of(clkevt);
+
+	writel_relaxed(0, timer_of_base(to) + TIM_CR1);
 
-	writel_relaxed(0, base + TIM_CR1);
 	return 0;
 }
 
-static int stm32_clock_event_set_periodic(struct clock_event_device *evtdev)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
 {
-	struct stm32_clock_event_ddata *data =
-		container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
-	void *base = data->base;
+	struct timer_of *to = to_timer_of(clkevt);
+
+	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(data->periodic_top, base + TIM_ARR);
-	writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
 	return 0;
 }
 
 static int stm32_clock_event_set_next_event(unsigned long evt,
-					    struct clock_event_device *evtdev)
+					    struct clock_event_device *clkevt)
 {
-	struct stm32_clock_event_ddata *data =
-		container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+	struct timer_of *to = to_timer_of(clkevt);
 
-	writel_relaxed(evt, data->base + TIM_ARR);
+	writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
 	writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
-		       data->base + TIM_CR1);
+		       timer_of_base(to) + TIM_CR1);
 
 	return 0;
 }
 
 static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
 {
-	struct stm32_clock_event_ddata *data = dev_id;
+	struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
+	struct timer_of *to = to_timer_of(clkevt);
 
-	writel_relaxed(0, data->base + TIM_SR);
+	writel_relaxed(0, timer_of_base(to) + TIM_SR);
 
-	data->evtdev.event_handler(&data->evtdev);
+	clkevt->event_handler(clkevt);
 
 	return IRQ_HANDLED;
 }
 
-static struct stm32_clock_event_ddata clock_event_ddata = {
-	.evtdev = {
-		.name = "stm32 clockevent",
-		.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
-		.set_state_shutdown = stm32_clock_event_shutdown,
-		.set_state_periodic = stm32_clock_event_set_periodic,
-		.set_state_oneshot = stm32_clock_event_shutdown,
-		.tick_resume = stm32_clock_event_shutdown,
-		.set_next_event = stm32_clock_event_set_next_event,
-		.rating = 200,
-	},
-};
-
-static int __init stm32_clockevent_init(struct device_node *np)
+static void __init stm32_clockevent_init(struct timer_of *to)
 {
-	struct stm32_clock_event_ddata *data = &clock_event_ddata;
-	struct clk *clk;
-	struct reset_control *rstc;
-	unsigned long rate, max_delta;
-	int irq, ret, bits, prescaler = 1;
-
-	data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	clk = of_clk_get(np, 0);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
-		pr_err("failed to get clock for clockevent (%d)\n", ret);
-		goto err_clk_get;
-	}
-
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		pr_err("failed to enable timer clock for clockevent (%d)\n",
-		       ret);
-		goto err_clk_enable;
-	}
-
-	rate = clk_get_rate(clk);
-
-	rstc = of_reset_control_get(np, NULL);
-	if (!IS_ERR(rstc)) {
-		reset_control_assert(rstc);
-		reset_control_deassert(rstc);
-	}
-
-	data->base = of_iomap(np, 0);
-	if (!data->base) {
-		ret = -ENXIO;
-		pr_err("failed to map registers for clockevent\n");
-		goto err_iomap;
-	}
+	unsigned long max_delta;
+	int prescaler;
 
-	irq = irq_of_parse_and_map(np, 0);
-	if (!irq) {
-		ret = -EINVAL;
-		pr_err("%pOF: failed to get irq.\n", np);
-		goto err_get_irq;
-	}
+	to->clkevt.name = "stm32_clockevent";
+	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+	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.tick_resume = stm32_clock_event_shutdown;
+	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
 
 	/* Detect whether the timer is 16 or 32 bits */
-	writel_relaxed(~0U, data->base + TIM_ARR);
-	max_delta = readl_relaxed(data->base + TIM_ARR);
+	writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
+	max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
 	if (max_delta == ~0U) {
 		prescaler = 1;
-		bits = 32;
+		to->clkevt.rating = 250;
 	} else {
 		prescaler = 1024;
-		bits = 16;
+		to->clkevt.rating = 100;
 	}
-	writel_relaxed(0, data->base + TIM_ARR);
+	writel_relaxed(0, timer_of_base(to) + TIM_ARR);
 
-	writel_relaxed(prescaler - 1, data->base + TIM_PSC);
-	writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
-	writel_relaxed(0, data->base + TIM_SR);
-	writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
+	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);
 
-	data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
+	/* Adjust rate and period given the prescaler value */
+	to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
+	to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
 
-	clockevents_config_and_register(&data->evtdev,
-					DIV_ROUND_CLOSEST(rate, prescaler),
-					0x1, max_delta);
-
-	ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER,
-			"stm32 clockevent", data);
-	if (ret) {
-		pr_err("%pOF: failed to request irq.\n", np);
-		goto err_get_irq;
-	}
+	clockevents_config_and_register(&to->clkevt,
+					timer_of_rate(to), 0x1, max_delta);
 
 	pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
-			np, bits);
+		to->np, max_delta == UINT_MAX ? 32 : 16);
+}
 
-	return ret;
+static int __init stm32_timer_init(struct device_node *node)
+{
+	struct reset_control *rstc;
+	struct timer_of *to;
+	int ret;
+
+	to = kzalloc(sizeof(*to), GFP_KERNEL);
+	if (!to)
+		return -ENOMEM;
+
+	to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
+	to->of_irq.handler = stm32_clock_event_handler;
+
+	ret = timer_of_init(node, to);
+	if (ret)
+		goto err;
 
-err_get_irq:
-	iounmap(data->base);
-err_iomap:
-	clk_disable_unprepare(clk);
-err_clk_enable:
-	clk_put(clk);
-err_clk_get:
-	kfree(data);
+	rstc = of_reset_control_get(node, NULL);
+	if (!IS_ERR(rstc)) {
+		reset_control_assert(rstc);
+		reset_control_deassert(rstc);
+	}
+
+	stm32_clockevent_init(to);
+	return 0;
+err:
+	kfree(to);
 	return ret;
 }
 
-TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
+TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);

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

Thread overview: 56+ 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   ` Daniel Lezcano
2018-01-08 13:28   ` Daniel Lezcano
2018-01-08 13:28   ` [PATCH 02/20] clocksource/drivers/owl: Adopt TIMER_OF_DECLARE() Daniel Lezcano
2018-01-08 13:28     ` Daniel Lezcano
2018-01-08 13:28   ` [PATCH 03/20] clocksource/drivers/owl: Add the S700 Daniel Lezcano
2018-01-08 13:28     ` Daniel Lezcano
2018-01-08 13:28   ` [PATCH 04/20] clocksource/drivers/tcb_clksrc: Fix clock speed message Daniel Lezcano
2018-01-08 13:28     ` 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
     [not found]   ` <1515418139-23276-1-git-send-email-daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2018-01-08 13:28     ` [PATCH 07/20] dt-bindings: clocksource: Add Spreadtrum SC9860 timer Daniel Lezcano
2018-01-08 13:28       ` 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 13:28     ` 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 13:28     ` Daniel Lezcano
2018-01-08 17:30     ` tip-bot for Benjamin Gaignard [this message]
2018-01-08 13:28   ` [PATCH 13/20] clocksource/drivers/stm32: Use the node name as timer name Daniel Lezcano
2018-01-08 13:28     ` 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 13:28     ` 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 13:28     ` 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 13:28     ` Daniel Lezcano
2018-01-08 17:32     ` [tip:timers/core] clocksource/drivers/stm32: Add " tip-bot for Benjamin Gaignard
2018-01-08 13:28   ` [PATCH 17/20] clocksource/drivers/stm32: Encapsulate more the clockevent code Daniel Lezcano
2018-01-08 13:28     ` 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 13:28     ` 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 13:28     ` 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 13:28     ` 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-d04af4908a7283bc6ae0dd9475ccf807d094f8ba@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 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.