From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: daniel.lezcano@linaro.org, tglx@linutronix.de
Cc: ghennadi.procopciuc@oss.nxp.com, S32@nxp.com,
linux-kernel@vger.kernel.org
Subject: [PATCH 03/20] clocksource/drivers/vf_pit: Set the scene for multiple timers
Date: Sat, 5 Jul 2025 18:01:09 +0200 [thread overview]
Message-ID: <20250705160129.3688026-3-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <20250705160129.3688026-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 instanciation in the next changes.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-vf-pit.c | 119 +++++++++++++++++------------
1 file changed, 70 insertions(+), 49 deletions(-)
diff --git a/drivers/clocksource/timer-vf-pit.c b/drivers/clocksource/timer-vf-pit.c
index 8041a8f62d1f..581b46e7b111 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)
+{
+ return container_of(ced, struct pit_timer, ced);
+}
+
+static inline void pit_timer_enable(struct pit_timer *pit)
{
- writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL);
+ writel(PITTCTRL_TEN | PITTCTRL_TIE, pit->clkevt_base + PITTCTRL);
}
-static inline void pit_timer_disable(void)
+static inline void pit_timer_disable(struct pit_timer *pit)
{
- writel(0, clkevt_base + PITTCTRL);
+ writel(0, pit->clkevt_base + PITTCTRL);
}
-static inline void pit_irq_acknowledge(void)
+static inline void pit_irq_acknowledge(struct pit_timer *pit)
{
- writel(PITTFLG_TIF, clkevt_base + PITTFLG);
+ writel(PITTFLG_TIF, pit->clkevt_base + PITTFLG);
}
static u64 notrace pit_read_sched_clock(void)
@@ -53,21 +66,22 @@ 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);
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 +89,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 +127,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 +162,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 +185,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 +201,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-05 16:01 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-05 16:01 [PATCH 01/20] clocksource/drivers/vf-pit: Replace raw_readl/writel to reald/writel Daniel Lezcano
2025-07-05 16:01 ` [PATCH 02/20] clocksource/drivers/vf_pit: Add COMPILE_TEST option Daniel Lezcano
2025-07-05 16:01 ` Daniel Lezcano [this message]
2025-07-07 12:04 ` [PATCH 03/20] clocksource/drivers/vf_pit: Set the scene for multiple timers Ghennadi Procopciuc
2025-07-05 16:01 ` [PATCH 04/20] clocksource/drivers/vf_pit: Rework the base address usage Daniel Lezcano
2025-07-07 12:03 ` Ghennadi Procopciuc
2025-07-24 17:29 ` Daniel Lezcano
2025-07-25 5:10 ` Ghennadi Procopciuc
2025-07-05 16:01 ` [PATCH 05/20] clocksource/drivers/vf_pit: Pass the cpu number as parameter Daniel Lezcano
2025-07-07 9:33 ` Ghennadi Procopciuc
2025-07-24 17:30 ` Daniel Lezcano
2025-07-05 16:01 ` [PATCH 06/20] clocksource/drivers/vf_pit: Encapsulate the initialization of the cycles_per_jiffy Daniel Lezcano
2025-07-05 16:01 ` [PATCH 07/20] clocksource/drivers/vf-pit: Allocate the struct timer at init time Daniel Lezcano
2025-07-05 16:01 ` [PATCH 08/20] clocksource/drivers/vf-pit: Convert raw values to BIT macros Daniel Lezcano
2025-07-05 16:01 ` [PATCH 09/20] clocksource/drivers/vf-pit: Register the clocksource from the driver Daniel Lezcano
2025-07-07 12:02 ` Ghennadi Procopciuc
2025-07-26 19:37 ` Daniel Lezcano
2025-07-05 16:01 ` [PATCH 10/20] clocksource/drivers/vf-pit: Encapsulate the macros Daniel Lezcano
2025-07-07 12:03 ` Ghennadi Procopciuc
2025-07-28 8:35 ` Daniel Lezcano
2025-07-05 16:01 ` [PATCH 11/20] clocksource/drivers/vf-pit: Encapsulate the PTLCVAL macro Daniel Lezcano
2025-07-05 16:01 ` [PATCH 12/20] clocksource/drivers/vf-pit: Use the node name for the interrupt and timer names Daniel Lezcano
2025-07-25 5:12 ` Ghennadi Procopciuc
2025-07-05 16:01 ` [PATCH 13/20] clocksource/drivers/vf-pit: Encapsulate clocksource enable / disable Daniel Lezcano
2025-07-05 16:01 ` [PATCH 14/20] clocksource/drivers/vf-pit: Enable and disable module on error Daniel Lezcano
2025-07-05 16:01 ` [PATCH 15/20] clocksource/drivers/vf-pit: Encapsulate set counter function Daniel Lezcano
2025-07-05 16:01 ` [PATCH 16/20] clocksource/drivers/vf-pit: Consolidate calls to pit_*_disable/enable Daniel Lezcano
2025-07-07 10:28 ` Ghennadi Procopciuc
2025-07-05 16:01 ` [PATCH 17/20] clocksource/drivers/vf-pit: Unify the function name for irq ack Daniel Lezcano
2025-07-05 16:01 ` [PATCH 18/20] clocksource/drivers/pit: Rename the VF PIT to NXP PIT Daniel Lezcano
2025-07-05 16:01 ` [PATCH 19/20] clocksource/drivers/nxp-pit: Add NXP Automotive s32g2 / s32g3 support Daniel Lezcano
2025-07-06 22:13 ` kernel test robot
2025-07-07 12:02 ` Ghennadi Procopciuc
2025-07-28 8:31 ` Daniel Lezcano
2025-07-05 16:01 ` [PATCH 20/20] dt: bindings: fsl,vf610-pit: Add compatible for s32g2 and s32g3 Daniel Lezcano
2025-07-08 17:27 ` Rob Herring
2025-07-07 9:11 ` [PATCH 01/20] clocksource/drivers/vf-pit: Replace raw_readl/writel to reald/writel 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=20250705160129.3688026-3-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 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.