Lines Matching +full:timer +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0-only
32 #define APBTMR_CONTROL_ENABLE (1 << 0)
33 /* 1: periodic, 0:free running. */
34 #define APBTMR_CONTROL_MODE_PERIODIC (1 << 1)
35 #define APBTMR_CONTROL_INT (1 << 2)
49 static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs) in apbt_readl() argument
51 return readl(timer->base + offs); in apbt_readl()
54 static inline void apbt_writel(struct dw_apb_timer *timer, u32 val, in apbt_writel() argument
57 writel(val, timer->base + offs); in apbt_writel()
60 static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs) in apbt_readl_relaxed() argument
62 return readl_relaxed(timer->base + offs); in apbt_readl_relaxed()
65 static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val, in apbt_writel_relaxed() argument
68 writel_relaxed(val, timer->base + offs); in apbt_writel_relaxed()
71 static void apbt_eoi(struct dw_apb_timer *timer) in apbt_eoi() argument
73 apbt_readl_relaxed(timer, APBTMR_N_EOI); in apbt_eoi()
81 if (!evt->event_handler) { in dw_apb_clockevent_irq()
82 pr_info("Spurious APBT timer interrupt %d\n", irq); in dw_apb_clockevent_irq()
86 if (dw_ced->eoi) in dw_apb_clockevent_irq()
87 dw_ced->eoi(&dw_ced->timer); in dw_apb_clockevent_irq()
89 evt->event_handler(evt); in dw_apb_clockevent_irq()
93 static void apbt_enable_int(struct dw_apb_timer *timer) in apbt_enable_int() argument
95 u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); in apbt_enable_int()
97 apbt_readl(timer, APBTMR_N_EOI); in apbt_enable_int()
99 apbt_writel(timer, ctrl, APBTMR_N_CONTROL); in apbt_enable_int()
108 cpumask_first(evt->cpumask)); in apbt_shutdown()
110 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); in apbt_shutdown()
112 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_shutdown()
122 cpumask_first(evt->cpumask)); in apbt_set_oneshot()
124 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); in apbt_set_oneshot()
126 * set free running mode, this mode will let timer reload max in apbt_set_oneshot()
128 * the next event, therefore emulate the one-shot mode. in apbt_set_oneshot()
133 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_set_oneshot()
135 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_set_oneshot()
138 * DW APB p. 46, load counter with all 1s before starting free in apbt_set_oneshot()
141 apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT); in apbt_set_oneshot()
144 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_set_oneshot()
151 unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); in apbt_set_periodic()
155 cpumask_first(evt->cpumask)); in apbt_set_periodic()
157 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); in apbt_set_periodic()
159 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_set_periodic()
161 * DW APB p. 46, have to disable timer before load counter, in apbt_set_periodic()
165 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_set_periodic()
166 udelay(1); in apbt_set_periodic()
168 apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT); in apbt_set_periodic()
170 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_set_periodic()
179 cpumask_first(evt->cpumask)); in apbt_resume()
181 apbt_enable_int(&dw_ced->timer); in apbt_resume()
191 /* Disable timer */ in apbt_next_event()
192 ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL); in apbt_next_event()
194 apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_next_event()
196 apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); in apbt_next_event()
198 apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); in apbt_next_event()
204 * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
206 * @cpu: The CPU the events will be targeted at or -1 if CPU affiliation
208 * @name: The name used for the timer and the IRQ for it.
209 * @rating: The rating to give the timer.
210 * @base: I/O base for the timer registers.
211 * @irq: The interrupt number to use for the timer.
212 * @freq: The frequency that the timer counts at.
217 * it has been called for a timer then the IRQ will be requested, if not it
231 dw_ced->timer.base = base; in dw_apb_clockevent_init()
232 dw_ced->timer.irq = irq; in dw_apb_clockevent_init()
233 dw_ced->timer.freq = freq; in dw_apb_clockevent_init()
235 clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD); in dw_apb_clockevent_init()
236 dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff, in dw_apb_clockevent_init()
237 &dw_ced->ced); in dw_apb_clockevent_init()
238 dw_ced->ced.max_delta_ticks = 0x7fffffff; in dw_apb_clockevent_init()
239 dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); in dw_apb_clockevent_init()
240 dw_ced->ced.min_delta_ticks = 5000; in dw_apb_clockevent_init()
241 dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu); in dw_apb_clockevent_init()
242 dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | in dw_apb_clockevent_init()
244 dw_ced->ced.set_state_shutdown = apbt_shutdown; in dw_apb_clockevent_init()
245 dw_ced->ced.set_state_periodic = apbt_set_periodic; in dw_apb_clockevent_init()
246 dw_ced->ced.set_state_oneshot = apbt_set_oneshot; in dw_apb_clockevent_init()
247 dw_ced->ced.set_state_oneshot_stopped = apbt_shutdown; in dw_apb_clockevent_init()
248 dw_ced->ced.tick_resume = apbt_resume; in dw_apb_clockevent_init()
249 dw_ced->ced.set_next_event = apbt_next_event; in dw_apb_clockevent_init()
250 dw_ced->ced.irq = dw_ced->timer.irq; in dw_apb_clockevent_init()
251 dw_ced->ced.rating = rating; in dw_apb_clockevent_init()
252 dw_ced->ced.name = name; in dw_apb_clockevent_init()
254 dw_ced->eoi = apbt_eoi; in dw_apb_clockevent_init()
257 dw_ced->ced.name, &dw_ced->ced); in dw_apb_clockevent_init()
259 pr_err("failed to request timer irq\n"); in dw_apb_clockevent_init()
268 * dw_apb_clockevent_register() - register the clock with the generic layer
274 apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL); in dw_apb_clockevent_register()
275 clockevents_register_device(&dw_ced->ced); in dw_apb_clockevent_register()
276 apbt_enable_int(&dw_ced->timer); in dw_apb_clockevent_register()
280 * dw_apb_clocksource_start() - start the clocksource counting.
293 u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); in dw_apb_clocksource_start()
296 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); in dw_apb_clocksource_start()
297 apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT); in dw_apb_clocksource_start()
301 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); in dw_apb_clocksource_start()
312 current_count = apbt_readl_relaxed(&dw_cs->timer, in __apbt_read_clocksource()
327 * dw_apb_clocksource_init() - use an APB timer as a clocksource.
331 * @base: The I/O base for the timer registers.
332 * @freq: The frequency that the timer counts at.
334 * This creates a clocksource using an APB timer but does not yet register it
347 dw_cs->timer.base = base; in dw_apb_clocksource_init()
348 dw_cs->timer.freq = freq; in dw_apb_clocksource_init()
349 dw_cs->cs.name = name; in dw_apb_clocksource_init()
350 dw_cs->cs.rating = rating; in dw_apb_clocksource_init()
351 dw_cs->cs.read = __apbt_read_clocksource; in dw_apb_clocksource_init()
352 dw_cs->cs.mask = CLOCKSOURCE_MASK(32); in dw_apb_clocksource_init()
353 dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; in dw_apb_clocksource_init()
354 dw_cs->cs.resume = apbt_restart_clocksource; in dw_apb_clocksource_init()
360 * dw_apb_clocksource_register() - register the APB clocksource.
366 clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq); in dw_apb_clocksource_register()
370 * dw_apb_clocksource_read() - read the current value of a clocksource.
376 return (u64)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); in dw_apb_clocksource_read()