1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e37e4593SMaxime Coquelin /*
3e37e4593SMaxime Coquelin  * Copyright (C) Maxime Coquelin 2015
4e37e4593SMaxime Coquelin  * Author:  Maxime Coquelin <[email protected]>
5e37e4593SMaxime Coquelin  *
6e37e4593SMaxime Coquelin  * Inspired by time-efm32.c from Uwe Kleine-Koenig
7e37e4593SMaxime Coquelin  */
8e37e4593SMaxime Coquelin 
9e37e4593SMaxime Coquelin #include <linux/kernel.h>
10e37e4593SMaxime Coquelin #include <linux/clocksource.h>
11e37e4593SMaxime Coquelin #include <linux/clockchips.h>
1281abdbbfSDaniel Lezcano #include <linux/delay.h>
13e37e4593SMaxime Coquelin #include <linux/irq.h>
14e37e4593SMaxime Coquelin #include <linux/interrupt.h>
15e37e4593SMaxime Coquelin #include <linux/of.h>
16e37e4593SMaxime Coquelin #include <linux/of_address.h>
17e37e4593SMaxime Coquelin #include <linux/of_irq.h>
18e37e4593SMaxime Coquelin #include <linux/clk.h>
19e37e4593SMaxime Coquelin #include <linux/reset.h>
20f5ef02bdSBenjamin Gaignard #include <linux/sched_clock.h>
21d04af490SBenjamin Gaignard #include <linux/slab.h>
22d04af490SBenjamin Gaignard 
23d04af490SBenjamin Gaignard #include "timer-of.h"
24e37e4593SMaxime Coquelin 
25e37e4593SMaxime Coquelin #define TIM_CR1		0x00
26e37e4593SMaxime Coquelin #define TIM_DIER	0x0c
27e37e4593SMaxime Coquelin #define TIM_SR		0x10
28e37e4593SMaxime Coquelin #define TIM_EGR		0x14
298e82df38SBenjamin Gaignard #define TIM_CNT		0x24
30e37e4593SMaxime Coquelin #define TIM_PSC		0x28
31e37e4593SMaxime Coquelin #define TIM_ARR		0x2c
328e82df38SBenjamin Gaignard #define TIM_CCR1	0x34
33e37e4593SMaxime Coquelin 
34e37e4593SMaxime Coquelin #define TIM_CR1_CEN	BIT(0)
358e82df38SBenjamin Gaignard #define TIM_CR1_UDIS	BIT(1)
36e37e4593SMaxime Coquelin #define TIM_CR1_OPM	BIT(3)
37e37e4593SMaxime Coquelin #define TIM_CR1_ARPE	BIT(7)
38e37e4593SMaxime Coquelin 
39e37e4593SMaxime Coquelin #define TIM_DIER_UIE	BIT(0)
408e82df38SBenjamin Gaignard #define TIM_DIER_CC1IE	BIT(1)
41e37e4593SMaxime Coquelin 
42e37e4593SMaxime Coquelin #define TIM_SR_UIF	BIT(0)
43e37e4593SMaxime Coquelin 
44e37e4593SMaxime Coquelin #define TIM_EGR_UG	BIT(0)
45e37e4593SMaxime Coquelin 
464744daa1SBenjamin Gaignard #define TIM_PSC_MAX	USHRT_MAX
474744daa1SBenjamin Gaignard #define TIM_PSC_CLKRATE	10000
484744daa1SBenjamin Gaignard 
493c84e75bSDaniel Lezcano struct stm32_timer_private {
503c84e75bSDaniel Lezcano 	int bits;
513c84e75bSDaniel Lezcano };
523c84e75bSDaniel Lezcano 
533c84e75bSDaniel Lezcano /**
543c84e75bSDaniel Lezcano  * stm32_timer_of_bits_set - set accessor helper
553c84e75bSDaniel Lezcano  * @to: a timer_of structure pointer
563c84e75bSDaniel Lezcano  * @bits: the number of bits (16 or 32)
573c84e75bSDaniel Lezcano  *
583c84e75bSDaniel Lezcano  * Accessor helper to set the number of bits in the timer-of private
593c84e75bSDaniel Lezcano  * structure.
603c84e75bSDaniel Lezcano  *
613c84e75bSDaniel Lezcano  */
stm32_timer_of_bits_set(struct timer_of * to,int bits)623c84e75bSDaniel Lezcano static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
633c84e75bSDaniel Lezcano {
643c84e75bSDaniel Lezcano 	struct stm32_timer_private *pd = to->private_data;
653c84e75bSDaniel Lezcano 
663c84e75bSDaniel Lezcano 	pd->bits = bits;
673c84e75bSDaniel Lezcano }
683c84e75bSDaniel Lezcano 
693c84e75bSDaniel Lezcano /**
703c84e75bSDaniel Lezcano  * stm32_timer_of_bits_get - get accessor helper
713c84e75bSDaniel Lezcano  * @to: a timer_of structure pointer
723c84e75bSDaniel Lezcano  *
733c84e75bSDaniel Lezcano  * Accessor helper to get the number of bits in the timer-of private
743c84e75bSDaniel Lezcano  * structure.
753c84e75bSDaniel Lezcano  *
76*906fed29SRandy Dunlap  * Returns: an integer corresponding to the number of bits.
773c84e75bSDaniel Lezcano  */
stm32_timer_of_bits_get(struct timer_of * to)783c84e75bSDaniel Lezcano static int stm32_timer_of_bits_get(struct timer_of *to)
793c84e75bSDaniel Lezcano {
803c84e75bSDaniel Lezcano 	struct stm32_timer_private *pd = to->private_data;
813c84e75bSDaniel Lezcano 
823c84e75bSDaniel Lezcano 	return pd->bits;
833c84e75bSDaniel Lezcano }
843c84e75bSDaniel Lezcano 
85f5ef02bdSBenjamin Gaignard static void __iomem *stm32_timer_cnt __read_mostly;
86f5ef02bdSBenjamin Gaignard 
stm32_read_sched_clock(void)87f5ef02bdSBenjamin Gaignard static u64 notrace stm32_read_sched_clock(void)
88f5ef02bdSBenjamin Gaignard {
89f5ef02bdSBenjamin Gaignard 	return readl_relaxed(stm32_timer_cnt);
90f5ef02bdSBenjamin Gaignard }
91f5ef02bdSBenjamin Gaignard 
9281abdbbfSDaniel Lezcano static struct delay_timer stm32_timer_delay;
9381abdbbfSDaniel Lezcano 
stm32_read_delay(void)9481abdbbfSDaniel Lezcano static unsigned long stm32_read_delay(void)
9581abdbbfSDaniel Lezcano {
9681abdbbfSDaniel Lezcano 	return readl_relaxed(stm32_timer_cnt);
9781abdbbfSDaniel Lezcano }
9881abdbbfSDaniel Lezcano 
stm32_clock_event_disable(struct timer_of * to)998e82df38SBenjamin Gaignard static void stm32_clock_event_disable(struct timer_of *to)
1008e82df38SBenjamin Gaignard {
1018e82df38SBenjamin Gaignard 	writel_relaxed(0, timer_of_base(to) + TIM_DIER);
1028e82df38SBenjamin Gaignard }
1038e82df38SBenjamin Gaignard 
104103bb56aSDaniel Lezcano /**
105103bb56aSDaniel Lezcano  * stm32_timer_start - Start the counter without event
106103bb56aSDaniel Lezcano  * @to: a timer_of structure pointer
107103bb56aSDaniel Lezcano  *
108103bb56aSDaniel Lezcano  * Start the timer in order to have the counter reset and start
109103bb56aSDaniel Lezcano  * incrementing but disable interrupt event when there is a counter
110103bb56aSDaniel Lezcano  * overflow. By default, the counter direction is used as upcounter.
111103bb56aSDaniel Lezcano  */
stm32_timer_start(struct timer_of * to)112103bb56aSDaniel Lezcano static void stm32_timer_start(struct timer_of *to)
1138e82df38SBenjamin Gaignard {
1148e82df38SBenjamin Gaignard 	writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
1158e82df38SBenjamin Gaignard }
1168e82df38SBenjamin Gaignard 
stm32_clock_event_shutdown(struct clock_event_device * clkevt)117d04af490SBenjamin Gaignard static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
118e37e4593SMaxime Coquelin {
119d04af490SBenjamin Gaignard 	struct timer_of *to = to_timer_of(clkevt);
120e37e4593SMaxime Coquelin 
1218e82df38SBenjamin Gaignard 	stm32_clock_event_disable(to);
122d04af490SBenjamin Gaignard 
1238e8af4cdSViresh Kumar 	return 0;
124e37e4593SMaxime Coquelin }
125e37e4593SMaxime Coquelin 
stm32_clock_event_set_next_event(unsigned long evt,struct clock_event_device * clkevt)126e37e4593SMaxime Coquelin static int stm32_clock_event_set_next_event(unsigned long evt,
127d04af490SBenjamin Gaignard 					    struct clock_event_device *clkevt)
128e37e4593SMaxime Coquelin {
129d04af490SBenjamin Gaignard 	struct timer_of *to = to_timer_of(clkevt);
1308e82df38SBenjamin Gaignard 	unsigned long now, next;
131e37e4593SMaxime Coquelin 
1328e82df38SBenjamin Gaignard 	next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
1338e82df38SBenjamin Gaignard 	writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
1348e82df38SBenjamin Gaignard 	now = readl_relaxed(timer_of_base(to) + TIM_CNT);
1358e82df38SBenjamin Gaignard 
1368e82df38SBenjamin Gaignard 	if ((next - now) > evt)
1378e82df38SBenjamin Gaignard 		return -ETIME;
1388e82df38SBenjamin Gaignard 
1398e82df38SBenjamin Gaignard 	writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
1408e82df38SBenjamin Gaignard 
1418e82df38SBenjamin Gaignard 	return 0;
1428e82df38SBenjamin Gaignard }
1438e82df38SBenjamin Gaignard 
stm32_clock_event_set_periodic(struct clock_event_device * clkevt)1448e82df38SBenjamin Gaignard static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
1458e82df38SBenjamin Gaignard {
1468e82df38SBenjamin Gaignard 	struct timer_of *to = to_timer_of(clkevt);
1478e82df38SBenjamin Gaignard 
148103bb56aSDaniel Lezcano 	stm32_timer_start(to);
1498e82df38SBenjamin Gaignard 
1508e82df38SBenjamin Gaignard 	return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
1518e82df38SBenjamin Gaignard }
1528e82df38SBenjamin Gaignard 
stm32_clock_event_set_oneshot(struct clock_event_device * clkevt)1538e82df38SBenjamin Gaignard static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
1548e82df38SBenjamin Gaignard {
1558e82df38SBenjamin Gaignard 	struct timer_of *to = to_timer_of(clkevt);
1568e82df38SBenjamin Gaignard 
157103bb56aSDaniel Lezcano 	stm32_timer_start(to);
158e37e4593SMaxime Coquelin 
159e37e4593SMaxime Coquelin 	return 0;
160e37e4593SMaxime Coquelin }
161e37e4593SMaxime Coquelin 
stm32_clock_event_handler(int irq,void * dev_id)162e37e4593SMaxime Coquelin static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
163e37e4593SMaxime Coquelin {
164d04af490SBenjamin Gaignard 	struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
165d04af490SBenjamin Gaignard 	struct timer_of *to = to_timer_of(clkevt);
166e37e4593SMaxime Coquelin 
167d04af490SBenjamin Gaignard 	writel_relaxed(0, timer_of_base(to) + TIM_SR);
168e37e4593SMaxime Coquelin 
1698e82df38SBenjamin Gaignard 	if (clockevent_state_periodic(clkevt))
1708e82df38SBenjamin Gaignard 		stm32_clock_event_set_periodic(clkevt);
1718e82df38SBenjamin Gaignard 	else
1728e82df38SBenjamin Gaignard 		stm32_clock_event_shutdown(clkevt);
1738e82df38SBenjamin Gaignard 
174d04af490SBenjamin Gaignard 	clkevt->event_handler(clkevt);
175e37e4593SMaxime Coquelin 
176e37e4593SMaxime Coquelin 	return IRQ_HANDLED;
177e37e4593SMaxime Coquelin }
178e37e4593SMaxime Coquelin 
17970c62cf9SDaniel Lezcano /**
180*906fed29SRandy Dunlap  * stm32_timer_set_width - Sort out the timer width (32/16)
18170c62cf9SDaniel Lezcano  * @to: a pointer to a timer-of structure
18270c62cf9SDaniel Lezcano  *
18370c62cf9SDaniel Lezcano  * Write the 32-bit max value and read/return the result. If the timer
18470c62cf9SDaniel Lezcano  * is 32 bits wide, the result will be UINT_MAX, otherwise it will
18570c62cf9SDaniel Lezcano  * be truncated by the 16-bit register to USHRT_MAX.
18670c62cf9SDaniel Lezcano  *
18770c62cf9SDaniel Lezcano  */
stm32_timer_set_width(struct timer_of * to)1883c84e75bSDaniel Lezcano static void __init stm32_timer_set_width(struct timer_of *to)
18970c62cf9SDaniel Lezcano {
1903c84e75bSDaniel Lezcano 	u32 width;
1913c84e75bSDaniel Lezcano 
19270c62cf9SDaniel Lezcano 	writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
19370c62cf9SDaniel Lezcano 
1943c84e75bSDaniel Lezcano 	width = readl_relaxed(timer_of_base(to) + TIM_ARR);
1953c84e75bSDaniel Lezcano 
1963c84e75bSDaniel Lezcano 	stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
19770c62cf9SDaniel Lezcano }
19870c62cf9SDaniel Lezcano 
1993c84e75bSDaniel Lezcano /**
2003c84e75bSDaniel Lezcano  * stm32_timer_set_prescaler - Compute and set the prescaler register
2013c84e75bSDaniel Lezcano  * @to: a pointer to a timer-of structure
2023c84e75bSDaniel Lezcano  *
2033c84e75bSDaniel Lezcano  * Depending on the timer width, compute the prescaler to always
2043c84e75bSDaniel Lezcano  * target a 10MHz timer rate for 16 bits. 32-bit timers are
2053c84e75bSDaniel Lezcano  * considered precise and long enough to not use the prescaler.
2063c84e75bSDaniel Lezcano  */
stm32_timer_set_prescaler(struct timer_of * to)2073c84e75bSDaniel Lezcano static void __init stm32_timer_set_prescaler(struct timer_of *to)
208e37e4593SMaxime Coquelin {
2093c84e75bSDaniel Lezcano 	int prescaler = 1;
210e37e4593SMaxime Coquelin 
2113c84e75bSDaniel Lezcano 	if (stm32_timer_of_bits_get(to) != 32) {
2124744daa1SBenjamin Gaignard 		prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
2134744daa1SBenjamin Gaignard 					      TIM_PSC_CLKRATE);
2144744daa1SBenjamin Gaignard 		/*
2154744daa1SBenjamin Gaignard 		 * The prescaler register is an u16, the variable
2164744daa1SBenjamin Gaignard 		 * can't be greater than TIM_PSC_MAX, let's cap it in
2174744daa1SBenjamin Gaignard 		 * this case.
2184744daa1SBenjamin Gaignard 		 */
2194744daa1SBenjamin Gaignard 		prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
220d04af490SBenjamin Gaignard 	}
221d04af490SBenjamin Gaignard 
222d04af490SBenjamin Gaignard 	writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
223d04af490SBenjamin Gaignard 	writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
224d04af490SBenjamin Gaignard 	writel_relaxed(0, timer_of_base(to) + TIM_SR);
225d04af490SBenjamin Gaignard 
226d04af490SBenjamin Gaignard 	/* Adjust rate and period given the prescaler value */
227d04af490SBenjamin Gaignard 	to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
228d04af490SBenjamin Gaignard 	to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
2293c84e75bSDaniel Lezcano }
230d04af490SBenjamin Gaignard 
stm32_clocksource_init(struct timer_of * to)231f5ef02bdSBenjamin Gaignard static int __init stm32_clocksource_init(struct timer_of *to)
232f5ef02bdSBenjamin Gaignard {
233f5ef02bdSBenjamin Gaignard         u32 bits = stm32_timer_of_bits_get(to);
234f5ef02bdSBenjamin Gaignard 	const char *name = to->np->full_name;
235f5ef02bdSBenjamin Gaignard 
236f5ef02bdSBenjamin Gaignard 	/*
237f5ef02bdSBenjamin Gaignard 	 * This driver allows to register several timers and relies on
238f5ef02bdSBenjamin Gaignard 	 * the generic time framework to select the right one.
239f5ef02bdSBenjamin Gaignard 	 * However, nothing allows to do the same for the
240f5ef02bdSBenjamin Gaignard 	 * sched_clock. We are not interested in a sched_clock for the
241f5ef02bdSBenjamin Gaignard 	 * 16-bit timers but only for the 32-bit one, so if no 32-bit
242f5ef02bdSBenjamin Gaignard 	 * timer is registered yet, we select this 32-bit timer as a
243f5ef02bdSBenjamin Gaignard 	 * sched_clock.
244f5ef02bdSBenjamin Gaignard 	 */
245f5ef02bdSBenjamin Gaignard 	if (bits == 32 && !stm32_timer_cnt) {
246103bb56aSDaniel Lezcano 
247103bb56aSDaniel Lezcano 		/*
248103bb56aSDaniel Lezcano 		 * Start immediately the counter as we will be using
249103bb56aSDaniel Lezcano 		 * it right after.
250103bb56aSDaniel Lezcano 		 */
251103bb56aSDaniel Lezcano 		stm32_timer_start(to);
252103bb56aSDaniel Lezcano 
253f5ef02bdSBenjamin Gaignard 		stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
254f5ef02bdSBenjamin Gaignard 		sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
255f5ef02bdSBenjamin Gaignard 		pr_info("%s: STM32 sched_clock registered\n", name);
25681abdbbfSDaniel Lezcano 
25781abdbbfSDaniel Lezcano 		stm32_timer_delay.read_current_timer = stm32_read_delay;
25881abdbbfSDaniel Lezcano 		stm32_timer_delay.freq = timer_of_rate(to);
25981abdbbfSDaniel Lezcano 		register_current_timer_delay(&stm32_timer_delay);
26081abdbbfSDaniel Lezcano 		pr_info("%s: STM32 delay timer registered\n", name);
261f5ef02bdSBenjamin Gaignard 	}
262f5ef02bdSBenjamin Gaignard 
263f5ef02bdSBenjamin Gaignard 	return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
264f5ef02bdSBenjamin Gaignard 				     timer_of_rate(to), bits == 32 ? 250 : 100,
265f5ef02bdSBenjamin Gaignard 				     bits, clocksource_mmio_readl_up);
266f5ef02bdSBenjamin Gaignard }
267f5ef02bdSBenjamin Gaignard 
stm32_clockevent_init(struct timer_of * to)2683c84e75bSDaniel Lezcano static void __init stm32_clockevent_init(struct timer_of *to)
2693c84e75bSDaniel Lezcano {
2703c84e75bSDaniel Lezcano 	u32 bits = stm32_timer_of_bits_get(to);
2713c84e75bSDaniel Lezcano 
2723c84e75bSDaniel Lezcano 	to->clkevt.name = to->np->full_name;
2733c84e75bSDaniel Lezcano 	to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
2743c84e75bSDaniel Lezcano 	to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
2753c84e75bSDaniel Lezcano 	to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
2763c84e75bSDaniel Lezcano 	to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
2773c84e75bSDaniel Lezcano 	to->clkevt.tick_resume = stm32_clock_event_shutdown;
2783c84e75bSDaniel Lezcano 	to->clkevt.set_next_event = stm32_clock_event_set_next_event;
2793c84e75bSDaniel Lezcano 	to->clkevt.rating = bits == 32 ? 250 : 100;
2803c84e75bSDaniel Lezcano 
2813c84e75bSDaniel Lezcano 	clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
2823c84e75bSDaniel Lezcano 					(1 <<  bits) - 1);
283d04af490SBenjamin Gaignard 
284d04af490SBenjamin Gaignard 	pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
2853c84e75bSDaniel Lezcano 		to->np, bits);
286d04af490SBenjamin Gaignard }
287d04af490SBenjamin Gaignard 
stm32_timer_init(struct device_node * node)288d04af490SBenjamin Gaignard static int __init stm32_timer_init(struct device_node *node)
289d04af490SBenjamin Gaignard {
290d04af490SBenjamin Gaignard 	struct reset_control *rstc;
291d04af490SBenjamin Gaignard 	struct timer_of *to;
292d04af490SBenjamin Gaignard 	int ret;
293d04af490SBenjamin Gaignard 
294d04af490SBenjamin Gaignard 	to = kzalloc(sizeof(*to), GFP_KERNEL);
295d04af490SBenjamin Gaignard 	if (!to)
296e0aeca3dSDaniel Lezcano 		return -ENOMEM;
297e0aeca3dSDaniel Lezcano 
298d04af490SBenjamin Gaignard 	to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
299d04af490SBenjamin Gaignard 	to->of_irq.handler = stm32_clock_event_handler;
300e37e4593SMaxime Coquelin 
301d04af490SBenjamin Gaignard 	ret = timer_of_init(node, to);
302d04af490SBenjamin Gaignard 	if (ret)
303d04af490SBenjamin Gaignard 		goto err;
304e37e4593SMaxime Coquelin 
3053c84e75bSDaniel Lezcano 	to->private_data = kzalloc(sizeof(struct stm32_timer_private),
3063c84e75bSDaniel Lezcano 				   GFP_KERNEL);
307a26ed66cSJulia Lawall 	if (!to->private_data) {
308a26ed66cSJulia Lawall 		ret = -ENOMEM;
3093c84e75bSDaniel Lezcano 		goto deinit;
310a26ed66cSJulia Lawall 	}
3113c84e75bSDaniel Lezcano 
312d04af490SBenjamin Gaignard 	rstc = of_reset_control_get(node, NULL);
313e37e4593SMaxime Coquelin 	if (!IS_ERR(rstc)) {
314e37e4593SMaxime Coquelin 		reset_control_assert(rstc);
315e37e4593SMaxime Coquelin 		reset_control_deassert(rstc);
316e37e4593SMaxime Coquelin 	}
317e37e4593SMaxime Coquelin 
3183c84e75bSDaniel Lezcano 	stm32_timer_set_width(to);
3193c84e75bSDaniel Lezcano 
3203c84e75bSDaniel Lezcano 	stm32_timer_set_prescaler(to);
3213c84e75bSDaniel Lezcano 
322f5ef02bdSBenjamin Gaignard 	ret = stm32_clocksource_init(to);
323f5ef02bdSBenjamin Gaignard 	if (ret)
324f5ef02bdSBenjamin Gaignard 		goto deinit;
325f5ef02bdSBenjamin Gaignard 
326d04af490SBenjamin Gaignard 	stm32_clockevent_init(to);
327d04af490SBenjamin Gaignard 	return 0;
3283c84e75bSDaniel Lezcano 
3293c84e75bSDaniel Lezcano deinit:
3303c84e75bSDaniel Lezcano 	timer_of_cleanup(to);
331d04af490SBenjamin Gaignard err:
332d04af490SBenjamin Gaignard 	kfree(to);
33338d94c5aSDaniel Lezcano 	return ret;
334e37e4593SMaxime Coquelin }
335e37e4593SMaxime Coquelin 
336d04af490SBenjamin Gaignard TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);
337