Lines Matching +full:pre +full:- +full:scaling
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2011-2013 Xilinx
22 * This driver configures the 2 16/32-bit count-up timers as follows:
29 * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
33 * obtained from device tree. The pre-scaler of 32 is used.
54 * Setup the timers to use pre-scaling, using a fixed value for now that will
59 #define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1)
66 * struct ttc_timer - This definition defines local timer structure
104 * ttc_set_interval - Set the timer interval value
114 /* Disable the counter, set the counter value and re-enable counter */ in ttc_set_interval()
115 ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_set_interval()
117 writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_set_interval()
119 writel_relaxed(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); in ttc_set_interval()
122 * Reset the counter (0x10) so that it starts from 0, one-shot in ttc_set_interval()
127 writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_set_interval()
131 * ttc_clock_event_interrupt - Clock event timer interrupt handler
136 * returns: Always IRQ_HANDLED - success
141 struct ttc_timer *timer = &ttce->ttc; in ttc_clock_event_interrupt()
144 readl_relaxed(timer->base_addr + TTC_ISR_OFFSET); in ttc_clock_event_interrupt()
146 ttce->ce.event_handler(&ttce->ce); in ttc_clock_event_interrupt()
152 * __ttc_clocksource_read - Reads the timer counter register
158 struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; in __ttc_clocksource_read()
160 return (u64)readl_relaxed(timer->base_addr + in __ttc_clocksource_read()
170 * ttc_set_next_event - Sets the time interval for next event
175 * returns: Always 0 - success
181 struct ttc_timer *timer = &ttce->ttc; in ttc_set_next_event()
188 * ttc_set_{shutdown|oneshot|periodic} - Sets the state of timer
195 struct ttc_timer *timer = &ttce->ttc; in ttc_shutdown()
198 ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_shutdown()
200 writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_shutdown()
207 struct ttc_timer *timer = &ttce->ttc; in ttc_set_periodic()
210 DIV_ROUND_CLOSEST(ttce->ttc.freq, PRESCALE * HZ)); in ttc_set_periodic()
217 struct ttc_timer *timer = &ttce->ttc; in ttc_resume()
220 ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_resume()
222 writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_resume()
240 if (ndata->new_rate > ndata->old_rate) { in ttc_rate_change_clocksource_cb()
241 factor = DIV_ROUND_CLOSEST(ndata->new_rate, in ttc_rate_change_clocksource_cb()
242 ndata->old_rate); in ttc_rate_change_clocksource_cb()
243 rate_low = ndata->old_rate; in ttc_rate_change_clocksource_cb()
244 rate_high = ndata->new_rate; in ttc_rate_change_clocksource_cb()
246 factor = DIV_ROUND_CLOSEST(ndata->old_rate, in ttc_rate_change_clocksource_cb()
247 ndata->new_rate); in ttc_rate_change_clocksource_cb()
248 rate_low = ndata->new_rate; in ttc_rate_change_clocksource_cb()
249 rate_high = ndata->old_rate; in ttc_rate_change_clocksource_cb()
255 if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR) in ttc_rate_change_clocksource_cb()
264 ttccs->scale_clk_ctrl_reg_old = in ttc_rate_change_clocksource_cb()
265 readl_relaxed(ttccs->ttc.base_addr + in ttc_rate_change_clocksource_cb()
268 psv = (ttccs->scale_clk_ctrl_reg_old & in ttc_rate_change_clocksource_cb()
271 if (ndata->new_rate < ndata->old_rate) in ttc_rate_change_clocksource_cb()
272 psv -= factor; in ttc_rate_change_clocksource_cb()
280 ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old & in ttc_rate_change_clocksource_cb()
282 ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT; in ttc_rate_change_clocksource_cb()
285 /* scale down: adjust divider in post-change notification */ in ttc_rate_change_clocksource_cb()
286 if (ndata->new_rate < ndata->old_rate) in ttc_rate_change_clocksource_cb()
289 /* scale up: adjust divider now - before frequency change */ in ttc_rate_change_clocksource_cb()
290 writel_relaxed(ttccs->scale_clk_ctrl_reg_new, in ttc_rate_change_clocksource_cb()
291 ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); in ttc_rate_change_clocksource_cb()
295 /* scale up: pre-change notification did the adjustment */ in ttc_rate_change_clocksource_cb()
296 if (ndata->new_rate > ndata->old_rate) in ttc_rate_change_clocksource_cb()
299 /* scale down: adjust divider now - after frequency change */ in ttc_rate_change_clocksource_cb()
300 writel_relaxed(ttccs->scale_clk_ctrl_reg_new, in ttc_rate_change_clocksource_cb()
301 ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); in ttc_rate_change_clocksource_cb()
306 if (ndata->new_rate < ndata->old_rate) in ttc_rate_change_clocksource_cb()
310 writel_relaxed(ttccs->scale_clk_ctrl_reg_old, in ttc_rate_change_clocksource_cb()
311 ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); in ttc_rate_change_clocksource_cb()
328 return -ENOMEM; in ttc_setup_clocksource()
330 ttccs->ttc.clk = clk; in ttc_setup_clocksource()
332 err = clk_prepare_enable(ttccs->ttc.clk); in ttc_setup_clocksource()
338 ttccs->ttc.freq = clk_get_rate(ttccs->ttc.clk); in ttc_setup_clocksource()
340 ttccs->ttc.clk_rate_change_nb.notifier_call = in ttc_setup_clocksource()
342 ttccs->ttc.clk_rate_change_nb.next = NULL; in ttc_setup_clocksource()
344 err = clk_notifier_register(ttccs->ttc.clk, in ttc_setup_clocksource()
345 &ttccs->ttc.clk_rate_change_nb); in ttc_setup_clocksource()
349 ttccs->ttc.base_addr = base; in ttc_setup_clocksource()
350 ttccs->cs.name = "ttc_clocksource"; in ttc_setup_clocksource()
351 ttccs->cs.rating = 200; in ttc_setup_clocksource()
352 ttccs->cs.read = __ttc_clocksource_read; in ttc_setup_clocksource()
353 ttccs->cs.mask = CLOCKSOURCE_MASK(timer_width); in ttc_setup_clocksource()
354 ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; in ttc_setup_clocksource()
358 * with no interrupt and it rolls over at 0xFFFF. Pre-scale in ttc_setup_clocksource()
361 writel_relaxed(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); in ttc_setup_clocksource()
363 ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); in ttc_setup_clocksource()
365 ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_setup_clocksource()
367 err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); in ttc_setup_clocksource()
375 ttccs->ttc.freq / PRESCALE); in ttc_setup_clocksource()
391 ttc->freq = ndata->new_rate; in ttc_rate_change_clockevent_cb()
393 clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); in ttc_rate_change_clockevent_cb()
411 return -ENOMEM; in ttc_setup_clockevent()
413 ttcce->ttc.clk = clk; in ttc_setup_clockevent()
415 err = clk_prepare_enable(ttcce->ttc.clk); in ttc_setup_clockevent()
421 ttcce->ttc.clk_rate_change_nb.notifier_call = in ttc_setup_clockevent()
423 ttcce->ttc.clk_rate_change_nb.next = NULL; in ttc_setup_clockevent()
425 err = clk_notifier_register(ttcce->ttc.clk, in ttc_setup_clockevent()
426 &ttcce->ttc.clk_rate_change_nb); in ttc_setup_clockevent()
432 ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); in ttc_setup_clockevent()
434 ttcce->ttc.base_addr = base; in ttc_setup_clockevent()
435 ttcce->ce.name = "ttc_clockevent"; in ttc_setup_clockevent()
436 ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; in ttc_setup_clockevent()
437 ttcce->ce.set_next_event = ttc_set_next_event; in ttc_setup_clockevent()
438 ttcce->ce.set_state_shutdown = ttc_shutdown; in ttc_setup_clockevent()
439 ttcce->ce.set_state_periodic = ttc_set_periodic; in ttc_setup_clockevent()
440 ttcce->ce.set_state_oneshot = ttc_shutdown; in ttc_setup_clockevent()
441 ttcce->ce.tick_resume = ttc_resume; in ttc_setup_clockevent()
442 ttcce->ce.rating = 200; in ttc_setup_clockevent()
443 ttcce->ce.irq = irq; in ttc_setup_clockevent()
444 ttcce->ce.cpumask = cpu_possible_mask; in ttc_setup_clockevent()
451 writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); in ttc_setup_clockevent()
453 ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); in ttc_setup_clockevent()
454 writel_relaxed(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); in ttc_setup_clockevent()
457 IRQF_TIMER, ttcce->ce.name, ttcce); in ttc_setup_clockevent()
463 clockevents_config_and_register(&ttcce->ce, in ttc_setup_clockevent()
464 ttcce->ttc.freq / PRESCALE, 1, 0xfffe); in ttc_setup_clockevent()
477 struct device_node *timer = pdev->dev.of_node; in ttc_timer_probe()
492 return -ENXIO; in ttc_timer_probe()
498 return -EINVAL; in ttc_timer_probe()
501 of_property_read_u32(timer, "timer-width", &timer_width); in ttc_timer_probe()