xref: /openbmc/linux/drivers/clocksource/timer-ti-dm-systimer.c (revision 52762fbd1c4778ac9b173624ca0faacd22ef4724)
1*52762fbdSTony Lindgren // SPDX-License-Identifier: GPL-2.0+
2*52762fbdSTony Lindgren #include <linux/clk.h>
3*52762fbdSTony Lindgren #include <linux/clocksource.h>
4*52762fbdSTony Lindgren #include <linux/clockchips.h>
5*52762fbdSTony Lindgren #include <linux/interrupt.h>
6*52762fbdSTony Lindgren #include <linux/io.h>
7*52762fbdSTony Lindgren #include <linux/iopoll.h>
8*52762fbdSTony Lindgren #include <linux/err.h>
9*52762fbdSTony Lindgren #include <linux/of.h>
10*52762fbdSTony Lindgren #include <linux/of_address.h>
11*52762fbdSTony Lindgren #include <linux/of_irq.h>
12*52762fbdSTony Lindgren #include <linux/sched_clock.h>
13*52762fbdSTony Lindgren 
14*52762fbdSTony Lindgren #include <linux/clk/clk-conf.h>
15*52762fbdSTony Lindgren 
16*52762fbdSTony Lindgren #include <clocksource/timer-ti-dm.h>
17*52762fbdSTony Lindgren #include <dt-bindings/bus/ti-sysc.h>
18*52762fbdSTony Lindgren 
19*52762fbdSTony Lindgren /* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */
20*52762fbdSTony Lindgren #define DMTIMER_TYPE1_ENABLE	((1 << 9) | (SYSC_IDLE_SMART << 3) | \
21*52762fbdSTony Lindgren 				 SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE)
22*52762fbdSTony Lindgren 
23*52762fbdSTony Lindgren #define DMTIMER_TYPE2_ENABLE	(SYSC_IDLE_SMART_WKUP << 2)
24*52762fbdSTony Lindgren #define DMTIMER_RESET_WAIT	100000
25*52762fbdSTony Lindgren 
26*52762fbdSTony Lindgren #define DMTIMER_INST_DONT_CARE	~0U
27*52762fbdSTony Lindgren 
28*52762fbdSTony Lindgren static int counter_32k;
29*52762fbdSTony Lindgren static u32 clocksource;
30*52762fbdSTony Lindgren static u32 clockevent;
31*52762fbdSTony Lindgren 
32*52762fbdSTony Lindgren /*
33*52762fbdSTony Lindgren  * Subset of the timer registers we use. Note that the register offsets
34*52762fbdSTony Lindgren  * depend on the timer revision detected.
35*52762fbdSTony Lindgren  */
36*52762fbdSTony Lindgren struct dmtimer_systimer {
37*52762fbdSTony Lindgren 	void __iomem *base;
38*52762fbdSTony Lindgren 	u8 sysc;
39*52762fbdSTony Lindgren 	u8 irq_stat;
40*52762fbdSTony Lindgren 	u8 irq_ena;
41*52762fbdSTony Lindgren 	u8 pend;
42*52762fbdSTony Lindgren 	u8 load;
43*52762fbdSTony Lindgren 	u8 counter;
44*52762fbdSTony Lindgren 	u8 ctrl;
45*52762fbdSTony Lindgren 	u8 wakeup;
46*52762fbdSTony Lindgren 	u8 ifctrl;
47*52762fbdSTony Lindgren 	unsigned long rate;
48*52762fbdSTony Lindgren };
49*52762fbdSTony Lindgren 
50*52762fbdSTony Lindgren struct dmtimer_clockevent {
51*52762fbdSTony Lindgren 	struct clock_event_device dev;
52*52762fbdSTony Lindgren 	struct dmtimer_systimer t;
53*52762fbdSTony Lindgren 	u32 period;
54*52762fbdSTony Lindgren };
55*52762fbdSTony Lindgren 
56*52762fbdSTony Lindgren struct dmtimer_clocksource {
57*52762fbdSTony Lindgren 	struct clocksource dev;
58*52762fbdSTony Lindgren 	struct dmtimer_systimer t;
59*52762fbdSTony Lindgren 	unsigned int loadval;
60*52762fbdSTony Lindgren };
61*52762fbdSTony Lindgren 
62*52762fbdSTony Lindgren /* Assumes v1 ip if bits [31:16] are zero */
63*52762fbdSTony Lindgren static bool dmtimer_systimer_revision1(struct dmtimer_systimer *t)
64*52762fbdSTony Lindgren {
65*52762fbdSTony Lindgren 	u32 tidr = readl_relaxed(t->base);
66*52762fbdSTony Lindgren 
67*52762fbdSTony Lindgren 	return !(tidr >> 16);
68*52762fbdSTony Lindgren }
69*52762fbdSTony Lindgren 
70*52762fbdSTony Lindgren static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t)
71*52762fbdSTony Lindgren {
72*52762fbdSTony Lindgren 	void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET;
73*52762fbdSTony Lindgren 	int ret;
74*52762fbdSTony Lindgren 	u32 l;
75*52762fbdSTony Lindgren 
76*52762fbdSTony Lindgren 	writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl);
77*52762fbdSTony Lindgren 	ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100,
78*52762fbdSTony Lindgren 					DMTIMER_RESET_WAIT);
79*52762fbdSTony Lindgren 
80*52762fbdSTony Lindgren 	return ret;
81*52762fbdSTony Lindgren }
82*52762fbdSTony Lindgren 
83*52762fbdSTony Lindgren /* Note we must use io_base instead of func_base for type2 OCP regs */
84*52762fbdSTony Lindgren static int __init dmtimer_systimer_type2_reset(struct dmtimer_systimer *t)
85*52762fbdSTony Lindgren {
86*52762fbdSTony Lindgren 	void __iomem *sysc = t->base + t->sysc;
87*52762fbdSTony Lindgren 	u32 l;
88*52762fbdSTony Lindgren 
89*52762fbdSTony Lindgren 	l = readl_relaxed(sysc);
90*52762fbdSTony Lindgren 	l |= BIT(0);
91*52762fbdSTony Lindgren 	writel_relaxed(l, sysc);
92*52762fbdSTony Lindgren 
93*52762fbdSTony Lindgren 	return readl_poll_timeout_atomic(sysc, l, !(l & BIT(0)), 100,
94*52762fbdSTony Lindgren 					 DMTIMER_RESET_WAIT);
95*52762fbdSTony Lindgren }
96*52762fbdSTony Lindgren 
97*52762fbdSTony Lindgren static int __init dmtimer_systimer_reset(struct dmtimer_systimer *t)
98*52762fbdSTony Lindgren {
99*52762fbdSTony Lindgren 	int ret;
100*52762fbdSTony Lindgren 
101*52762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t))
102*52762fbdSTony Lindgren 		ret = dmtimer_systimer_type1_reset(t);
103*52762fbdSTony Lindgren 	else
104*52762fbdSTony Lindgren 		ret = dmtimer_systimer_type2_reset(t);
105*52762fbdSTony Lindgren 	if (ret < 0) {
106*52762fbdSTony Lindgren 		pr_err("%s failed with %i\n", __func__, ret);
107*52762fbdSTony Lindgren 
108*52762fbdSTony Lindgren 		return ret;
109*52762fbdSTony Lindgren 	}
110*52762fbdSTony Lindgren 
111*52762fbdSTony Lindgren 	return 0;
112*52762fbdSTony Lindgren }
113*52762fbdSTony Lindgren 
114*52762fbdSTony Lindgren static const struct of_device_id counter_match_table[] = {
115*52762fbdSTony Lindgren 	{ .compatible = "ti,omap-counter32k" },
116*52762fbdSTony Lindgren 	{ /* Sentinel */ },
117*52762fbdSTony Lindgren };
118*52762fbdSTony Lindgren 
119*52762fbdSTony Lindgren /*
120*52762fbdSTony Lindgren  * Check if the SoC als has a usable working 32 KiHz counter. The 32 KiHz
121*52762fbdSTony Lindgren  * counter is handled by timer-ti-32k, but we need to detect it as it
122*52762fbdSTony Lindgren  * affects the preferred dmtimer system timer configuration. There is
123*52762fbdSTony Lindgren  * typically no use for a dmtimer clocksource if the 32 KiHz counter is
124*52762fbdSTony Lindgren  * present, except on am437x as described below.
125*52762fbdSTony Lindgren  */
126*52762fbdSTony Lindgren static void __init dmtimer_systimer_check_counter32k(void)
127*52762fbdSTony Lindgren {
128*52762fbdSTony Lindgren 	struct device_node *np;
129*52762fbdSTony Lindgren 
130*52762fbdSTony Lindgren 	if (counter_32k)
131*52762fbdSTony Lindgren 		return;
132*52762fbdSTony Lindgren 
133*52762fbdSTony Lindgren 	np = of_find_matching_node(NULL, counter_match_table);
134*52762fbdSTony Lindgren 	if (!np) {
135*52762fbdSTony Lindgren 		counter_32k = -ENODEV;
136*52762fbdSTony Lindgren 
137*52762fbdSTony Lindgren 		return;
138*52762fbdSTony Lindgren 	}
139*52762fbdSTony Lindgren 
140*52762fbdSTony Lindgren 	if (of_device_is_available(np))
141*52762fbdSTony Lindgren 		counter_32k = 1;
142*52762fbdSTony Lindgren 	else
143*52762fbdSTony Lindgren 		counter_32k = -ENODEV;
144*52762fbdSTony Lindgren 
145*52762fbdSTony Lindgren 	of_node_put(np);
146*52762fbdSTony Lindgren }
147*52762fbdSTony Lindgren 
148*52762fbdSTony Lindgren static const struct of_device_id dmtimer_match_table[] = {
149*52762fbdSTony Lindgren 	{ .compatible = "ti,omap2420-timer", },
150*52762fbdSTony Lindgren 	{ .compatible = "ti,omap3430-timer", },
151*52762fbdSTony Lindgren 	{ .compatible = "ti,omap4430-timer", },
152*52762fbdSTony Lindgren 	{ .compatible = "ti,omap5430-timer", },
153*52762fbdSTony Lindgren 	{ .compatible = "ti,am335x-timer", },
154*52762fbdSTony Lindgren 	{ .compatible = "ti,am335x-timer-1ms", },
155*52762fbdSTony Lindgren 	{ .compatible = "ti,dm814-timer", },
156*52762fbdSTony Lindgren 	{ .compatible = "ti,dm816-timer", },
157*52762fbdSTony Lindgren 	{ /* Sentinel */ },
158*52762fbdSTony Lindgren };
159*52762fbdSTony Lindgren 
160*52762fbdSTony Lindgren /*
161*52762fbdSTony Lindgren  * Checks that system timers are configured to not reset and idle during
162*52762fbdSTony Lindgren  * the generic timer-ti-dm device driver probe. And that the system timer
163*52762fbdSTony Lindgren  * source clocks are properly configured. Also, let's not hog any DSP and
164*52762fbdSTony Lindgren  * PWM capable timers unnecessarily as system timers.
165*52762fbdSTony Lindgren  */
166*52762fbdSTony Lindgren static bool __init dmtimer_is_preferred(struct device_node *np)
167*52762fbdSTony Lindgren {
168*52762fbdSTony Lindgren 	if (!of_device_is_available(np))
169*52762fbdSTony Lindgren 		return false;
170*52762fbdSTony Lindgren 
171*52762fbdSTony Lindgren 	if (!of_property_read_bool(np->parent,
172*52762fbdSTony Lindgren 				   "ti,no-reset-on-init"))
173*52762fbdSTony Lindgren 		return false;
174*52762fbdSTony Lindgren 
175*52762fbdSTony Lindgren 	if (!of_property_read_bool(np->parent, "ti,no-idle"))
176*52762fbdSTony Lindgren 		return false;
177*52762fbdSTony Lindgren 
178*52762fbdSTony Lindgren 	/* Secure gptimer12 is always clocked with a fixed source */
179*52762fbdSTony Lindgren 	if (!of_property_read_bool(np, "ti,timer-secure")) {
180*52762fbdSTony Lindgren 		if (!of_property_read_bool(np, "assigned-clocks"))
181*52762fbdSTony Lindgren 			return false;
182*52762fbdSTony Lindgren 
183*52762fbdSTony Lindgren 		if (!of_property_read_bool(np, "assigned-clock-parents"))
184*52762fbdSTony Lindgren 			return false;
185*52762fbdSTony Lindgren 	}
186*52762fbdSTony Lindgren 
187*52762fbdSTony Lindgren 	if (of_property_read_bool(np, "ti,timer-dsp"))
188*52762fbdSTony Lindgren 		return false;
189*52762fbdSTony Lindgren 
190*52762fbdSTony Lindgren 	if (of_property_read_bool(np, "ti,timer-pwm"))
191*52762fbdSTony Lindgren 		return false;
192*52762fbdSTony Lindgren 
193*52762fbdSTony Lindgren 	return true;
194*52762fbdSTony Lindgren }
195*52762fbdSTony Lindgren 
196*52762fbdSTony Lindgren /*
197*52762fbdSTony Lindgren  * Finds the first available usable always-on timer, and assigns it to either
198*52762fbdSTony Lindgren  * clockevent or clocksource depending if the counter_32k is available on the
199*52762fbdSTony Lindgren  * SoC or not.
200*52762fbdSTony Lindgren  *
201*52762fbdSTony Lindgren  * Some omap3 boards with unreliable oscillator must not use the counter_32k
202*52762fbdSTony Lindgren  * or dmtimer1 with 32 KiHz source. Additionally, the boards with unreliable
203*52762fbdSTony Lindgren  * oscillator should really set counter_32k as disabled, and delete dmtimer1
204*52762fbdSTony Lindgren  * ti,always-on property, but let's not count on it. For these quirky cases,
205*52762fbdSTony Lindgren  * we prefer using the always-on secure dmtimer12 with the internal 32 KiHz
206*52762fbdSTony Lindgren  * clock as the clocksource, and any available dmtimer as clockevent.
207*52762fbdSTony Lindgren  *
208*52762fbdSTony Lindgren  * For am437x, we are using am335x style dmtimer clocksource. It is unclear
209*52762fbdSTony Lindgren  * if this quirk handling is really needed, but let's change it separately
210*52762fbdSTony Lindgren  * based on testing as it might cause side effects.
211*52762fbdSTony Lindgren  */
212*52762fbdSTony Lindgren static void __init dmtimer_systimer_assign_alwon(void)
213*52762fbdSTony Lindgren {
214*52762fbdSTony Lindgren 	struct device_node *np;
215*52762fbdSTony Lindgren 	u32 pa = 0;
216*52762fbdSTony Lindgren 	bool quirk_unreliable_oscillator = false;
217*52762fbdSTony Lindgren 
218*52762fbdSTony Lindgren 	/* Quirk unreliable 32 KiHz oscillator with incomplete dts */
219*52762fbdSTony Lindgren 	if (of_machine_is_compatible("ti,omap3-beagle") ||
220*52762fbdSTony Lindgren 	    of_machine_is_compatible("timll,omap3-devkit8000")) {
221*52762fbdSTony Lindgren 		quirk_unreliable_oscillator = true;
222*52762fbdSTony Lindgren 		counter_32k = -ENODEV;
223*52762fbdSTony Lindgren 	}
224*52762fbdSTony Lindgren 
225*52762fbdSTony Lindgren 	/* Quirk am437x using am335x style dmtimer clocksource */
226*52762fbdSTony Lindgren 	if (of_machine_is_compatible("ti,am43"))
227*52762fbdSTony Lindgren 		counter_32k = -ENODEV;
228*52762fbdSTony Lindgren 
229*52762fbdSTony Lindgren 	for_each_matching_node(np, dmtimer_match_table) {
230*52762fbdSTony Lindgren 		if (!dmtimer_is_preferred(np))
231*52762fbdSTony Lindgren 			continue;
232*52762fbdSTony Lindgren 
233*52762fbdSTony Lindgren 		if (of_property_read_bool(np, "ti,timer-alwon")) {
234*52762fbdSTony Lindgren 			const __be32 *addr;
235*52762fbdSTony Lindgren 
236*52762fbdSTony Lindgren 			addr = of_get_address(np, 0, NULL, NULL);
237*52762fbdSTony Lindgren 			pa = of_translate_address(np, addr);
238*52762fbdSTony Lindgren 			if (pa) {
239*52762fbdSTony Lindgren 				/* Quirky omap3 boards must use dmtimer12 */
240*52762fbdSTony Lindgren 				if (quirk_unreliable_oscillator &&
241*52762fbdSTony Lindgren 				    pa == 0x48318000)
242*52762fbdSTony Lindgren 					continue;
243*52762fbdSTony Lindgren 
244*52762fbdSTony Lindgren 				of_node_put(np);
245*52762fbdSTony Lindgren 				break;
246*52762fbdSTony Lindgren 			}
247*52762fbdSTony Lindgren 		}
248*52762fbdSTony Lindgren 	}
249*52762fbdSTony Lindgren 
250*52762fbdSTony Lindgren 	/* Usually no need for dmtimer clocksource if we have counter32 */
251*52762fbdSTony Lindgren 	if (counter_32k >= 0) {
252*52762fbdSTony Lindgren 		clockevent = pa;
253*52762fbdSTony Lindgren 		clocksource = 0;
254*52762fbdSTony Lindgren 	} else {
255*52762fbdSTony Lindgren 		clocksource = pa;
256*52762fbdSTony Lindgren 		clockevent = DMTIMER_INST_DONT_CARE;
257*52762fbdSTony Lindgren 	}
258*52762fbdSTony Lindgren }
259*52762fbdSTony Lindgren 
260*52762fbdSTony Lindgren /* Finds the first usable dmtimer, used for the don't care case */
261*52762fbdSTony Lindgren static u32 __init dmtimer_systimer_find_first_available(void)
262*52762fbdSTony Lindgren {
263*52762fbdSTony Lindgren 	struct device_node *np;
264*52762fbdSTony Lindgren 	const __be32 *addr;
265*52762fbdSTony Lindgren 	u32 pa = 0;
266*52762fbdSTony Lindgren 
267*52762fbdSTony Lindgren 	for_each_matching_node(np, dmtimer_match_table) {
268*52762fbdSTony Lindgren 		if (!dmtimer_is_preferred(np))
269*52762fbdSTony Lindgren 			continue;
270*52762fbdSTony Lindgren 
271*52762fbdSTony Lindgren 		addr = of_get_address(np, 0, NULL, NULL);
272*52762fbdSTony Lindgren 		pa = of_translate_address(np, addr);
273*52762fbdSTony Lindgren 		if (pa) {
274*52762fbdSTony Lindgren 			if (pa == clocksource || pa == clockevent) {
275*52762fbdSTony Lindgren 				pa = 0;
276*52762fbdSTony Lindgren 				continue;
277*52762fbdSTony Lindgren 			}
278*52762fbdSTony Lindgren 
279*52762fbdSTony Lindgren 			of_node_put(np);
280*52762fbdSTony Lindgren 			break;
281*52762fbdSTony Lindgren 		}
282*52762fbdSTony Lindgren 	}
283*52762fbdSTony Lindgren 
284*52762fbdSTony Lindgren 	return pa;
285*52762fbdSTony Lindgren }
286*52762fbdSTony Lindgren 
287*52762fbdSTony Lindgren /* Selects the best clocksource and clockevent to use */
288*52762fbdSTony Lindgren static void __init dmtimer_systimer_select_best(void)
289*52762fbdSTony Lindgren {
290*52762fbdSTony Lindgren 	dmtimer_systimer_check_counter32k();
291*52762fbdSTony Lindgren 	dmtimer_systimer_assign_alwon();
292*52762fbdSTony Lindgren 
293*52762fbdSTony Lindgren 	if (clockevent == DMTIMER_INST_DONT_CARE)
294*52762fbdSTony Lindgren 		clockevent = dmtimer_systimer_find_first_available();
295*52762fbdSTony Lindgren 
296*52762fbdSTony Lindgren 	pr_debug("%s: counter_32k: %i clocksource: %08x clockevent: %08x\n",
297*52762fbdSTony Lindgren 		 __func__, counter_32k, clocksource, clockevent);
298*52762fbdSTony Lindgren }
299*52762fbdSTony Lindgren 
300*52762fbdSTony Lindgren /* Interface clocks are only available on some SoCs variants */
301*52762fbdSTony Lindgren static int __init dmtimer_systimer_init_clock(struct device_node *np,
302*52762fbdSTony Lindgren 					      const char *name,
303*52762fbdSTony Lindgren 					      unsigned long *rate)
304*52762fbdSTony Lindgren {
305*52762fbdSTony Lindgren 	struct clk *clock;
306*52762fbdSTony Lindgren 	unsigned long r;
307*52762fbdSTony Lindgren 	int error;
308*52762fbdSTony Lindgren 
309*52762fbdSTony Lindgren 	clock = of_clk_get_by_name(np, name);
310*52762fbdSTony Lindgren 	if ((PTR_ERR(clock) == -EINVAL) && !strncmp(name, "ick", 3))
311*52762fbdSTony Lindgren 		return 0;
312*52762fbdSTony Lindgren 	else if (IS_ERR(clock))
313*52762fbdSTony Lindgren 		return PTR_ERR(clock);
314*52762fbdSTony Lindgren 
315*52762fbdSTony Lindgren 	error = clk_prepare_enable(clock);
316*52762fbdSTony Lindgren 	if (error)
317*52762fbdSTony Lindgren 		return error;
318*52762fbdSTony Lindgren 
319*52762fbdSTony Lindgren 	r = clk_get_rate(clock);
320*52762fbdSTony Lindgren 	if (!r)
321*52762fbdSTony Lindgren 		return -ENODEV;
322*52762fbdSTony Lindgren 
323*52762fbdSTony Lindgren 	*rate = r;
324*52762fbdSTony Lindgren 
325*52762fbdSTony Lindgren 	return 0;
326*52762fbdSTony Lindgren }
327*52762fbdSTony Lindgren 
328*52762fbdSTony Lindgren static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
329*52762fbdSTony Lindgren {
330*52762fbdSTony Lindgren 	u32 val;
331*52762fbdSTony Lindgren 
332*52762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t))
333*52762fbdSTony Lindgren 		val = DMTIMER_TYPE1_ENABLE;
334*52762fbdSTony Lindgren 	else
335*52762fbdSTony Lindgren 		val = DMTIMER_TYPE2_ENABLE;
336*52762fbdSTony Lindgren 
337*52762fbdSTony Lindgren 	writel_relaxed(val, t->base + t->sysc);
338*52762fbdSTony Lindgren }
339*52762fbdSTony Lindgren 
340*52762fbdSTony Lindgren static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
341*52762fbdSTony Lindgren {
342*52762fbdSTony Lindgren 	writel_relaxed(0, t->base + t->sysc);
343*52762fbdSTony Lindgren }
344*52762fbdSTony Lindgren 
345*52762fbdSTony Lindgren static int __init dmtimer_systimer_setup(struct device_node *np,
346*52762fbdSTony Lindgren 					 struct dmtimer_systimer *t)
347*52762fbdSTony Lindgren {
348*52762fbdSTony Lindgren 	unsigned long rate;
349*52762fbdSTony Lindgren 	u8 regbase;
350*52762fbdSTony Lindgren 	int error;
351*52762fbdSTony Lindgren 
352*52762fbdSTony Lindgren 	if (!of_device_is_compatible(np->parent, "ti,sysc"))
353*52762fbdSTony Lindgren 		return -EINVAL;
354*52762fbdSTony Lindgren 
355*52762fbdSTony Lindgren 	t->base = of_iomap(np, 0);
356*52762fbdSTony Lindgren 	if (!t->base)
357*52762fbdSTony Lindgren 		return -ENXIO;
358*52762fbdSTony Lindgren 
359*52762fbdSTony Lindgren 	/*
360*52762fbdSTony Lindgren 	 * Enable optional assigned-clock-parents configured at the timer
361*52762fbdSTony Lindgren 	 * node level. For regular device drivers, this is done automatically
362*52762fbdSTony Lindgren 	 * by bus related code such as platform_drv_probe().
363*52762fbdSTony Lindgren 	 */
364*52762fbdSTony Lindgren 	error = of_clk_set_defaults(np, false);
365*52762fbdSTony Lindgren 	if (error < 0)
366*52762fbdSTony Lindgren 		pr_err("%s: clock source init failed: %i\n", __func__, error);
367*52762fbdSTony Lindgren 
368*52762fbdSTony Lindgren 	/* For ti-sysc, we have timer clocks at the parent module level */
369*52762fbdSTony Lindgren 	error = dmtimer_systimer_init_clock(np->parent, "fck", &rate);
370*52762fbdSTony Lindgren 	if (error)
371*52762fbdSTony Lindgren 		goto err_unmap;
372*52762fbdSTony Lindgren 
373*52762fbdSTony Lindgren 	t->rate = rate;
374*52762fbdSTony Lindgren 
375*52762fbdSTony Lindgren 	error = dmtimer_systimer_init_clock(np->parent, "ick", &rate);
376*52762fbdSTony Lindgren 	if (error)
377*52762fbdSTony Lindgren 		goto err_unmap;
378*52762fbdSTony Lindgren 
379*52762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t)) {
380*52762fbdSTony Lindgren 		t->irq_stat = OMAP_TIMER_V1_STAT_OFFSET;
381*52762fbdSTony Lindgren 		t->irq_ena = OMAP_TIMER_V1_INT_EN_OFFSET;
382*52762fbdSTony Lindgren 		t->pend = _OMAP_TIMER_WRITE_PEND_OFFSET;
383*52762fbdSTony Lindgren 		regbase = 0;
384*52762fbdSTony Lindgren 	} else {
385*52762fbdSTony Lindgren 		t->irq_stat = OMAP_TIMER_V2_IRQSTATUS;
386*52762fbdSTony Lindgren 		t->irq_ena = OMAP_TIMER_V2_IRQENABLE_SET;
387*52762fbdSTony Lindgren 		regbase = OMAP_TIMER_V2_FUNC_OFFSET;
388*52762fbdSTony Lindgren 		t->pend = regbase + _OMAP_TIMER_WRITE_PEND_OFFSET;
389*52762fbdSTony Lindgren 	}
390*52762fbdSTony Lindgren 
391*52762fbdSTony Lindgren 	t->sysc = OMAP_TIMER_OCP_CFG_OFFSET;
392*52762fbdSTony Lindgren 	t->load = regbase + _OMAP_TIMER_LOAD_OFFSET;
393*52762fbdSTony Lindgren 	t->counter = regbase + _OMAP_TIMER_COUNTER_OFFSET;
394*52762fbdSTony Lindgren 	t->ctrl = regbase + _OMAP_TIMER_CTRL_OFFSET;
395*52762fbdSTony Lindgren 	t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET;
396*52762fbdSTony Lindgren 	t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET;
397*52762fbdSTony Lindgren 
398*52762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
399*52762fbdSTony Lindgren 	dmtimer_systimer_reset(t);
400*52762fbdSTony Lindgren 	pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base),
401*52762fbdSTony Lindgren 		 readl_relaxed(t->base + t->sysc));
402*52762fbdSTony Lindgren 
403*52762fbdSTony Lindgren 	return 0;
404*52762fbdSTony Lindgren 
405*52762fbdSTony Lindgren err_unmap:
406*52762fbdSTony Lindgren 	iounmap(t->base);
407*52762fbdSTony Lindgren 
408*52762fbdSTony Lindgren 	return error;
409*52762fbdSTony Lindgren }
410*52762fbdSTony Lindgren 
411*52762fbdSTony Lindgren /* Clockevent */
412*52762fbdSTony Lindgren static struct dmtimer_clockevent *
413*52762fbdSTony Lindgren to_dmtimer_clockevent(struct clock_event_device *clockevent)
414*52762fbdSTony Lindgren {
415*52762fbdSTony Lindgren 	return container_of(clockevent, struct dmtimer_clockevent, dev);
416*52762fbdSTony Lindgren }
417*52762fbdSTony Lindgren 
418*52762fbdSTony Lindgren static irqreturn_t dmtimer_clockevent_interrupt(int irq, void *data)
419*52762fbdSTony Lindgren {
420*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = data;
421*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
422*52762fbdSTony Lindgren 
423*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_stat);
424*52762fbdSTony Lindgren 	clkevt->dev.event_handler(&clkevt->dev);
425*52762fbdSTony Lindgren 
426*52762fbdSTony Lindgren 	return IRQ_HANDLED;
427*52762fbdSTony Lindgren }
428*52762fbdSTony Lindgren 
429*52762fbdSTony Lindgren static int dmtimer_set_next_event(unsigned long cycles,
430*52762fbdSTony Lindgren 				  struct clock_event_device *evt)
431*52762fbdSTony Lindgren {
432*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
433*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
434*52762fbdSTony Lindgren 	void __iomem *pend = t->base + t->pend;
435*52762fbdSTony Lindgren 
436*52762fbdSTony Lindgren 	writel_relaxed(0xffffffff - cycles, t->base + t->counter);
437*52762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCRR)
438*52762fbdSTony Lindgren 		cpu_relax();
439*52762fbdSTony Lindgren 
440*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST, t->base + t->ctrl);
441*52762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCLR)
442*52762fbdSTony Lindgren 		cpu_relax();
443*52762fbdSTony Lindgren 
444*52762fbdSTony Lindgren 	return 0;
445*52762fbdSTony Lindgren }
446*52762fbdSTony Lindgren 
447*52762fbdSTony Lindgren static int dmtimer_clockevent_shutdown(struct clock_event_device *evt)
448*52762fbdSTony Lindgren {
449*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
450*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
451*52762fbdSTony Lindgren 	void __iomem *ctrl = t->base + t->ctrl;
452*52762fbdSTony Lindgren 	u32 l;
453*52762fbdSTony Lindgren 
454*52762fbdSTony Lindgren 	l = readl_relaxed(ctrl);
455*52762fbdSTony Lindgren 	if (l & OMAP_TIMER_CTRL_ST) {
456*52762fbdSTony Lindgren 		l &= ~BIT(0);
457*52762fbdSTony Lindgren 		writel_relaxed(l, ctrl);
458*52762fbdSTony Lindgren 		/* Flush posted write */
459*52762fbdSTony Lindgren 		l = readl_relaxed(ctrl);
460*52762fbdSTony Lindgren 		/*  Wait for functional clock period x 3.5 */
461*52762fbdSTony Lindgren 		udelay(3500000 / t->rate + 1);
462*52762fbdSTony Lindgren 	}
463*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_stat);
464*52762fbdSTony Lindgren 
465*52762fbdSTony Lindgren 	return 0;
466*52762fbdSTony Lindgren }
467*52762fbdSTony Lindgren 
468*52762fbdSTony Lindgren static int dmtimer_set_periodic(struct clock_event_device *evt)
469*52762fbdSTony Lindgren {
470*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
471*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
472*52762fbdSTony Lindgren 	void __iomem *pend = t->base + t->pend;
473*52762fbdSTony Lindgren 
474*52762fbdSTony Lindgren 	dmtimer_clockevent_shutdown(evt);
475*52762fbdSTony Lindgren 
476*52762fbdSTony Lindgren 	/* Looks like we need to first set the load value separately */
477*52762fbdSTony Lindgren 	writel_relaxed(clkevt->period, t->base + t->load);
478*52762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TLDR)
479*52762fbdSTony Lindgren 		cpu_relax();
480*52762fbdSTony Lindgren 
481*52762fbdSTony Lindgren 	writel_relaxed(clkevt->period, t->base + t->counter);
482*52762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCRR)
483*52762fbdSTony Lindgren 		cpu_relax();
484*52762fbdSTony Lindgren 
485*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
486*52762fbdSTony Lindgren 		       t->base + t->ctrl);
487*52762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCLR)
488*52762fbdSTony Lindgren 		cpu_relax();
489*52762fbdSTony Lindgren 
490*52762fbdSTony Lindgren 	return 0;
491*52762fbdSTony Lindgren }
492*52762fbdSTony Lindgren 
493*52762fbdSTony Lindgren static void omap_clockevent_idle(struct clock_event_device *evt)
494*52762fbdSTony Lindgren {
495*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
496*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
497*52762fbdSTony Lindgren 
498*52762fbdSTony Lindgren 	dmtimer_systimer_disable(t);
499*52762fbdSTony Lindgren }
500*52762fbdSTony Lindgren 
501*52762fbdSTony Lindgren static void omap_clockevent_unidle(struct clock_event_device *evt)
502*52762fbdSTony Lindgren {
503*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
504*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
505*52762fbdSTony Lindgren 
506*52762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
507*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
508*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
509*52762fbdSTony Lindgren }
510*52762fbdSTony Lindgren 
511*52762fbdSTony Lindgren static int __init dmtimer_clockevent_init(struct device_node *np)
512*52762fbdSTony Lindgren {
513*52762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt;
514*52762fbdSTony Lindgren 	struct clock_event_device *dev;
515*52762fbdSTony Lindgren 	struct dmtimer_systimer *t;
516*52762fbdSTony Lindgren 	int error;
517*52762fbdSTony Lindgren 	u32 pa;
518*52762fbdSTony Lindgren 
519*52762fbdSTony Lindgren 	clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
520*52762fbdSTony Lindgren 	if (!clkevt)
521*52762fbdSTony Lindgren 		return -ENOMEM;
522*52762fbdSTony Lindgren 
523*52762fbdSTony Lindgren 	t = &clkevt->t;
524*52762fbdSTony Lindgren 	dev = &clkevt->dev;
525*52762fbdSTony Lindgren 
526*52762fbdSTony Lindgren 	/*
527*52762fbdSTony Lindgren 	 * We mostly use cpuidle_coupled with ARM local timers for runtime,
528*52762fbdSTony Lindgren 	 * so there's probably no use for CLOCK_EVT_FEAT_DYNIRQ here.
529*52762fbdSTony Lindgren 	 */
530*52762fbdSTony Lindgren 	dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
531*52762fbdSTony Lindgren 	dev->rating = 300;
532*52762fbdSTony Lindgren 	dev->set_next_event = dmtimer_set_next_event;
533*52762fbdSTony Lindgren 	dev->set_state_shutdown = dmtimer_clockevent_shutdown;
534*52762fbdSTony Lindgren 	dev->set_state_periodic = dmtimer_set_periodic;
535*52762fbdSTony Lindgren 	dev->set_state_oneshot = dmtimer_clockevent_shutdown;
536*52762fbdSTony Lindgren 	dev->tick_resume = dmtimer_clockevent_shutdown;
537*52762fbdSTony Lindgren 	dev->cpumask = cpu_possible_mask;
538*52762fbdSTony Lindgren 
539*52762fbdSTony Lindgren 	dev->irq = irq_of_parse_and_map(np, 0);
540*52762fbdSTony Lindgren 	if (!dev->irq) {
541*52762fbdSTony Lindgren 		error = -ENXIO;
542*52762fbdSTony Lindgren 		goto err_out_free;
543*52762fbdSTony Lindgren 	}
544*52762fbdSTony Lindgren 
545*52762fbdSTony Lindgren 	error = dmtimer_systimer_setup(np, &clkevt->t);
546*52762fbdSTony Lindgren 	if (error)
547*52762fbdSTony Lindgren 		goto err_out_free;
548*52762fbdSTony Lindgren 
549*52762fbdSTony Lindgren 	clkevt->period = 0xffffffff - DIV_ROUND_CLOSEST(t->rate, HZ);
550*52762fbdSTony Lindgren 
551*52762fbdSTony Lindgren 	/*
552*52762fbdSTony Lindgren 	 * For clock-event timers we never read the timer counter and
553*52762fbdSTony Lindgren 	 * so we are not impacted by errata i103 and i767. Therefore,
554*52762fbdSTony Lindgren 	 * we can safely ignore this errata for clock-event timers.
555*52762fbdSTony Lindgren 	 */
556*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_POSTED, t->base + t->ifctrl);
557*52762fbdSTony Lindgren 
558*52762fbdSTony Lindgren 	error = request_irq(dev->irq, dmtimer_clockevent_interrupt,
559*52762fbdSTony Lindgren 			    IRQF_TIMER, "clockevent", clkevt);
560*52762fbdSTony Lindgren 	if (error)
561*52762fbdSTony Lindgren 		goto err_out_unmap;
562*52762fbdSTony Lindgren 
563*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
564*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
565*52762fbdSTony Lindgren 
566*52762fbdSTony Lindgren 	pa = of_translate_address(np, of_get_address(np, 0, NULL, NULL));
567*52762fbdSTony Lindgren 	pr_info("TI gptimer clockevent: %s%lu Hz at %pOF\n",
568*52762fbdSTony Lindgren 		of_find_property(np, "ti,timer-alwon", NULL) ?
569*52762fbdSTony Lindgren 		"always-on " : "", t->rate, np->parent);
570*52762fbdSTony Lindgren 
571*52762fbdSTony Lindgren 	clockevents_config_and_register(dev, t->rate,
572*52762fbdSTony Lindgren 					3, /* Timer internal resynch latency */
573*52762fbdSTony Lindgren 					0xffffffff);
574*52762fbdSTony Lindgren 
575*52762fbdSTony Lindgren 	if (of_device_is_compatible(np, "ti,am33xx") ||
576*52762fbdSTony Lindgren 	    of_device_is_compatible(np, "ti,am43")) {
577*52762fbdSTony Lindgren 		dev->suspend = omap_clockevent_idle;
578*52762fbdSTony Lindgren 		dev->resume = omap_clockevent_unidle;
579*52762fbdSTony Lindgren 	}
580*52762fbdSTony Lindgren 
581*52762fbdSTony Lindgren 	return 0;
582*52762fbdSTony Lindgren 
583*52762fbdSTony Lindgren err_out_unmap:
584*52762fbdSTony Lindgren 	iounmap(t->base);
585*52762fbdSTony Lindgren 
586*52762fbdSTony Lindgren err_out_free:
587*52762fbdSTony Lindgren 	kfree(clkevt);
588*52762fbdSTony Lindgren 
589*52762fbdSTony Lindgren 	return error;
590*52762fbdSTony Lindgren }
591*52762fbdSTony Lindgren 
592*52762fbdSTony Lindgren /* Clocksource */
593*52762fbdSTony Lindgren static struct dmtimer_clocksource *
594*52762fbdSTony Lindgren to_dmtimer_clocksource(struct clocksource *cs)
595*52762fbdSTony Lindgren {
596*52762fbdSTony Lindgren 	return container_of(cs, struct dmtimer_clocksource, dev);
597*52762fbdSTony Lindgren }
598*52762fbdSTony Lindgren 
599*52762fbdSTony Lindgren static u64 dmtimer_clocksource_read_cycles(struct clocksource *cs)
600*52762fbdSTony Lindgren {
601*52762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
602*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
603*52762fbdSTony Lindgren 
604*52762fbdSTony Lindgren 	return (u64)readl_relaxed(t->base + t->counter);
605*52762fbdSTony Lindgren }
606*52762fbdSTony Lindgren 
607*52762fbdSTony Lindgren static void __iomem *dmtimer_sched_clock_counter;
608*52762fbdSTony Lindgren 
609*52762fbdSTony Lindgren static u64 notrace dmtimer_read_sched_clock(void)
610*52762fbdSTony Lindgren {
611*52762fbdSTony Lindgren 	return readl_relaxed(dmtimer_sched_clock_counter);
612*52762fbdSTony Lindgren }
613*52762fbdSTony Lindgren 
614*52762fbdSTony Lindgren static void dmtimer_clocksource_suspend(struct clocksource *cs)
615*52762fbdSTony Lindgren {
616*52762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
617*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
618*52762fbdSTony Lindgren 
619*52762fbdSTony Lindgren 	clksrc->loadval = readl_relaxed(t->base + t->counter);
620*52762fbdSTony Lindgren 	dmtimer_systimer_disable(t);
621*52762fbdSTony Lindgren }
622*52762fbdSTony Lindgren 
623*52762fbdSTony Lindgren static void dmtimer_clocksource_resume(struct clocksource *cs)
624*52762fbdSTony Lindgren {
625*52762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
626*52762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
627*52762fbdSTony Lindgren 
628*52762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
629*52762fbdSTony Lindgren 	writel_relaxed(clksrc->loadval, t->base + t->counter);
630*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
631*52762fbdSTony Lindgren 		       t->base + t->ctrl);
632*52762fbdSTony Lindgren }
633*52762fbdSTony Lindgren 
634*52762fbdSTony Lindgren static int __init dmtimer_clocksource_init(struct device_node *np)
635*52762fbdSTony Lindgren {
636*52762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc;
637*52762fbdSTony Lindgren 	struct dmtimer_systimer *t;
638*52762fbdSTony Lindgren 	struct clocksource *dev;
639*52762fbdSTony Lindgren 	int error;
640*52762fbdSTony Lindgren 	u32 pa;
641*52762fbdSTony Lindgren 
642*52762fbdSTony Lindgren 	clksrc = kzalloc(sizeof(*clksrc), GFP_KERNEL);
643*52762fbdSTony Lindgren 	if (!clksrc)
644*52762fbdSTony Lindgren 		return -ENOMEM;
645*52762fbdSTony Lindgren 
646*52762fbdSTony Lindgren 	dev = &clksrc->dev;
647*52762fbdSTony Lindgren 	t = &clksrc->t;
648*52762fbdSTony Lindgren 
649*52762fbdSTony Lindgren 	error = dmtimer_systimer_setup(np, t);
650*52762fbdSTony Lindgren 	if (error)
651*52762fbdSTony Lindgren 		goto err_out_free;
652*52762fbdSTony Lindgren 
653*52762fbdSTony Lindgren 	dev->name = "dmtimer";
654*52762fbdSTony Lindgren 	dev->rating = 300;
655*52762fbdSTony Lindgren 	dev->read = dmtimer_clocksource_read_cycles;
656*52762fbdSTony Lindgren 	dev->mask = CLOCKSOURCE_MASK(32);
657*52762fbdSTony Lindgren 	dev->flags = CLOCK_SOURCE_IS_CONTINUOUS;
658*52762fbdSTony Lindgren 
659*52762fbdSTony Lindgren 	if (of_device_is_compatible(np, "ti,am33xx") ||
660*52762fbdSTony Lindgren 	    of_device_is_compatible(np, "ti,am43")) {
661*52762fbdSTony Lindgren 		dev->suspend = dmtimer_clocksource_suspend;
662*52762fbdSTony Lindgren 		dev->resume = dmtimer_clocksource_resume;
663*52762fbdSTony Lindgren 	}
664*52762fbdSTony Lindgren 
665*52762fbdSTony Lindgren 	writel_relaxed(0, t->base + t->counter);
666*52762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
667*52762fbdSTony Lindgren 		       t->base + t->ctrl);
668*52762fbdSTony Lindgren 
669*52762fbdSTony Lindgren 	pa = of_translate_address(np, of_get_address(np, 0, NULL, NULL));
670*52762fbdSTony Lindgren 	pr_info("TI gptimer clocksource: %s%pOF\n",
671*52762fbdSTony Lindgren 		of_find_property(np, "ti,timer-alwon", NULL) ?
672*52762fbdSTony Lindgren 		"always-on " : "", np->parent);
673*52762fbdSTony Lindgren 
674*52762fbdSTony Lindgren 	if (!dmtimer_sched_clock_counter) {
675*52762fbdSTony Lindgren 		dmtimer_sched_clock_counter = t->base + t->counter;
676*52762fbdSTony Lindgren 		sched_clock_register(dmtimer_read_sched_clock, 32, t->rate);
677*52762fbdSTony Lindgren 	}
678*52762fbdSTony Lindgren 
679*52762fbdSTony Lindgren 	if (clocksource_register_hz(dev, t->rate))
680*52762fbdSTony Lindgren 		pr_err("Could not register clocksource %pOF\n", np);
681*52762fbdSTony Lindgren 
682*52762fbdSTony Lindgren 	return 0;
683*52762fbdSTony Lindgren 
684*52762fbdSTony Lindgren err_out_free:
685*52762fbdSTony Lindgren 	kfree(clksrc);
686*52762fbdSTony Lindgren 
687*52762fbdSTony Lindgren 	return -ENODEV;
688*52762fbdSTony Lindgren }
689*52762fbdSTony Lindgren 
690*52762fbdSTony Lindgren /*
691*52762fbdSTony Lindgren  * To detect between a clocksource and clockevent, we assume the device tree
692*52762fbdSTony Lindgren  * has no interrupts configured for a clocksource timer.
693*52762fbdSTony Lindgren  */
694*52762fbdSTony Lindgren static int __init dmtimer_systimer_init(struct device_node *np)
695*52762fbdSTony Lindgren {
696*52762fbdSTony Lindgren 	const __be32 *addr;
697*52762fbdSTony Lindgren 	u32 pa;
698*52762fbdSTony Lindgren 
699*52762fbdSTony Lindgren 	/* One time init for the preferred timer configuration */
700*52762fbdSTony Lindgren 	if (!clocksource && !clockevent)
701*52762fbdSTony Lindgren 		dmtimer_systimer_select_best();
702*52762fbdSTony Lindgren 
703*52762fbdSTony Lindgren 	if (!clocksource && !clockevent) {
704*52762fbdSTony Lindgren 		pr_err("%s: unable to detectt system timers, update dtb?\n",
705*52762fbdSTony Lindgren 		       __func__);
706*52762fbdSTony Lindgren 
707*52762fbdSTony Lindgren 		return -EINVAL;
708*52762fbdSTony Lindgren 	}
709*52762fbdSTony Lindgren 
710*52762fbdSTony Lindgren 	addr = of_get_address(np, 0, NULL, NULL);
711*52762fbdSTony Lindgren 	pa = of_translate_address(np, addr);
712*52762fbdSTony Lindgren 	if (!pa)
713*52762fbdSTony Lindgren 		return -EINVAL;
714*52762fbdSTony Lindgren 
715*52762fbdSTony Lindgren 	if (counter_32k <= 0 && clocksource == pa)
716*52762fbdSTony Lindgren 		return dmtimer_clocksource_init(np);
717*52762fbdSTony Lindgren 
718*52762fbdSTony Lindgren 	if (clockevent == pa)
719*52762fbdSTony Lindgren 		return dmtimer_clockevent_init(np);
720*52762fbdSTony Lindgren 
721*52762fbdSTony Lindgren 	return 0;
722*52762fbdSTony Lindgren }
723*52762fbdSTony Lindgren 
724*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap2, "ti,omap2420-timer", dmtimer_systimer_init);
725*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap3, "ti,omap3430-timer", dmtimer_systimer_init);
726*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap4, "ti,omap4430-timer", dmtimer_systimer_init);
727*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap5, "ti,omap5430-timer", dmtimer_systimer_init);
728*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_am33x, "ti,am335x-timer", dmtimer_systimer_init);
729*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_am3ms, "ti,am335x-timer-1ms", dmtimer_systimer_init);
730*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_dm814, "ti,dm814-timer", dmtimer_systimer_init);
731*52762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_dm816, "ti,dm816-timer", dmtimer_systimer_init);
732