Lines Matching +full:cs +full:- +full:3

1 // SPDX-License-Identifier: GPL-2.0
3 * 64-bit Periodic Interval Timer driver
25 #define MCHP_PIT64B_MR_SGCLK BIT(3)
51 * struct mchp_pit64b_timer - PIT64B timer data structure
65 * mchp_pit64b_clkevt - PIT64B clockevent data structure
79 * mchp_pit64b_clksrc - PIT64B clocksource data structure
125 writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_reset()
126 writel_relaxed(mode | timer->mode, timer->base + MCHP_PIT64B_MR); in mchp_pit64b_reset()
127 writel_relaxed(high, timer->base + MCHP_PIT64B_MSB_PR); in mchp_pit64b_reset()
128 writel_relaxed(low, timer->base + MCHP_PIT64B_LSB_PR); in mchp_pit64b_reset()
129 writel_relaxed(irqs, timer->base + MCHP_PIT64B_IER); in mchp_pit64b_reset()
130 writel_relaxed(MCHP_PIT64B_CR_START, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_reset()
135 writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_suspend()
136 if (timer->mode & MCHP_PIT64B_MR_SGCLK) in mchp_pit64b_suspend()
137 clk_disable_unprepare(timer->gclk); in mchp_pit64b_suspend()
138 clk_disable_unprepare(timer->pclk); in mchp_pit64b_suspend()
143 clk_prepare_enable(timer->pclk); in mchp_pit64b_resume()
144 if (timer->mode & MCHP_PIT64B_MR_SGCLK) in mchp_pit64b_resume()
145 clk_prepare_enable(timer->gclk); in mchp_pit64b_resume()
148 static void mchp_pit64b_clksrc_suspend(struct clocksource *cs) in mchp_pit64b_clksrc_suspend() argument
150 struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs); in mchp_pit64b_clksrc_suspend()
155 static void mchp_pit64b_clksrc_resume(struct clocksource *cs) in mchp_pit64b_clksrc_resume() argument
157 struct mchp_pit64b_timer *timer = clksrc_to_mchp_pit64b_timer(cs); in mchp_pit64b_clksrc_resume()
163 static u64 mchp_pit64b_clksrc_read(struct clocksource *cs) in mchp_pit64b_clksrc_read() argument
177 writel_relaxed(MCHP_PIT64B_CR_SWRST, timer->base + MCHP_PIT64B_CR); in mchp_pit64b_clkevt_shutdown()
222 readl_relaxed(irq_data->timer.base + MCHP_PIT64B_ISR); in mchp_pit64b_interrupt()
224 irq_data->clkevt.event_handler(&irq_data->clkevt); in mchp_pit64b_interrupt()
242 *pres = MCHP_PIT64B_PRES_MAX - 1; in mchp_pit64b_pres_compute()
246 * mchp_pit64b_init_mode - prepare PIT64B mode register value to be used at
250 * be at least 3 times lower that pclk's rate. pclk rate is fixed, gclk rate
256 * requested rate. If PCLK/GCLK < 3 (condition requested by PIT64B hardware)
264 * PMC +------------------------------------+
265 * +----+ | +-----+ |
266 * | |-->gclk -->|-->| | +---------+ +-----+ |
267 * | | | | MUX |--->| Divider |->|timer| |
268 * | |-->pclk -->|-->| | +---------+ +-----+ |
269 * +----+ | +-----+ |
272 * +------------------------------------+
275 * - gclk rate <= pclk rate/3
276 * - gclk rate could be requested from PMC
277 * - pclk rate is fixed (cannot be requested from PMC)
286 pclk_rate = clk_get_rate(timer->pclk); in mchp_pit64b_init_mode()
288 return -EINVAL; in mchp_pit64b_init_mode()
290 timer->mode = 0; in mchp_pit64b_init_mode()
293 gclk_round = clk_round_rate(timer->gclk, max_rate); in mchp_pit64b_init_mode()
297 if (pclk_rate / gclk_round < 3) in mchp_pit64b_init_mode()
301 best_diff = abs(gclk_round / (pres + 1) - max_rate); in mchp_pit64b_init_mode()
305 timer->mode |= MCHP_PIT64B_MR_SGCLK; in mchp_pit64b_init_mode()
306 clk_set_rate(timer->gclk, gclk_round); in mchp_pit64b_init_mode()
313 diff = abs(pclk_rate / (pres + 1) - max_rate); in mchp_pit64b_init_mode()
320 timer->mode |= MCHP_PIT64B_MR_SGCLK; in mchp_pit64b_init_mode()
321 clk_set_rate(timer->gclk, gclk_round); in mchp_pit64b_init_mode()
325 timer->mode |= MCHP_PIT64B_PRES_TO_MODE(best_pres); in mchp_pit64b_init_mode()
328 timer->mode & MCHP_PIT64B_MR_SGCLK ? "gclk" : "pclk", best_pres, in mchp_pit64b_init_mode()
329 timer->mode & MCHP_PIT64B_MR_SGCLK ? in mchp_pit64b_init_mode()
338 struct mchp_pit64b_clksrc *cs; in mchp_pit64b_init_clksrc() local
341 cs = kzalloc(sizeof(*cs), GFP_KERNEL); in mchp_pit64b_init_clksrc()
342 if (!cs) in mchp_pit64b_init_clksrc()
343 return -ENOMEM; in mchp_pit64b_init_clksrc()
347 mchp_pit64b_cs_base = timer->base; in mchp_pit64b_init_clksrc()
349 cs->timer.base = timer->base; in mchp_pit64b_init_clksrc()
350 cs->timer.pclk = timer->pclk; in mchp_pit64b_init_clksrc()
351 cs->timer.gclk = timer->gclk; in mchp_pit64b_init_clksrc()
352 cs->timer.mode = timer->mode; in mchp_pit64b_init_clksrc()
353 cs->clksrc.name = MCHP_PIT64B_NAME; in mchp_pit64b_init_clksrc()
354 cs->clksrc.mask = CLOCKSOURCE_MASK(64); in mchp_pit64b_init_clksrc()
355 cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; in mchp_pit64b_init_clksrc()
356 cs->clksrc.rating = 210; in mchp_pit64b_init_clksrc()
357 cs->clksrc.read = mchp_pit64b_clksrc_read; in mchp_pit64b_init_clksrc()
358 cs->clksrc.suspend = mchp_pit64b_clksrc_suspend; in mchp_pit64b_init_clksrc()
359 cs->clksrc.resume = mchp_pit64b_clksrc_resume; in mchp_pit64b_init_clksrc()
361 ret = clocksource_register_hz(&cs->clksrc, clk_rate); in mchp_pit64b_init_clksrc()
367 timer->base + MCHP_PIT64B_CR); in mchp_pit64b_init_clksrc()
368 kfree(cs); in mchp_pit64b_init_clksrc()
386 return -ENOMEM; in mchp_pit64b_init_clkevt()
390 ce->timer.base = timer->base; in mchp_pit64b_init_clkevt()
391 ce->timer.pclk = timer->pclk; in mchp_pit64b_init_clkevt()
392 ce->timer.gclk = timer->gclk; in mchp_pit64b_init_clkevt()
393 ce->timer.mode = timer->mode; in mchp_pit64b_init_clkevt()
394 ce->clkevt.name = MCHP_PIT64B_NAME; in mchp_pit64b_init_clkevt()
395 ce->clkevt.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC; in mchp_pit64b_init_clkevt()
396 ce->clkevt.rating = 150; in mchp_pit64b_init_clkevt()
397 ce->clkevt.set_state_shutdown = mchp_pit64b_clkevt_shutdown; in mchp_pit64b_init_clkevt()
398 ce->clkevt.set_state_periodic = mchp_pit64b_clkevt_set_periodic; in mchp_pit64b_init_clkevt()
399 ce->clkevt.set_next_event = mchp_pit64b_clkevt_set_next_event; in mchp_pit64b_init_clkevt()
400 ce->clkevt.suspend = mchp_pit64b_clkevt_suspend; in mchp_pit64b_init_clkevt()
401 ce->clkevt.resume = mchp_pit64b_clkevt_resume; in mchp_pit64b_init_clkevt()
402 ce->clkevt.cpumask = cpumask_of(0); in mchp_pit64b_init_clkevt()
403 ce->clkevt.irq = irq; in mchp_pit64b_init_clkevt()
413 clockevents_config_and_register(&ce->clkevt, clk_rate, 1, ULONG_MAX); in mchp_pit64b_init_clkevt()
438 return -ENXIO; in mchp_pit64b_dt_init_timer()
443 ret = -ENODEV; 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);