Lines Matching +full:cs +full:- +full:to +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright 2018,2021-2025 NXP
9 * timing functions. STM includes a 32-bit count-up timer and four
10 * 32-bit compare channels with a separate interrupt source for each
12 * 8-bit prescale value (1 to 256). It has ability to stop the timer
15 #include <linux/clk.h>
61 struct clocksource cs; member
75 * This global lock is used to prevent race conditions with the
82 static struct stm_timer *cs_to_stm(struct clocksource *cs) in DEFINE_GUARD()
84 return container_of(cs, struct stm_timer, cs); in DEFINE_GUARD()
94 return readl(STM_CNT(stm_sched_clock->base)); in nxp_stm_read_sched_clock()
99 return readl(STM_CNT(stm_timer->base)); in nxp_stm_clocksource_getcnt()
104 writel(cnt, STM_CNT(stm_timer->base)); in nxp_stm_clocksource_setcnt()
107 static u64 nxp_stm_clocksource_read(struct clocksource *cs) in nxp_stm_clocksource_read() argument
109 struct stm_timer *stm_timer = cs_to_stm(cs); in nxp_stm_clocksource_read()
118 reg = readl(STM_CR(stm_timer->base)); in nxp_stm_module_enable()
122 writel(reg, STM_CR(stm_timer->base)); in nxp_stm_module_enable()
129 reg = readl(STM_CR(stm_timer->base)); in nxp_stm_module_disable()
133 writel(reg, STM_CR(stm_timer->base)); in nxp_stm_module_disable()
138 if (atomic_dec_and_test(&stm_timer->refcnt)) in nxp_stm_module_put()
144 if (atomic_inc_return(&stm_timer->refcnt) == 1) in nxp_stm_module_get()
148 static int nxp_stm_clocksource_enable(struct clocksource *cs) in nxp_stm_clocksource_enable() argument
150 struct stm_timer *stm_timer = cs_to_stm(cs); in nxp_stm_clocksource_enable()
157 static void nxp_stm_clocksource_disable(struct clocksource *cs) in nxp_stm_clocksource_disable() argument
159 struct stm_timer *stm_timer = cs_to_stm(cs); in nxp_stm_clocksource_disable()
164 static void nxp_stm_clocksource_suspend(struct clocksource *cs) in nxp_stm_clocksource_suspend() argument
166 struct stm_timer *stm_timer = cs_to_stm(cs); in nxp_stm_clocksource_suspend()
168 nxp_stm_clocksource_disable(cs); in nxp_stm_clocksource_suspend()
169 stm_timer->counter = nxp_stm_clocksource_getcnt(stm_timer); in nxp_stm_clocksource_suspend()
172 static void nxp_stm_clocksource_resume(struct clocksource *cs) in nxp_stm_clocksource_resume() argument
174 struct stm_timer *stm_timer = cs_to_stm(cs); in nxp_stm_clocksource_resume()
176 nxp_stm_clocksource_setcnt(stm_timer, stm_timer->counter); in nxp_stm_clocksource_resume()
177 nxp_stm_clocksource_enable(cs); in nxp_stm_clocksource_resume()
184 clocksource_unregister(&stm_timer->cs); in devm_clocksource_unregister()
188 const char *name, void __iomem *base, struct clk *clk) in nxp_stm_clocksource_init() argument
192 stm_timer->base = base; in nxp_stm_clocksource_init()
193 stm_timer->rate = clk_get_rate(clk); in nxp_stm_clocksource_init()
195 stm_timer->cs.name = name; in nxp_stm_clocksource_init()
196 stm_timer->cs.rating = 460; in nxp_stm_clocksource_init()
197 stm_timer->cs.read = nxp_stm_clocksource_read; in nxp_stm_clocksource_init()
198 stm_timer->cs.enable = nxp_stm_clocksource_enable; in nxp_stm_clocksource_init()
199 stm_timer->cs.disable = nxp_stm_clocksource_disable; in nxp_stm_clocksource_init()
200 stm_timer->cs.suspend = nxp_stm_clocksource_suspend; in nxp_stm_clocksource_init()
201 stm_timer->cs.resume = nxp_stm_clocksource_resume; in nxp_stm_clocksource_init()
202 stm_timer->cs.mask = CLOCKSOURCE_MASK(32); in nxp_stm_clocksource_init()
203 stm_timer->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; in nxp_stm_clocksource_init()
204 stm_timer->cs.owner = THIS_MODULE; in nxp_stm_clocksource_init()
206 ret = clocksource_register_hz(&stm_timer->cs, stm_timer->rate); in nxp_stm_clocksource_init()
212 clocksource_unregister(&stm_timer->cs); in nxp_stm_clocksource_init()
218 sched_clock_register(nxp_stm_read_sched_clock, 32, stm_timer->rate); in nxp_stm_clocksource_init()
227 return readl(STM_CNT(stm_timer->base)); in nxp_stm_clockevent_read_counter()
232 writel(0, STM_CCR0(stm_timer->base)); in nxp_stm_clockevent_disable()
237 writel(STM_CCR_CEN, STM_CCR0(stm_timer->base)); in nxp_stm_clockevent_enable()
256 stm_timer->delta = delta; in nxp_stm_clockevent_set_next_event()
260 writel(val, STM_CMP0(stm_timer->base)); in nxp_stm_clockevent_set_next_event()
270 * check if we are back in time and abort the timer with -ETIME. in nxp_stm_clockevent_set_next_event()
273 return -ETIME; in nxp_stm_clockevent_set_next_event()
284 return nxp_stm_clockevent_set_next_event(stm_timer->rate, ced); in nxp_stm_clockevent_set_periodic()
303 struct clk *clk, int cpu) in nxp_stm_clockevent_per_cpu_init() argument
305 stm_timer->base = base; in nxp_stm_clockevent_per_cpu_init()
306 stm_timer->rate = clk_get_rate(clk); in nxp_stm_clockevent_per_cpu_init()
308 stm_timer->ced.name = name; in nxp_stm_clockevent_per_cpu_init()
309 stm_timer->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; in nxp_stm_clockevent_per_cpu_init()
310 stm_timer->ced.set_state_shutdown = nxp_stm_clockevent_shutdown; in nxp_stm_clockevent_per_cpu_init()
311 stm_timer->ced.set_state_periodic = nxp_stm_clockevent_set_periodic; in nxp_stm_clockevent_per_cpu_init()
312 stm_timer->ced.set_next_event = nxp_stm_clockevent_set_next_event; in nxp_stm_clockevent_per_cpu_init()
313 stm_timer->ced.suspend = nxp_stm_clockevent_suspend; in nxp_stm_clockevent_per_cpu_init()
314 stm_timer->ced.resume = nxp_stm_clockevent_resume; in nxp_stm_clockevent_per_cpu_init()
315 stm_timer->ced.cpumask = cpumask_of(cpu); in nxp_stm_clockevent_per_cpu_init()
316 stm_timer->ced.rating = 460; in nxp_stm_clockevent_per_cpu_init()
317 stm_timer->ced.irq = irq; in nxp_stm_clockevent_per_cpu_init()
318 stm_timer->ced.owner = THIS_MODULE; in nxp_stm_clockevent_per_cpu_init()
335 return -EFAULT; in nxp_stm_clockevent_starting_cpu()
337 ret = irq_force_affinity(stm_timer->ced.irq, cpumask_of(cpu)); in nxp_stm_clockevent_starting_cpu()
343 * and writing to the comparator register takes as a maximum in nxp_stm_clockevent_starting_cpu()
345 * set above this value and to be secure we set the minimum in nxp_stm_clockevent_starting_cpu()
346 * value equal to 2000ns, so 2us. in nxp_stm_clockevent_starting_cpu()
350 clockevents_config_and_register(&stm_timer->ced, stm_timer->rate, in nxp_stm_clockevent_starting_cpu()
351 (stm_timer->rate / MICRO) * 2, ULONG_MAX); in nxp_stm_clockevent_starting_cpu()
359 struct clock_event_device *ced = &stm_timer->ced; in nxp_stm_module_interrupt()
364 * module. But this one is configured to run only one channel, in nxp_stm_module_interrupt()
365 * consequently it is pointless to test the interrupt flags in nxp_stm_module_interrupt()
369 writel(STM_CIR_CIF, STM_CIR0(stm_timer->base)); in nxp_stm_module_interrupt()
374 val = nxp_stm_clockevent_read_counter(stm_timer) + stm_timer->delta; in nxp_stm_module_interrupt()
376 writel(val, STM_CMP0(stm_timer->base)); in nxp_stm_module_interrupt()
380 * interrupt and start the counter again so software needs to in nxp_stm_module_interrupt()
381 * disable the timer to stop the counter loop in ONESHOT mode. in nxp_stm_module_interrupt()
386 ced->event_handler(ced); in nxp_stm_module_interrupt()
394 struct device *dev = &pdev->dev; in nxp_stm_timer_probe()
395 struct device_node *np = dev->of_node; in nxp_stm_timer_probe()
397 struct clk *clk; in nxp_stm_timer_probe() local
406 * ready to support the option. in nxp_stm_timer_probe()
412 * is expected to run on Cortex-A53 cores, while other in nxp_stm_timer_probe()
413 * software stacks will operate on Cortex-M cores. The number in nxp_stm_timer_probe()
414 * of STM instances has been sized to include at most one in nxp_stm_timer_probe()
429 return dev_err_probe(dev, PTR_ERR(base), "Failed to iomap %pOFn\n", np); in nxp_stm_timer_probe()
433 return dev_err_probe(dev, irq, "Failed to get IRQ\n"); in nxp_stm_timer_probe()
435 clk = devm_clk_get_enabled(dev, NULL); in nxp_stm_timer_probe()
436 if (IS_ERR(clk)) in nxp_stm_timer_probe()
437 return dev_err_probe(dev, PTR_ERR(clk), "Clock not found\n"); in nxp_stm_timer_probe()
441 return -ENOMEM; in nxp_stm_timer_probe()
446 return dev_err_probe(dev, ret, "Unable to allocate interrupt line\n"); in nxp_stm_timer_probe()
448 ret = nxp_stm_clocksource_init(dev, stm_timer, name, base, clk); in nxp_stm_timer_probe()
458 base, irq, clk, in nxp_stm_timer_probe()
467 * equal to the number of available CPUs on the in nxp_stm_timer_probe()
468 * system. We install the cpu hotplug to finish the in nxp_stm_timer_probe()
482 { .compatible = "nxp,s32g2-stm" },
490 .name = "nxp-stm",