From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: daniel.lezcano@linaro.org, tglx@linutronix.de
Cc: S32@nxp.com, linux-kernel@vger.kernel.org,
ghennadi.procopciuc@oss.nxp.com
Subject: [PATCH v2 03/20] clocksource/drivers/vf-pit: Set the scene for multiple timers
Date: Wed, 30 Jul 2025 10:27:05 +0200 [thread overview]
Message-ID: <20250730082725.183133-4-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <20250730082725.183133-1-daniel.lezcano@linaro.org>
The driver is implemented as using a single timer and a single
clocksource. In order to take advantage of the multiple timers
supported in the PIT hardware and introduce different setup for a new
platform, let's encapsulate the data into a structure and pass this
structure around in the function parameter. The structure will be a
per timer instansiation in the next changes.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-vf-pit.c | 121 +++++++++++++++++------------
1 file changed, 72 insertions(+), 49 deletions(-)
diff --git a/drivers/clocksource/timer-vf-pit.c b/drivers/clocksource/timer-vf-pit.c
index 8041a8f62d1f..e4a8b32fff75 100644
--- a/drivers/clocksource/timer-vf-pit.c
+++ b/drivers/clocksource/timer-vf-pit.c
@@ -15,7 +15,7 @@
*/
#define PITMCR 0x00
#define PIT0_OFFSET 0x100
-#define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n))
+#define PIT_CH(n) (PIT0_OFFSET + 0x10 * (n))
#define PITLDVAL 0x00
#define PITCVAL 0x04
#define PITTCTRL 0x08
@@ -29,23 +29,36 @@
#define PITTFLG_TIF 0x1
+struct pit_timer {
+ void __iomem *clksrc_base;
+ void __iomem *clkevt_base;
+ unsigned long cycle_per_jiffy;
+ struct clock_event_device ced;
+ struct clocksource cs;
+};
+
+static struct pit_timer pit_timer;
+
static void __iomem *clksrc_base;
-static void __iomem *clkevt_base;
-static unsigned long cycle_per_jiffy;
-static inline void pit_timer_enable(void)
+static inline struct pit_timer *ced_to_pit(struct clock_event_device *ced)
{
- writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL);
+ return container_of(ced, struct pit_timer, ced);
}
-static inline void pit_timer_disable(void)
+static inline void pit_timer_enable(struct pit_timer *pit)
{
- writel(0, clkevt_base + PITTCTRL);
+ writel(PITTCTRL_TEN | PITTCTRL_TIE, pit->clkevt_base + PITTCTRL);
}
-static inline void pit_irq_acknowledge(void)
+static inline void pit_timer_disable(struct pit_timer *pit)
{
- writel(PITTFLG_TIF, clkevt_base + PITTFLG);
+ writel(0, pit->clkevt_base + PITTCTRL);
+}
+
+static inline void pit_irq_acknowledge(struct pit_timer *pit)
+{
+ writel(PITTFLG_TIF, pit->clkevt_base + PITTFLG);
}
static u64 notrace pit_read_sched_clock(void)
@@ -53,21 +66,24 @@ static u64 notrace pit_read_sched_clock(void)
return ~readl(clksrc_base + PITCVAL);
}
-static int __init pit_clocksource_init(unsigned long rate)
+static int __init pit_clocksource_init(struct pit_timer *pit, unsigned long rate)
{
/* set the max load value and start the clock source counter */
- writel(0, clksrc_base + PITTCTRL);
- writel(~0UL, clksrc_base + PITLDVAL);
- writel(PITTCTRL_TEN, clksrc_base + PITTCTRL);
+ writel(0, pit->clksrc_base + PITTCTRL);
+ writel(~0, pit->clksrc_base + PITLDVAL);
+ writel(PITTCTRL_TEN, pit->clksrc_base + PITTCTRL);
+
+ clksrc_base = pit->clksrc_base;
sched_clock_register(pit_read_sched_clock, 32, rate);
- return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate,
+ return clocksource_mmio_init(pit->clksrc_base + PITCVAL, "vf-pit", rate,
300, 32, clocksource_mmio_readl_down);
}
-static int pit_set_next_event(unsigned long delta,
- struct clock_event_device *unused)
+static int pit_set_next_event(unsigned long delta, struct clock_event_device *ced)
{
+ struct pit_timer *pit = ced_to_pit(ced);
+
/*
* set a new value to PITLDVAL register will not restart the timer,
* to abort the current cycle and start a timer period with the new
@@ -75,30 +91,37 @@ static int pit_set_next_event(unsigned long delta,
* and the PITLAVAL should be set to delta minus one according to pit
* hardware requirement.
*/
- pit_timer_disable();
- writel(delta - 1, clkevt_base + PITLDVAL);
- pit_timer_enable();
+ pit_timer_disable(pit);
+ writel(delta - 1, pit->clkevt_base + PITLDVAL);
+ pit_timer_enable(pit);
return 0;
}
-static int pit_shutdown(struct clock_event_device *evt)
+static int pit_shutdown(struct clock_event_device *ced)
{
- pit_timer_disable();
+ struct pit_timer *pit = ced_to_pit(ced);
+
+ pit_timer_disable(pit);
+
return 0;
}
-static int pit_set_periodic(struct clock_event_device *evt)
+static int pit_set_periodic(struct clock_event_device *ced)
{
- pit_set_next_event(cycle_per_jiffy, evt);
+ struct pit_timer *pit = ced_to_pit(ced);
+
+ pit_set_next_event(pit->cycle_per_jiffy, ced);
+
return 0;
}
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = dev_id;
+ struct clock_event_device *ced = dev_id;
+ struct pit_timer *pit = ced_to_pit(ced);
- pit_irq_acknowledge();
+ pit_irq_acknowledge(pit);
/*
* pit hardware doesn't support oneshot, it will generate an interrupt
@@ -106,33 +129,33 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
* and start the counter again. So software need to disable the timer
* to stop the counter loop in ONESHOT mode.
*/
- if (likely(clockevent_state_oneshot(evt)))
- pit_timer_disable();
+ if (likely(clockevent_state_oneshot(ced)))
+ pit_timer_disable(pit);
- evt->event_handler(evt);
+ ced->event_handler(ced);
return IRQ_HANDLED;
}
-static struct clock_event_device clockevent_pit = {
- .name = "VF pit timer",
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_state_shutdown = pit_shutdown,
- .set_state_periodic = pit_set_periodic,
- .set_next_event = pit_set_next_event,
- .rating = 300,
-};
-
-static int __init pit_clockevent_init(unsigned long rate, int irq)
+static int __init pit_clockevent_init(struct pit_timer *pit, unsigned long rate, int irq)
{
- writel(0, clkevt_base + PITTCTRL);
- writel(PITTFLG_TIF, clkevt_base + PITTFLG);
+ writel(0, pit->clkevt_base + PITTCTRL);
+
+ writel(PITTFLG_TIF, pit->clkevt_base + PITTFLG);
BUG_ON(request_irq(irq, pit_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
- "VF pit timer", &clockevent_pit));
+ "VF pit timer", &pit->ced));
+
+ pit->ced.cpumask = cpumask_of(0);
+ pit->ced.irq = irq;
+
+ pit->ced.name = "VF pit timer";
+ pit->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ pit->ced.set_state_shutdown = pit_shutdown;
+ pit->ced.set_state_periodic = pit_set_periodic;
+ pit->ced.set_next_event = pit_set_next_event;
+ pit->ced.rating = 300;
- clockevent_pit.cpumask = cpumask_of(0);
- clockevent_pit.irq = irq;
/*
* The value for the LDVAL register trigger is calculated as:
* LDVAL trigger = (period / clock period) - 1
@@ -141,7 +164,7 @@ static int __init pit_clockevent_init(unsigned long rate, int irq)
* LDVAL trigger value is 1. And then the min_delta is
* minimal LDVAL trigger value + 1, and the max_delta is full 32-bit.
*/
- clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff);
+ clockevents_config_and_register(&pit->ced, rate, 2, 0xffffffff);
return 0;
}
@@ -164,8 +187,8 @@ static int __init pit_timer_init(struct device_node *np)
* so choose PIT2 as clocksource, PIT3 as clockevent device,
* and leave PIT0 and PIT1 unused for anyone else who needs them.
*/
- clksrc_base = timer_base + PITn_OFFSET(2);
- clkevt_base = timer_base + PITn_OFFSET(3);
+ pit_timer.clksrc_base = timer_base + PIT_CH(2);
+ pit_timer.clkevt_base = timer_base + PIT_CH(3);
irq = irq_of_parse_and_map(np, 0);
if (irq <= 0)
@@ -180,15 +203,15 @@ static int __init pit_timer_init(struct device_node *np)
return ret;
clk_rate = clk_get_rate(pit_clk);
- cycle_per_jiffy = clk_rate / (HZ);
+ pit_timer.cycle_per_jiffy = clk_rate / (HZ);
/* enable the pit module */
writel(~PITMCR_MDIS, timer_base + PITMCR);
- ret = pit_clocksource_init(clk_rate);
+ ret = pit_clocksource_init(&pit_timer, clk_rate);
if (ret)
return ret;
- return pit_clockevent_init(clk_rate, irq);
+ return pit_clockevent_init(&pit_timer, clk_rate, irq);
}
TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);
--
2.43.0
next prev parent reply other threads:[~2025-07-30 8:28 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-30 8:27 [PATCH v2 00/20] Add support for the NXP automotive S32G PIT Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 01/20] clocksource/drivers/vf-pit: Replace raw_readl/writel to reald/writel Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 02/20] clocksource/drivers/vf-pit: Add COMPILE_TEST option Daniel Lezcano
2025-07-30 8:27 ` Daniel Lezcano [this message]
2025-07-30 8:27 ` [PATCH v2 04/20] clocksource/drivers/vf-pit: Rework the base address usage Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 05/20] clocksource/drivers/vf-pit: Pass the cpu number as parameter Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 06/20] clocksource/drivers/vf-pit: Encapsulate the initialization of the cycles_per_jiffy Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 07/20] clocksource/drivers/vf-pit: Allocate the struct timer at init time Daniel Lezcano
2025-08-01 7:33 ` Ghennadi Procopciuc
2025-08-04 9:12 ` Daniel Lezcano
2025-08-04 10:02 ` Ghennadi Procopciuc
2025-07-30 8:27 ` [PATCH v2 08/20] clocksource/drivers/vf-pit: Convert raw values to BIT macros Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 09/20] clocksource/drivers/vf-pit: Register the clocksource from the driver Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 10/20] clocksource/drivers/vf-pit: Encapsulate the macros Daniel Lezcano
2025-08-01 7:33 ` Ghennadi Procopciuc
2025-07-30 8:27 ` [PATCH v2 11/20] clocksource/drivers/vf-pit: Encapsulate the PTLCVAL macro Daniel Lezcano
2025-08-01 7:34 ` Ghennadi Procopciuc
2025-07-30 8:27 ` [PATCH v2 12/20] clocksource/drivers/vf-pit: Use the node name for the interrupt and timer names Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 13/20] clocksource/drivers/vf-pit: Encapsulate clocksource enable / disable Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 14/20] clocksource/drivers/vf-pit: Enable and disable module on error Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 15/20] clocksource/drivers/vf-pit: Encapsulate set counter function Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 16/20] clocksource/drivers/vf-pit: Consolidate calls to pit_*_disable/enable Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 17/20] clocksource/drivers/vf-pit: Unify the function name for irq ack Daniel Lezcano
2025-08-01 7:34 ` Ghennadi Procopciuc
2025-07-30 8:27 ` [PATCH v2 18/20] clocksource/drivers/vf-pit: Rename the VF PIT to NXP PIT Daniel Lezcano
2025-08-01 7:35 ` Ghennadi Procopciuc
2025-08-01 8:48 ` Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 19/20] dt: bindings: fsl,vf610-pit: Add compatible for s32g2 and s32g3 Daniel Lezcano
2025-07-30 23:36 ` Rob Herring
2025-07-31 7:41 ` Daniel Lezcano
2025-07-31 7:50 ` Krzysztof Kozlowski
2025-07-31 8:24 ` Daniel Lezcano
2025-07-30 8:27 ` [PATCH v2 20/20] clocksource/drivers/nxp-pit: Add NXP Automotive s32g2 / s32g3 support Daniel Lezcano
2025-08-01 7:36 ` Ghennadi Procopciuc
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=20250730082725.183133-4-daniel.lezcano@linaro.org \
--to=daniel.lezcano@linaro.org \
--cc=S32@nxp.com \
--cc=ghennadi.procopciuc@oss.nxp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=tglx@linutronix.de \
/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).