Lines Matching +full:timer +full:-

1 // SPDX-License-Identifier: GPL-2.0
3 * 64-bit Periodic Interval Timer driver
38 #define MCHP_PIT64B_TLSBR 0x20 /* Timer LSB Register */
40 #define MCHP_PIT64B_TMSBR 0x24 /* Timer MSB Register */
51 * struct mchp_pit64b_timer - PIT64B timer data structure
65 * struct mchp_pit64b_clkevt - PIT64B clockevent data structure
66 * @timer: PIT64B timer
70 struct mchp_pit64b_timer timer; member
79 * struct mchp_pit64b_clksrc - PIT64B clocksource data structure
80 * @timer: PIT64B timer
84 struct mchp_pit64b_timer timer; member
92 /* Base address for clocksource timer. */
94 /* Default cycles for clockevent timer. */
96 /* Delay timer. */
109 * timer value whatever the lapse of time between the accesses. in mchp_pit64b_cnt_read()
119 static inline void mchp_pit64b_reset(struct mchp_pit64b_timer *timer, in mchp_pit64b_reset() argument
127 writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_reset()
128 writel_relaxed(mode | timer->mode, timer->base + MCHP_PIT64B_MR); in mchp_pit64b_reset()
129 writel_relaxed(high, timer->base + MCHP_PIT64B_MSB_PR); in mchp_pit64b_reset()
130 writel_relaxed(low, timer->base + MCHP_PIT64B_LSB_PR); in mchp_pit64b_reset()
131 writel_relaxed(irqs, timer->base + MCHP_PIT64B_IER); in mchp_pit64b_reset()
132 writel_relaxed(MCHP_PIT64B_CR_START, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_reset()
135 static void mchp_pit64b_suspend(struct mchp_pit64b_timer *timer) in mchp_pit64b_suspend() argument
137 writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_suspend()
138 if (timer->mode & MCHP_PIT64B_MR_SGCLK) in mchp_pit64b_suspend()
139 clk_disable_unprepare(timer->gclk); in mchp_pit64b_suspend()
140 clk_disable_unprepare(timer->pclk); in mchp_pit64b_suspend()
143 static void mchp_pit64b_resume(struct mchp_pit64b_timer *timer) in mchp_pit64b_resume() argument
145 clk_prepare_enable(timer->pclk); in mchp_pit64b_resume()
146 if (timer->mode & MCHP_PIT64B_MR_SGCLK) in mchp_pit64b_resume()
147 clk_prepare_enable(timer->gclk); in mchp_pit64b_resume()
152 struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs); in mchp_pit64b_clksrc_suspend() local
154 mchp_pit64b_suspend(timer); in mchp_pit64b_clksrc_suspend()
159 struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs); in mchp_pit64b_clksrc_resume() local
161 mchp_pit64b_resume(timer); in mchp_pit64b_clksrc_resume()
162 mchp_pit64b_reset(timer, ULLONG_MAX, MCHP_PIT64B_MR_CONT, 0); in mchp_pit64b_clksrc_resume()
182 struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev); in mchp_pit64b_clkevt_shutdown() local
185 mchp_pit64b_suspend(timer); in mchp_pit64b_clkevt_shutdown()
192 struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev); in mchp_pit64b_clkevt_set_periodic() local
195 mchp_pit64b_resume(timer); in mchp_pit64b_clkevt_set_periodic()
197 mchp_pit64b_reset(timer, mchp_pit64b_ce_cycles, MCHP_PIT64B_MR_CONT, in mchp_pit64b_clkevt_set_periodic()
205 struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev); in mchp_pit64b_clkevt_set_oneshot() local
208 mchp_pit64b_resume(timer); in mchp_pit64b_clkevt_set_oneshot()
210 mchp_pit64b_reset(timer, mchp_pit64b_ce_cycles, MCHP_PIT64B_MR_ONE_SHOT, in mchp_pit64b_clkevt_set_oneshot()
219 struct mchp_pit64b_timer *timer = clkevt_to_mchp_pit64b_timer(cedev); in mchp_pit64b_clkevt_set_next_event() local
221 mchp_pit64b_reset(timer, evt, MCHP_PIT64B_MR_ONE_SHOT, in mchp_pit64b_clkevt_set_next_event()
232 readl_relaxed(irq_data->timer.base + MCHP_PIT64B_ISR); in mchp_pit64b_interrupt()
234 irq_data->clkevt.event_handler(&irq_data->clkevt); in mchp_pit64b_interrupt()
252 *pres = MCHP_PIT64B_PRES_MAX - 1; in mchp_pit64b_pres_compute()
256 * mchp_pit64b_init_mode() - prepare PIT64B mode register value to be used at
258 * @timer: pointer to pit64b timer to init
259 * @max_rate: maximum rate that timer's clock could use
261 * PIT64B timer may be fed by gclk or pclk. When gclk is used its rate has to
269 * then the function falls back on using PCLK as clock source for PIT64B timer
276 * PMC +------------------------------------+
277 * +----+ | +-----+ |
278 * | |-->gclk -->|-->| | +---------+ +-----+ |
279 * | | | | MUX |--->| Divider |->|timer| |
280 * | |-->pclk -->|-->| | +---------+ +-----+ |
281 * +----+ | +-----+ |
284 * +------------------------------------+
287 * - gclk rate <= pclk rate/3
288 * - gclk rate could be requested from PMC
289 * - pclk rate is fixed (cannot be requested from PMC)
291 static int __init mchp_pit64b_init_mode(struct mchp_pit64b_timer *timer, in mchp_pit64b_init_mode() argument
298 pclk_rate = clk_get_rate(timer->pclk); in mchp_pit64b_init_mode()
300 return -EINVAL; in mchp_pit64b_init_mode()
302 timer->mode = 0; in mchp_pit64b_init_mode()
305 gclk_round = clk_round_rate(timer->gclk, max_rate); in mchp_pit64b_init_mode()
313 best_diff = abs(gclk_round / (pres + 1) - max_rate); in mchp_pit64b_init_mode()
317 timer->mode |= MCHP_PIT64B_MR_SGCLK; in mchp_pit64b_init_mode()
318 clk_set_rate(timer->gclk, gclk_round); in mchp_pit64b_init_mode()
325 diff = abs(pclk_rate / (pres + 1) - max_rate); in mchp_pit64b_init_mode()
332 timer->mode |= MCHP_PIT64B_MR_SGCLK; in mchp_pit64b_init_mode()
333 clk_set_rate(timer->gclk, gclk_round); in mchp_pit64b_init_mode()
337 timer->mode |= MCHP_PIT64B_PRES_TO_MODE(best_pres); in mchp_pit64b_init_mode()
340 timer->mode & MCHP_PIT64B_MR_SGCLK ? "gclk" : "pclk", best_pres, in mchp_pit64b_init_mode()
341 timer->mode & MCHP_PIT64B_MR_SGCLK ? in mchp_pit64b_init_mode()
347 static int __init mchp_pit64b_init_clksrc(struct mchp_pit64b_timer *timer, in mchp_pit64b_init_clksrc() argument
355 return -ENOMEM; in mchp_pit64b_init_clksrc()
357 mchp_pit64b_resume(timer); in mchp_pit64b_init_clksrc()
358 mchp_pit64b_reset(timer, ULLONG_MAX, MCHP_PIT64B_MR_CONT, 0); in mchp_pit64b_init_clksrc()
360 mchp_pit64b_cs_base = timer->base; in mchp_pit64b_init_clksrc()
362 cs->timer.base = timer->base; in mchp_pit64b_init_clksrc()
363 cs->timer.pclk = timer->pclk; in mchp_pit64b_init_clksrc()
364 cs->timer.gclk = timer->gclk; in mchp_pit64b_init_clksrc()
365 cs->timer.mode = timer->mode; in mchp_pit64b_init_clksrc()
366 cs->clksrc.name = MCHP_PIT64B_NAME; in mchp_pit64b_init_clksrc()
367 cs->clksrc.mask = CLOCKSOURCE_MASK(64); in mchp_pit64b_init_clksrc()
368 cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; in mchp_pit64b_init_clksrc()
369 cs->clksrc.rating = 210; in mchp_pit64b_init_clksrc()
370 cs->clksrc.read = mchp_pit64b_clksrc_read; in mchp_pit64b_init_clksrc()
371 cs->clksrc.suspend = mchp_pit64b_clksrc_suspend; in mchp_pit64b_init_clksrc()
372 cs->clksrc.resume = mchp_pit64b_clksrc_resume; in mchp_pit64b_init_clksrc()
374 ret = clocksource_register_hz(&cs->clksrc, clk_rate); in mchp_pit64b_init_clksrc()
378 /* Stop timer. */ in mchp_pit64b_init_clksrc()
379 mchp_pit64b_suspend(timer); in mchp_pit64b_init_clksrc()
394 static int __init mchp_pit64b_init_clkevt(struct mchp_pit64b_timer *timer, in mchp_pit64b_init_clkevt() argument
402 return -ENOMEM; in mchp_pit64b_init_clkevt()
406 ce->timer.base = timer->base; in mchp_pit64b_init_clkevt()
407 ce->timer.pclk = timer->pclk; in mchp_pit64b_init_clkevt()
408 ce->timer.gclk = timer->gclk; in mchp_pit64b_init_clkevt()
409 ce->timer.mode = timer->mode; in mchp_pit64b_init_clkevt()
410 ce->clkevt.name = MCHP_PIT64B_NAME; in mchp_pit64b_init_clkevt()
411 ce->clkevt.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC; in mchp_pit64b_init_clkevt()
412 ce->clkevt.rating = 150; in mchp_pit64b_init_clkevt()
413 ce->clkevt.set_state_shutdown = mchp_pit64b_clkevt_shutdown; in mchp_pit64b_init_clkevt()
414 ce->clkevt.set_state_periodic = mchp_pit64b_clkevt_set_periodic; in mchp_pit64b_init_clkevt()
415 ce->clkevt.set_state_oneshot = mchp_pit64b_clkevt_set_oneshot; in mchp_pit64b_init_clkevt()
416 ce->clkevt.set_next_event = mchp_pit64b_clkevt_set_next_event; in mchp_pit64b_init_clkevt()
417 ce->clkevt.cpumask = cpumask_of(0); in mchp_pit64b_init_clkevt()
418 ce->clkevt.irq = irq; in mchp_pit64b_init_clkevt()
428 clockevents_config_and_register(&ce->clkevt, clk_rate, 1, ULONG_MAX); in mchp_pit64b_init_clkevt()
436 struct mchp_pit64b_timer timer; in mchp_pit64b_dt_init_timer() local
442 timer.pclk = of_clk_get_by_name(node, "pclk"); in mchp_pit64b_dt_init_timer()
443 if (IS_ERR(timer.pclk)) in mchp_pit64b_dt_init_timer()
444 return PTR_ERR(timer.pclk); in mchp_pit64b_dt_init_timer()
446 timer.gclk = of_clk_get_by_name(node, "gclk"); in mchp_pit64b_dt_init_timer()
447 if (IS_ERR(timer.gclk)) in mchp_pit64b_dt_init_timer()
448 return PTR_ERR(timer.gclk); in mchp_pit64b_dt_init_timer()
450 timer.base = of_iomap(node, 0); in mchp_pit64b_dt_init_timer()
451 if (!timer.base) in mchp_pit64b_dt_init_timer()
452 return -ENXIO; in mchp_pit64b_dt_init_timer()
457 ret = -ENODEV; in mchp_pit64b_dt_init_timer()
463 ret = mchp_pit64b_init_mode(&timer, MCHP_PIT64B_DEF_FREQ); in mchp_pit64b_dt_init_timer()
467 if (timer.mode & MCHP_PIT64B_MR_SGCLK) in mchp_pit64b_dt_init_timer()
468 clk_rate = clk_get_rate(timer.gclk); in mchp_pit64b_dt_init_timer()
470 clk_rate = clk_get_rate(timer.pclk); in mchp_pit64b_dt_init_timer()
471 clk_rate = clk_rate / (MCHP_PIT64B_MODE_TO_PRES(timer.mode) + 1); in mchp_pit64b_dt_init_timer()
474 ret = mchp_pit64b_init_clkevt(&timer, clk_rate, irq); in mchp_pit64b_dt_init_timer()
476 ret = mchp_pit64b_init_clksrc(&timer, clk_rate); in mchp_pit64b_dt_init_timer()
486 iounmap(timer.base); in mchp_pit64b_dt_init_timer()
505 return -EINVAL; in mchp_pit64b_dt_init()
508 TIMER_OF_DECLARE(mchp_pit64b, "microchip,sam9x60-pit64b", mchp_pit64b_dt_init);