xref: /linux/drivers/clocksource/timer-ti-dm-systimer.c (revision 164805157f3c6834670afbaff563353c773131f1)
152762fbdSTony Lindgren // SPDX-License-Identifier: GPL-2.0+
252762fbdSTony Lindgren #include <linux/clk.h>
352762fbdSTony Lindgren #include <linux/clocksource.h>
452762fbdSTony Lindgren #include <linux/clockchips.h>
552762fbdSTony Lindgren #include <linux/interrupt.h>
652762fbdSTony Lindgren #include <linux/io.h>
752762fbdSTony Lindgren #include <linux/iopoll.h>
852762fbdSTony Lindgren #include <linux/err.h>
952762fbdSTony Lindgren #include <linux/of.h>
1052762fbdSTony Lindgren #include <linux/of_address.h>
1152762fbdSTony Lindgren #include <linux/of_irq.h>
1252762fbdSTony Lindgren #include <linux/sched_clock.h>
1352762fbdSTony Lindgren 
1452762fbdSTony Lindgren #include <linux/clk/clk-conf.h>
1552762fbdSTony Lindgren 
1652762fbdSTony Lindgren #include <clocksource/timer-ti-dm.h>
1752762fbdSTony Lindgren #include <dt-bindings/bus/ti-sysc.h>
1852762fbdSTony Lindgren 
1952762fbdSTony Lindgren /* For type1, set SYSC_OMAP2_CLOCKACTIVITY for fck off on idle, l4 clock on */
2052762fbdSTony Lindgren #define DMTIMER_TYPE1_ENABLE	((1 << 9) | (SYSC_IDLE_SMART << 3) | \
2152762fbdSTony Lindgren 				 SYSC_OMAP2_ENAWAKEUP | SYSC_OMAP2_AUTOIDLE)
226cfcd556STony Lindgren #define DMTIMER_TYPE1_DISABLE	(SYSC_OMAP2_SOFTRESET | SYSC_OMAP2_AUTOIDLE)
2352762fbdSTony Lindgren #define DMTIMER_TYPE2_ENABLE	(SYSC_IDLE_SMART_WKUP << 2)
2452762fbdSTony Lindgren #define DMTIMER_RESET_WAIT	100000
2552762fbdSTony Lindgren 
2652762fbdSTony Lindgren #define DMTIMER_INST_DONT_CARE	~0U
2752762fbdSTony Lindgren 
2852762fbdSTony Lindgren static int counter_32k;
2952762fbdSTony Lindgren static u32 clocksource;
3052762fbdSTony Lindgren static u32 clockevent;
3152762fbdSTony Lindgren 
3252762fbdSTony Lindgren /*
3352762fbdSTony Lindgren  * Subset of the timer registers we use. Note that the register offsets
3452762fbdSTony Lindgren  * depend on the timer revision detected.
3552762fbdSTony Lindgren  */
3652762fbdSTony Lindgren struct dmtimer_systimer {
3752762fbdSTony Lindgren 	void __iomem *base;
3852762fbdSTony Lindgren 	u8 sysc;
3952762fbdSTony Lindgren 	u8 irq_stat;
4052762fbdSTony Lindgren 	u8 irq_ena;
4152762fbdSTony Lindgren 	u8 pend;
4252762fbdSTony Lindgren 	u8 load;
4352762fbdSTony Lindgren 	u8 counter;
4452762fbdSTony Lindgren 	u8 ctrl;
4552762fbdSTony Lindgren 	u8 wakeup;
4652762fbdSTony Lindgren 	u8 ifctrl;
476cfcd556STony Lindgren 	struct clk *fck;
486cfcd556STony Lindgren 	struct clk *ick;
4952762fbdSTony Lindgren 	unsigned long rate;
5052762fbdSTony Lindgren };
5152762fbdSTony Lindgren 
5252762fbdSTony Lindgren struct dmtimer_clockevent {
5352762fbdSTony Lindgren 	struct clock_event_device dev;
5452762fbdSTony Lindgren 	struct dmtimer_systimer t;
5552762fbdSTony Lindgren 	u32 period;
5652762fbdSTony Lindgren };
5752762fbdSTony Lindgren 
5852762fbdSTony Lindgren struct dmtimer_clocksource {
5952762fbdSTony Lindgren 	struct clocksource dev;
6052762fbdSTony Lindgren 	struct dmtimer_systimer t;
6152762fbdSTony Lindgren 	unsigned int loadval;
6252762fbdSTony Lindgren };
6352762fbdSTony Lindgren 
6452762fbdSTony Lindgren /* Assumes v1 ip if bits [31:16] are zero */
6552762fbdSTony Lindgren static bool dmtimer_systimer_revision1(struct dmtimer_systimer *t)
6652762fbdSTony Lindgren {
6752762fbdSTony Lindgren 	u32 tidr = readl_relaxed(t->base);
6852762fbdSTony Lindgren 
6952762fbdSTony Lindgren 	return !(tidr >> 16);
7052762fbdSTony Lindgren }
7152762fbdSTony Lindgren 
72*16480515STony Lindgren static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
73*16480515STony Lindgren {
74*16480515STony Lindgren 	u32 val;
75*16480515STony Lindgren 
76*16480515STony Lindgren 	if (dmtimer_systimer_revision1(t))
77*16480515STony Lindgren 		val = DMTIMER_TYPE1_ENABLE;
78*16480515STony Lindgren 	else
79*16480515STony Lindgren 		val = DMTIMER_TYPE2_ENABLE;
80*16480515STony Lindgren 
81*16480515STony Lindgren 	writel_relaxed(val, t->base + t->sysc);
82*16480515STony Lindgren }
83*16480515STony Lindgren 
84*16480515STony Lindgren static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
85*16480515STony Lindgren {
86*16480515STony Lindgren 	if (!dmtimer_systimer_revision1(t))
87*16480515STony Lindgren 		return;
88*16480515STony Lindgren 
89*16480515STony Lindgren 	writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
90*16480515STony Lindgren }
91*16480515STony Lindgren 
9252762fbdSTony Lindgren static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t)
9352762fbdSTony Lindgren {
9452762fbdSTony Lindgren 	void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET;
9552762fbdSTony Lindgren 	int ret;
9652762fbdSTony Lindgren 	u32 l;
9752762fbdSTony Lindgren 
98*16480515STony Lindgren 	dmtimer_systimer_enable(t);
9952762fbdSTony Lindgren 	writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl);
10052762fbdSTony Lindgren 	ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100,
10152762fbdSTony Lindgren 					DMTIMER_RESET_WAIT);
10252762fbdSTony Lindgren 
10352762fbdSTony Lindgren 	return ret;
10452762fbdSTony Lindgren }
10552762fbdSTony Lindgren 
10652762fbdSTony Lindgren /* Note we must use io_base instead of func_base for type2 OCP regs */
10752762fbdSTony Lindgren static int __init dmtimer_systimer_type2_reset(struct dmtimer_systimer *t)
10852762fbdSTony Lindgren {
10952762fbdSTony Lindgren 	void __iomem *sysc = t->base + t->sysc;
11052762fbdSTony Lindgren 	u32 l;
11152762fbdSTony Lindgren 
112*16480515STony Lindgren 	dmtimer_systimer_enable(t);
11352762fbdSTony Lindgren 	l = readl_relaxed(sysc);
11452762fbdSTony Lindgren 	l |= BIT(0);
11552762fbdSTony Lindgren 	writel_relaxed(l, sysc);
11652762fbdSTony Lindgren 
11752762fbdSTony Lindgren 	return readl_poll_timeout_atomic(sysc, l, !(l & BIT(0)), 100,
11852762fbdSTony Lindgren 					 DMTIMER_RESET_WAIT);
11952762fbdSTony Lindgren }
12052762fbdSTony Lindgren 
12152762fbdSTony Lindgren static int __init dmtimer_systimer_reset(struct dmtimer_systimer *t)
12252762fbdSTony Lindgren {
12352762fbdSTony Lindgren 	int ret;
12452762fbdSTony Lindgren 
12552762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t))
12652762fbdSTony Lindgren 		ret = dmtimer_systimer_type1_reset(t);
12752762fbdSTony Lindgren 	else
12852762fbdSTony Lindgren 		ret = dmtimer_systimer_type2_reset(t);
12952762fbdSTony Lindgren 	if (ret < 0) {
13052762fbdSTony Lindgren 		pr_err("%s failed with %i\n", __func__, ret);
13152762fbdSTony Lindgren 
13252762fbdSTony Lindgren 		return ret;
13352762fbdSTony Lindgren 	}
13452762fbdSTony Lindgren 
13552762fbdSTony Lindgren 	return 0;
13652762fbdSTony Lindgren }
13752762fbdSTony Lindgren 
13852762fbdSTony Lindgren static const struct of_device_id counter_match_table[] = {
13952762fbdSTony Lindgren 	{ .compatible = "ti,omap-counter32k" },
14052762fbdSTony Lindgren 	{ /* Sentinel */ },
14152762fbdSTony Lindgren };
14252762fbdSTony Lindgren 
14352762fbdSTony Lindgren /*
14452762fbdSTony Lindgren  * Check if the SoC als has a usable working 32 KiHz counter. The 32 KiHz
14552762fbdSTony Lindgren  * counter is handled by timer-ti-32k, but we need to detect it as it
14652762fbdSTony Lindgren  * affects the preferred dmtimer system timer configuration. There is
14752762fbdSTony Lindgren  * typically no use for a dmtimer clocksource if the 32 KiHz counter is
14852762fbdSTony Lindgren  * present, except on am437x as described below.
14952762fbdSTony Lindgren  */
15052762fbdSTony Lindgren static void __init dmtimer_systimer_check_counter32k(void)
15152762fbdSTony Lindgren {
15252762fbdSTony Lindgren 	struct device_node *np;
15352762fbdSTony Lindgren 
15452762fbdSTony Lindgren 	if (counter_32k)
15552762fbdSTony Lindgren 		return;
15652762fbdSTony Lindgren 
15752762fbdSTony Lindgren 	np = of_find_matching_node(NULL, counter_match_table);
15852762fbdSTony Lindgren 	if (!np) {
15952762fbdSTony Lindgren 		counter_32k = -ENODEV;
16052762fbdSTony Lindgren 
16152762fbdSTony Lindgren 		return;
16252762fbdSTony Lindgren 	}
16352762fbdSTony Lindgren 
16452762fbdSTony Lindgren 	if (of_device_is_available(np))
16552762fbdSTony Lindgren 		counter_32k = 1;
16652762fbdSTony Lindgren 	else
16752762fbdSTony Lindgren 		counter_32k = -ENODEV;
16852762fbdSTony Lindgren 
16952762fbdSTony Lindgren 	of_node_put(np);
17052762fbdSTony Lindgren }
17152762fbdSTony Lindgren 
17252762fbdSTony Lindgren static const struct of_device_id dmtimer_match_table[] = {
17352762fbdSTony Lindgren 	{ .compatible = "ti,omap2420-timer", },
17452762fbdSTony Lindgren 	{ .compatible = "ti,omap3430-timer", },
17552762fbdSTony Lindgren 	{ .compatible = "ti,omap4430-timer", },
17652762fbdSTony Lindgren 	{ .compatible = "ti,omap5430-timer", },
17752762fbdSTony Lindgren 	{ .compatible = "ti,am335x-timer", },
17852762fbdSTony Lindgren 	{ .compatible = "ti,am335x-timer-1ms", },
17952762fbdSTony Lindgren 	{ .compatible = "ti,dm814-timer", },
18052762fbdSTony Lindgren 	{ .compatible = "ti,dm816-timer", },
18152762fbdSTony Lindgren 	{ /* Sentinel */ },
18252762fbdSTony Lindgren };
18352762fbdSTony Lindgren 
18452762fbdSTony Lindgren /*
18552762fbdSTony Lindgren  * Checks that system timers are configured to not reset and idle during
18652762fbdSTony Lindgren  * the generic timer-ti-dm device driver probe. And that the system timer
18752762fbdSTony Lindgren  * source clocks are properly configured. Also, let's not hog any DSP and
18852762fbdSTony Lindgren  * PWM capable timers unnecessarily as system timers.
18952762fbdSTony Lindgren  */
19052762fbdSTony Lindgren static bool __init dmtimer_is_preferred(struct device_node *np)
19152762fbdSTony Lindgren {
19252762fbdSTony Lindgren 	if (!of_device_is_available(np))
19352762fbdSTony Lindgren 		return false;
19452762fbdSTony Lindgren 
19552762fbdSTony Lindgren 	if (!of_property_read_bool(np->parent,
19652762fbdSTony Lindgren 				   "ti,no-reset-on-init"))
19752762fbdSTony Lindgren 		return false;
19852762fbdSTony Lindgren 
19952762fbdSTony Lindgren 	if (!of_property_read_bool(np->parent, "ti,no-idle"))
20052762fbdSTony Lindgren 		return false;
20152762fbdSTony Lindgren 
20252762fbdSTony Lindgren 	/* Secure gptimer12 is always clocked with a fixed source */
20352762fbdSTony Lindgren 	if (!of_property_read_bool(np, "ti,timer-secure")) {
20452762fbdSTony Lindgren 		if (!of_property_read_bool(np, "assigned-clocks"))
20552762fbdSTony Lindgren 			return false;
20652762fbdSTony Lindgren 
20752762fbdSTony Lindgren 		if (!of_property_read_bool(np, "assigned-clock-parents"))
20852762fbdSTony Lindgren 			return false;
20952762fbdSTony Lindgren 	}
21052762fbdSTony Lindgren 
21152762fbdSTony Lindgren 	if (of_property_read_bool(np, "ti,timer-dsp"))
21252762fbdSTony Lindgren 		return false;
21352762fbdSTony Lindgren 
21452762fbdSTony Lindgren 	if (of_property_read_bool(np, "ti,timer-pwm"))
21552762fbdSTony Lindgren 		return false;
21652762fbdSTony Lindgren 
21752762fbdSTony Lindgren 	return true;
21852762fbdSTony Lindgren }
21952762fbdSTony Lindgren 
22052762fbdSTony Lindgren /*
22152762fbdSTony Lindgren  * Finds the first available usable always-on timer, and assigns it to either
22252762fbdSTony Lindgren  * clockevent or clocksource depending if the counter_32k is available on the
22352762fbdSTony Lindgren  * SoC or not.
22452762fbdSTony Lindgren  *
22552762fbdSTony Lindgren  * Some omap3 boards with unreliable oscillator must not use the counter_32k
22652762fbdSTony Lindgren  * or dmtimer1 with 32 KiHz source. Additionally, the boards with unreliable
22752762fbdSTony Lindgren  * oscillator should really set counter_32k as disabled, and delete dmtimer1
22852762fbdSTony Lindgren  * ti,always-on property, but let's not count on it. For these quirky cases,
22952762fbdSTony Lindgren  * we prefer using the always-on secure dmtimer12 with the internal 32 KiHz
23052762fbdSTony Lindgren  * clock as the clocksource, and any available dmtimer as clockevent.
23152762fbdSTony Lindgren  *
23252762fbdSTony Lindgren  * For am437x, we are using am335x style dmtimer clocksource. It is unclear
23352762fbdSTony Lindgren  * if this quirk handling is really needed, but let's change it separately
23452762fbdSTony Lindgren  * based on testing as it might cause side effects.
23552762fbdSTony Lindgren  */
23652762fbdSTony Lindgren static void __init dmtimer_systimer_assign_alwon(void)
23752762fbdSTony Lindgren {
23852762fbdSTony Lindgren 	struct device_node *np;
23952762fbdSTony Lindgren 	u32 pa = 0;
24052762fbdSTony Lindgren 	bool quirk_unreliable_oscillator = false;
24152762fbdSTony Lindgren 
24252762fbdSTony Lindgren 	/* Quirk unreliable 32 KiHz oscillator with incomplete dts */
24352762fbdSTony Lindgren 	if (of_machine_is_compatible("ti,omap3-beagle") ||
24452762fbdSTony Lindgren 	    of_machine_is_compatible("timll,omap3-devkit8000")) {
24552762fbdSTony Lindgren 		quirk_unreliable_oscillator = true;
24652762fbdSTony Lindgren 		counter_32k = -ENODEV;
24752762fbdSTony Lindgren 	}
24852762fbdSTony Lindgren 
24952762fbdSTony Lindgren 	/* Quirk am437x using am335x style dmtimer clocksource */
25052762fbdSTony Lindgren 	if (of_machine_is_compatible("ti,am43"))
25152762fbdSTony Lindgren 		counter_32k = -ENODEV;
25252762fbdSTony Lindgren 
25352762fbdSTony Lindgren 	for_each_matching_node(np, dmtimer_match_table) {
25452762fbdSTony Lindgren 		if (!dmtimer_is_preferred(np))
25552762fbdSTony Lindgren 			continue;
25652762fbdSTony Lindgren 
25752762fbdSTony Lindgren 		if (of_property_read_bool(np, "ti,timer-alwon")) {
25852762fbdSTony Lindgren 			const __be32 *addr;
25952762fbdSTony Lindgren 
26052762fbdSTony Lindgren 			addr = of_get_address(np, 0, NULL, NULL);
26152762fbdSTony Lindgren 			pa = of_translate_address(np, addr);
26252762fbdSTony Lindgren 			if (pa) {
26352762fbdSTony Lindgren 				/* Quirky omap3 boards must use dmtimer12 */
26452762fbdSTony Lindgren 				if (quirk_unreliable_oscillator &&
26552762fbdSTony Lindgren 				    pa == 0x48318000)
26652762fbdSTony Lindgren 					continue;
26752762fbdSTony Lindgren 
26852762fbdSTony Lindgren 				of_node_put(np);
26952762fbdSTony Lindgren 				break;
27052762fbdSTony Lindgren 			}
27152762fbdSTony Lindgren 		}
27252762fbdSTony Lindgren 	}
27352762fbdSTony Lindgren 
27452762fbdSTony Lindgren 	/* Usually no need for dmtimer clocksource if we have counter32 */
27552762fbdSTony Lindgren 	if (counter_32k >= 0) {
27652762fbdSTony Lindgren 		clockevent = pa;
27752762fbdSTony Lindgren 		clocksource = 0;
27852762fbdSTony Lindgren 	} else {
27952762fbdSTony Lindgren 		clocksource = pa;
28052762fbdSTony Lindgren 		clockevent = DMTIMER_INST_DONT_CARE;
28152762fbdSTony Lindgren 	}
28252762fbdSTony Lindgren }
28352762fbdSTony Lindgren 
28452762fbdSTony Lindgren /* Finds the first usable dmtimer, used for the don't care case */
28552762fbdSTony Lindgren static u32 __init dmtimer_systimer_find_first_available(void)
28652762fbdSTony Lindgren {
28752762fbdSTony Lindgren 	struct device_node *np;
28852762fbdSTony Lindgren 	const __be32 *addr;
28952762fbdSTony Lindgren 	u32 pa = 0;
29052762fbdSTony Lindgren 
29152762fbdSTony Lindgren 	for_each_matching_node(np, dmtimer_match_table) {
29252762fbdSTony Lindgren 		if (!dmtimer_is_preferred(np))
29352762fbdSTony Lindgren 			continue;
29452762fbdSTony Lindgren 
29552762fbdSTony Lindgren 		addr = of_get_address(np, 0, NULL, NULL);
29652762fbdSTony Lindgren 		pa = of_translate_address(np, addr);
29752762fbdSTony Lindgren 		if (pa) {
29852762fbdSTony Lindgren 			if (pa == clocksource || pa == clockevent) {
29952762fbdSTony Lindgren 				pa = 0;
30052762fbdSTony Lindgren 				continue;
30152762fbdSTony Lindgren 			}
30252762fbdSTony Lindgren 
30352762fbdSTony Lindgren 			of_node_put(np);
30452762fbdSTony Lindgren 			break;
30552762fbdSTony Lindgren 		}
30652762fbdSTony Lindgren 	}
30752762fbdSTony Lindgren 
30852762fbdSTony Lindgren 	return pa;
30952762fbdSTony Lindgren }
31052762fbdSTony Lindgren 
31152762fbdSTony Lindgren /* Selects the best clocksource and clockevent to use */
31252762fbdSTony Lindgren static void __init dmtimer_systimer_select_best(void)
31352762fbdSTony Lindgren {
31452762fbdSTony Lindgren 	dmtimer_systimer_check_counter32k();
31552762fbdSTony Lindgren 	dmtimer_systimer_assign_alwon();
31652762fbdSTony Lindgren 
31752762fbdSTony Lindgren 	if (clockevent == DMTIMER_INST_DONT_CARE)
31852762fbdSTony Lindgren 		clockevent = dmtimer_systimer_find_first_available();
31952762fbdSTony Lindgren 
32052762fbdSTony Lindgren 	pr_debug("%s: counter_32k: %i clocksource: %08x clockevent: %08x\n",
32152762fbdSTony Lindgren 		 __func__, counter_32k, clocksource, clockevent);
32252762fbdSTony Lindgren }
32352762fbdSTony Lindgren 
32452762fbdSTony Lindgren /* Interface clocks are only available on some SoCs variants */
3256cfcd556STony Lindgren static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
3266cfcd556STony Lindgren 					      struct device_node *np,
32752762fbdSTony Lindgren 					      const char *name,
32852762fbdSTony Lindgren 					      unsigned long *rate)
32952762fbdSTony Lindgren {
33052762fbdSTony Lindgren 	struct clk *clock;
33152762fbdSTony Lindgren 	unsigned long r;
3326cfcd556STony Lindgren 	bool is_ick = false;
33352762fbdSTony Lindgren 	int error;
33452762fbdSTony Lindgren 
3356cfcd556STony Lindgren 	is_ick = !strncmp(name, "ick", 3);
3366cfcd556STony Lindgren 
33752762fbdSTony Lindgren 	clock = of_clk_get_by_name(np, name);
3386cfcd556STony Lindgren 	if ((PTR_ERR(clock) == -EINVAL) && is_ick)
33952762fbdSTony Lindgren 		return 0;
34052762fbdSTony Lindgren 	else if (IS_ERR(clock))
34152762fbdSTony Lindgren 		return PTR_ERR(clock);
34252762fbdSTony Lindgren 
34352762fbdSTony Lindgren 	error = clk_prepare_enable(clock);
34452762fbdSTony Lindgren 	if (error)
34552762fbdSTony Lindgren 		return error;
34652762fbdSTony Lindgren 
34752762fbdSTony Lindgren 	r = clk_get_rate(clock);
34852762fbdSTony Lindgren 	if (!r)
34952762fbdSTony Lindgren 		return -ENODEV;
35052762fbdSTony Lindgren 
3516cfcd556STony Lindgren 	if (is_ick)
3526cfcd556STony Lindgren 		t->ick = clock;
3536cfcd556STony Lindgren 	else
3546cfcd556STony Lindgren 		t->fck = clock;
3556cfcd556STony Lindgren 
35652762fbdSTony Lindgren 	*rate = r;
35752762fbdSTony Lindgren 
35852762fbdSTony Lindgren 	return 0;
35952762fbdSTony Lindgren }
36052762fbdSTony Lindgren 
36152762fbdSTony Lindgren static int __init dmtimer_systimer_setup(struct device_node *np,
36252762fbdSTony Lindgren 					 struct dmtimer_systimer *t)
36352762fbdSTony Lindgren {
36452762fbdSTony Lindgren 	unsigned long rate;
36552762fbdSTony Lindgren 	u8 regbase;
36652762fbdSTony Lindgren 	int error;
36752762fbdSTony Lindgren 
36852762fbdSTony Lindgren 	if (!of_device_is_compatible(np->parent, "ti,sysc"))
36952762fbdSTony Lindgren 		return -EINVAL;
37052762fbdSTony Lindgren 
37152762fbdSTony Lindgren 	t->base = of_iomap(np, 0);
37252762fbdSTony Lindgren 	if (!t->base)
37352762fbdSTony Lindgren 		return -ENXIO;
37452762fbdSTony Lindgren 
37552762fbdSTony Lindgren 	/*
37652762fbdSTony Lindgren 	 * Enable optional assigned-clock-parents configured at the timer
37752762fbdSTony Lindgren 	 * node level. For regular device drivers, this is done automatically
37852762fbdSTony Lindgren 	 * by bus related code such as platform_drv_probe().
37952762fbdSTony Lindgren 	 */
38052762fbdSTony Lindgren 	error = of_clk_set_defaults(np, false);
38152762fbdSTony Lindgren 	if (error < 0)
38252762fbdSTony Lindgren 		pr_err("%s: clock source init failed: %i\n", __func__, error);
38352762fbdSTony Lindgren 
38452762fbdSTony Lindgren 	/* For ti-sysc, we have timer clocks at the parent module level */
3856cfcd556STony Lindgren 	error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate);
38652762fbdSTony Lindgren 	if (error)
38752762fbdSTony Lindgren 		goto err_unmap;
38852762fbdSTony Lindgren 
38952762fbdSTony Lindgren 	t->rate = rate;
39052762fbdSTony Lindgren 
3916cfcd556STony Lindgren 	error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate);
39252762fbdSTony Lindgren 	if (error)
39352762fbdSTony Lindgren 		goto err_unmap;
39452762fbdSTony Lindgren 
39552762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t)) {
39652762fbdSTony Lindgren 		t->irq_stat = OMAP_TIMER_V1_STAT_OFFSET;
39752762fbdSTony Lindgren 		t->irq_ena = OMAP_TIMER_V1_INT_EN_OFFSET;
39852762fbdSTony Lindgren 		t->pend = _OMAP_TIMER_WRITE_PEND_OFFSET;
39952762fbdSTony Lindgren 		regbase = 0;
40052762fbdSTony Lindgren 	} else {
40152762fbdSTony Lindgren 		t->irq_stat = OMAP_TIMER_V2_IRQSTATUS;
40252762fbdSTony Lindgren 		t->irq_ena = OMAP_TIMER_V2_IRQENABLE_SET;
40352762fbdSTony Lindgren 		regbase = OMAP_TIMER_V2_FUNC_OFFSET;
40452762fbdSTony Lindgren 		t->pend = regbase + _OMAP_TIMER_WRITE_PEND_OFFSET;
40552762fbdSTony Lindgren 	}
40652762fbdSTony Lindgren 
40752762fbdSTony Lindgren 	t->sysc = OMAP_TIMER_OCP_CFG_OFFSET;
40852762fbdSTony Lindgren 	t->load = regbase + _OMAP_TIMER_LOAD_OFFSET;
40952762fbdSTony Lindgren 	t->counter = regbase + _OMAP_TIMER_COUNTER_OFFSET;
41052762fbdSTony Lindgren 	t->ctrl = regbase + _OMAP_TIMER_CTRL_OFFSET;
41152762fbdSTony Lindgren 	t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET;
41252762fbdSTony Lindgren 	t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET;
41352762fbdSTony Lindgren 
41452762fbdSTony Lindgren 	dmtimer_systimer_reset(t);
415*16480515STony Lindgren 	dmtimer_systimer_enable(t);
41652762fbdSTony Lindgren 	pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base),
41752762fbdSTony Lindgren 		 readl_relaxed(t->base + t->sysc));
41852762fbdSTony Lindgren 
41952762fbdSTony Lindgren 	return 0;
42052762fbdSTony Lindgren 
42152762fbdSTony Lindgren err_unmap:
42252762fbdSTony Lindgren 	iounmap(t->base);
42352762fbdSTony Lindgren 
42452762fbdSTony Lindgren 	return error;
42552762fbdSTony Lindgren }
42652762fbdSTony Lindgren 
42752762fbdSTony Lindgren /* Clockevent */
42852762fbdSTony Lindgren static struct dmtimer_clockevent *
42952762fbdSTony Lindgren to_dmtimer_clockevent(struct clock_event_device *clockevent)
43052762fbdSTony Lindgren {
43152762fbdSTony Lindgren 	return container_of(clockevent, struct dmtimer_clockevent, dev);
43252762fbdSTony Lindgren }
43352762fbdSTony Lindgren 
43452762fbdSTony Lindgren static irqreturn_t dmtimer_clockevent_interrupt(int irq, void *data)
43552762fbdSTony Lindgren {
43652762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = data;
43752762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
43852762fbdSTony Lindgren 
43952762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_stat);
44052762fbdSTony Lindgren 	clkevt->dev.event_handler(&clkevt->dev);
44152762fbdSTony Lindgren 
44252762fbdSTony Lindgren 	return IRQ_HANDLED;
44352762fbdSTony Lindgren }
44452762fbdSTony Lindgren 
44552762fbdSTony Lindgren static int dmtimer_set_next_event(unsigned long cycles,
44652762fbdSTony Lindgren 				  struct clock_event_device *evt)
44752762fbdSTony Lindgren {
44852762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
44952762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
45052762fbdSTony Lindgren 	void __iomem *pend = t->base + t->pend;
45152762fbdSTony Lindgren 
45252762fbdSTony Lindgren 	writel_relaxed(0xffffffff - cycles, t->base + t->counter);
45352762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCRR)
45452762fbdSTony Lindgren 		cpu_relax();
45552762fbdSTony Lindgren 
45652762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST, t->base + t->ctrl);
45752762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCLR)
45852762fbdSTony Lindgren 		cpu_relax();
45952762fbdSTony Lindgren 
46052762fbdSTony Lindgren 	return 0;
46152762fbdSTony Lindgren }
46252762fbdSTony Lindgren 
46352762fbdSTony Lindgren static int dmtimer_clockevent_shutdown(struct clock_event_device *evt)
46452762fbdSTony Lindgren {
46552762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
46652762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
46752762fbdSTony Lindgren 	void __iomem *ctrl = t->base + t->ctrl;
46852762fbdSTony Lindgren 	u32 l;
46952762fbdSTony Lindgren 
47052762fbdSTony Lindgren 	l = readl_relaxed(ctrl);
47152762fbdSTony Lindgren 	if (l & OMAP_TIMER_CTRL_ST) {
47252762fbdSTony Lindgren 		l &= ~BIT(0);
47352762fbdSTony Lindgren 		writel_relaxed(l, ctrl);
47452762fbdSTony Lindgren 		/* Flush posted write */
47552762fbdSTony Lindgren 		l = readl_relaxed(ctrl);
47652762fbdSTony Lindgren 		/*  Wait for functional clock period x 3.5 */
47752762fbdSTony Lindgren 		udelay(3500000 / t->rate + 1);
47852762fbdSTony Lindgren 	}
47952762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_stat);
48052762fbdSTony Lindgren 
48152762fbdSTony Lindgren 	return 0;
48252762fbdSTony Lindgren }
48352762fbdSTony Lindgren 
48452762fbdSTony Lindgren static int dmtimer_set_periodic(struct clock_event_device *evt)
48552762fbdSTony Lindgren {
48652762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
48752762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
48852762fbdSTony Lindgren 	void __iomem *pend = t->base + t->pend;
48952762fbdSTony Lindgren 
49052762fbdSTony Lindgren 	dmtimer_clockevent_shutdown(evt);
49152762fbdSTony Lindgren 
49252762fbdSTony Lindgren 	/* Looks like we need to first set the load value separately */
49352762fbdSTony Lindgren 	writel_relaxed(clkevt->period, t->base + t->load);
49452762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TLDR)
49552762fbdSTony Lindgren 		cpu_relax();
49652762fbdSTony Lindgren 
49752762fbdSTony Lindgren 	writel_relaxed(clkevt->period, t->base + t->counter);
49852762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCRR)
49952762fbdSTony Lindgren 		cpu_relax();
50052762fbdSTony Lindgren 
50152762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
50252762fbdSTony Lindgren 		       t->base + t->ctrl);
50352762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCLR)
50452762fbdSTony Lindgren 		cpu_relax();
50552762fbdSTony Lindgren 
50652762fbdSTony Lindgren 	return 0;
50752762fbdSTony Lindgren }
50852762fbdSTony Lindgren 
50952762fbdSTony Lindgren static void omap_clockevent_idle(struct clock_event_device *evt)
51052762fbdSTony Lindgren {
51152762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
51252762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
51352762fbdSTony Lindgren 
51452762fbdSTony Lindgren 	dmtimer_systimer_disable(t);
5156cfcd556STony Lindgren 	clk_disable(t->fck);
51652762fbdSTony Lindgren }
51752762fbdSTony Lindgren 
51852762fbdSTony Lindgren static void omap_clockevent_unidle(struct clock_event_device *evt)
51952762fbdSTony Lindgren {
52052762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
52152762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
5226cfcd556STony Lindgren 	int error;
5236cfcd556STony Lindgren 
5246cfcd556STony Lindgren 	error = clk_enable(t->fck);
5256cfcd556STony Lindgren 	if (error)
5266cfcd556STony Lindgren 		pr_err("could not enable timer fck on resume: %i\n", error);
52752762fbdSTony Lindgren 
52852762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
52952762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
53052762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
53152762fbdSTony Lindgren }
53252762fbdSTony Lindgren 
53352762fbdSTony Lindgren static int __init dmtimer_clockevent_init(struct device_node *np)
53452762fbdSTony Lindgren {
53552762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt;
53652762fbdSTony Lindgren 	struct clock_event_device *dev;
53752762fbdSTony Lindgren 	struct dmtimer_systimer *t;
53852762fbdSTony Lindgren 	int error;
53952762fbdSTony Lindgren 
54052762fbdSTony Lindgren 	clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
54152762fbdSTony Lindgren 	if (!clkevt)
54252762fbdSTony Lindgren 		return -ENOMEM;
54352762fbdSTony Lindgren 
54452762fbdSTony Lindgren 	t = &clkevt->t;
54552762fbdSTony Lindgren 	dev = &clkevt->dev;
54652762fbdSTony Lindgren 
54752762fbdSTony Lindgren 	/*
54852762fbdSTony Lindgren 	 * We mostly use cpuidle_coupled with ARM local timers for runtime,
54952762fbdSTony Lindgren 	 * so there's probably no use for CLOCK_EVT_FEAT_DYNIRQ here.
55052762fbdSTony Lindgren 	 */
55152762fbdSTony Lindgren 	dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
55252762fbdSTony Lindgren 	dev->rating = 300;
55352762fbdSTony Lindgren 	dev->set_next_event = dmtimer_set_next_event;
55452762fbdSTony Lindgren 	dev->set_state_shutdown = dmtimer_clockevent_shutdown;
55552762fbdSTony Lindgren 	dev->set_state_periodic = dmtimer_set_periodic;
55652762fbdSTony Lindgren 	dev->set_state_oneshot = dmtimer_clockevent_shutdown;
55752762fbdSTony Lindgren 	dev->tick_resume = dmtimer_clockevent_shutdown;
55852762fbdSTony Lindgren 	dev->cpumask = cpu_possible_mask;
55952762fbdSTony Lindgren 
56052762fbdSTony Lindgren 	dev->irq = irq_of_parse_and_map(np, 0);
56152762fbdSTony Lindgren 	if (!dev->irq) {
56252762fbdSTony Lindgren 		error = -ENXIO;
56352762fbdSTony Lindgren 		goto err_out_free;
56452762fbdSTony Lindgren 	}
56552762fbdSTony Lindgren 
56652762fbdSTony Lindgren 	error = dmtimer_systimer_setup(np, &clkevt->t);
56752762fbdSTony Lindgren 	if (error)
56852762fbdSTony Lindgren 		goto err_out_free;
56952762fbdSTony Lindgren 
57052762fbdSTony Lindgren 	clkevt->period = 0xffffffff - DIV_ROUND_CLOSEST(t->rate, HZ);
57152762fbdSTony Lindgren 
57252762fbdSTony Lindgren 	/*
57352762fbdSTony Lindgren 	 * For clock-event timers we never read the timer counter and
57452762fbdSTony Lindgren 	 * so we are not impacted by errata i103 and i767. Therefore,
57552762fbdSTony Lindgren 	 * we can safely ignore this errata for clock-event timers.
57652762fbdSTony Lindgren 	 */
57752762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_POSTED, t->base + t->ifctrl);
57852762fbdSTony Lindgren 
57952762fbdSTony Lindgren 	error = request_irq(dev->irq, dmtimer_clockevent_interrupt,
58052762fbdSTony Lindgren 			    IRQF_TIMER, "clockevent", clkevt);
58152762fbdSTony Lindgren 	if (error)
58252762fbdSTony Lindgren 		goto err_out_unmap;
58352762fbdSTony Lindgren 
58452762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
58552762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
58652762fbdSTony Lindgren 
58752762fbdSTony Lindgren 	pr_info("TI gptimer clockevent: %s%lu Hz at %pOF\n",
58852762fbdSTony Lindgren 		of_find_property(np, "ti,timer-alwon", NULL) ?
58952762fbdSTony Lindgren 		"always-on " : "", t->rate, np->parent);
59052762fbdSTony Lindgren 
59152762fbdSTony Lindgren 	clockevents_config_and_register(dev, t->rate,
59252762fbdSTony Lindgren 					3, /* Timer internal resynch latency */
59352762fbdSTony Lindgren 					0xffffffff);
59452762fbdSTony Lindgren 
5956cfcd556STony Lindgren 	if (of_machine_is_compatible("ti,am33xx") ||
5966cfcd556STony Lindgren 	    of_machine_is_compatible("ti,am43")) {
59752762fbdSTony Lindgren 		dev->suspend = omap_clockevent_idle;
59852762fbdSTony Lindgren 		dev->resume = omap_clockevent_unidle;
59952762fbdSTony Lindgren 	}
60052762fbdSTony Lindgren 
60152762fbdSTony Lindgren 	return 0;
60252762fbdSTony Lindgren 
60352762fbdSTony Lindgren err_out_unmap:
60452762fbdSTony Lindgren 	iounmap(t->base);
60552762fbdSTony Lindgren 
60652762fbdSTony Lindgren err_out_free:
60752762fbdSTony Lindgren 	kfree(clkevt);
60852762fbdSTony Lindgren 
60952762fbdSTony Lindgren 	return error;
61052762fbdSTony Lindgren }
61152762fbdSTony Lindgren 
61252762fbdSTony Lindgren /* Clocksource */
61352762fbdSTony Lindgren static struct dmtimer_clocksource *
61452762fbdSTony Lindgren to_dmtimer_clocksource(struct clocksource *cs)
61552762fbdSTony Lindgren {
61652762fbdSTony Lindgren 	return container_of(cs, struct dmtimer_clocksource, dev);
61752762fbdSTony Lindgren }
61852762fbdSTony Lindgren 
61952762fbdSTony Lindgren static u64 dmtimer_clocksource_read_cycles(struct clocksource *cs)
62052762fbdSTony Lindgren {
62152762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
62252762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
62352762fbdSTony Lindgren 
62452762fbdSTony Lindgren 	return (u64)readl_relaxed(t->base + t->counter);
62552762fbdSTony Lindgren }
62652762fbdSTony Lindgren 
62752762fbdSTony Lindgren static void __iomem *dmtimer_sched_clock_counter;
62852762fbdSTony Lindgren 
62952762fbdSTony Lindgren static u64 notrace dmtimer_read_sched_clock(void)
63052762fbdSTony Lindgren {
63152762fbdSTony Lindgren 	return readl_relaxed(dmtimer_sched_clock_counter);
63252762fbdSTony Lindgren }
63352762fbdSTony Lindgren 
63452762fbdSTony Lindgren static void dmtimer_clocksource_suspend(struct clocksource *cs)
63552762fbdSTony Lindgren {
63652762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
63752762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
63852762fbdSTony Lindgren 
63952762fbdSTony Lindgren 	clksrc->loadval = readl_relaxed(t->base + t->counter);
64052762fbdSTony Lindgren 	dmtimer_systimer_disable(t);
6416cfcd556STony Lindgren 	clk_disable(t->fck);
64252762fbdSTony Lindgren }
64352762fbdSTony Lindgren 
64452762fbdSTony Lindgren static void dmtimer_clocksource_resume(struct clocksource *cs)
64552762fbdSTony Lindgren {
64652762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
64752762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
6486cfcd556STony Lindgren 	int error;
6496cfcd556STony Lindgren 
6506cfcd556STony Lindgren 	error = clk_enable(t->fck);
6516cfcd556STony Lindgren 	if (error)
6526cfcd556STony Lindgren 		pr_err("could not enable timer fck on resume: %i\n", error);
65352762fbdSTony Lindgren 
65452762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
65552762fbdSTony Lindgren 	writel_relaxed(clksrc->loadval, t->base + t->counter);
65652762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
65752762fbdSTony Lindgren 		       t->base + t->ctrl);
65852762fbdSTony Lindgren }
65952762fbdSTony Lindgren 
66052762fbdSTony Lindgren static int __init dmtimer_clocksource_init(struct device_node *np)
66152762fbdSTony Lindgren {
66252762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc;
66352762fbdSTony Lindgren 	struct dmtimer_systimer *t;
66452762fbdSTony Lindgren 	struct clocksource *dev;
66552762fbdSTony Lindgren 	int error;
66652762fbdSTony Lindgren 
66752762fbdSTony Lindgren 	clksrc = kzalloc(sizeof(*clksrc), GFP_KERNEL);
66852762fbdSTony Lindgren 	if (!clksrc)
66952762fbdSTony Lindgren 		return -ENOMEM;
67052762fbdSTony Lindgren 
67152762fbdSTony Lindgren 	dev = &clksrc->dev;
67252762fbdSTony Lindgren 	t = &clksrc->t;
67352762fbdSTony Lindgren 
67452762fbdSTony Lindgren 	error = dmtimer_systimer_setup(np, t);
67552762fbdSTony Lindgren 	if (error)
67652762fbdSTony Lindgren 		goto err_out_free;
67752762fbdSTony Lindgren 
67852762fbdSTony Lindgren 	dev->name = "dmtimer";
67952762fbdSTony Lindgren 	dev->rating = 300;
68052762fbdSTony Lindgren 	dev->read = dmtimer_clocksource_read_cycles;
68152762fbdSTony Lindgren 	dev->mask = CLOCKSOURCE_MASK(32);
68252762fbdSTony Lindgren 	dev->flags = CLOCK_SOURCE_IS_CONTINUOUS;
68352762fbdSTony Lindgren 
6846cfcd556STony Lindgren 	/* Unlike for clockevent, legacy code sets suspend only for am4 */
6856cfcd556STony Lindgren 	if (of_machine_is_compatible("ti,am43")) {
68652762fbdSTony Lindgren 		dev->suspend = dmtimer_clocksource_suspend;
68752762fbdSTony Lindgren 		dev->resume = dmtimer_clocksource_resume;
68852762fbdSTony Lindgren 	}
68952762fbdSTony Lindgren 
69052762fbdSTony Lindgren 	writel_relaxed(0, t->base + t->counter);
69152762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
69252762fbdSTony Lindgren 		       t->base + t->ctrl);
69352762fbdSTony Lindgren 
69452762fbdSTony Lindgren 	pr_info("TI gptimer clocksource: %s%pOF\n",
69552762fbdSTony Lindgren 		of_find_property(np, "ti,timer-alwon", NULL) ?
69652762fbdSTony Lindgren 		"always-on " : "", np->parent);
69752762fbdSTony Lindgren 
69852762fbdSTony Lindgren 	if (!dmtimer_sched_clock_counter) {
69952762fbdSTony Lindgren 		dmtimer_sched_clock_counter = t->base + t->counter;
70052762fbdSTony Lindgren 		sched_clock_register(dmtimer_read_sched_clock, 32, t->rate);
70152762fbdSTony Lindgren 	}
70252762fbdSTony Lindgren 
70352762fbdSTony Lindgren 	if (clocksource_register_hz(dev, t->rate))
70452762fbdSTony Lindgren 		pr_err("Could not register clocksource %pOF\n", np);
70552762fbdSTony Lindgren 
70652762fbdSTony Lindgren 	return 0;
70752762fbdSTony Lindgren 
70852762fbdSTony Lindgren err_out_free:
70952762fbdSTony Lindgren 	kfree(clksrc);
71052762fbdSTony Lindgren 
71152762fbdSTony Lindgren 	return -ENODEV;
71252762fbdSTony Lindgren }
71352762fbdSTony Lindgren 
71452762fbdSTony Lindgren /*
71552762fbdSTony Lindgren  * To detect between a clocksource and clockevent, we assume the device tree
71652762fbdSTony Lindgren  * has no interrupts configured for a clocksource timer.
71752762fbdSTony Lindgren  */
71852762fbdSTony Lindgren static int __init dmtimer_systimer_init(struct device_node *np)
71952762fbdSTony Lindgren {
72052762fbdSTony Lindgren 	const __be32 *addr;
72152762fbdSTony Lindgren 	u32 pa;
72252762fbdSTony Lindgren 
72352762fbdSTony Lindgren 	/* One time init for the preferred timer configuration */
72452762fbdSTony Lindgren 	if (!clocksource && !clockevent)
72552762fbdSTony Lindgren 		dmtimer_systimer_select_best();
72652762fbdSTony Lindgren 
72752762fbdSTony Lindgren 	if (!clocksource && !clockevent) {
728ac593e62SColin Ian King 		pr_err("%s: unable to detect system timers, update dtb?\n",
72952762fbdSTony Lindgren 		       __func__);
73052762fbdSTony Lindgren 
73152762fbdSTony Lindgren 		return -EINVAL;
73252762fbdSTony Lindgren 	}
73352762fbdSTony Lindgren 
73452762fbdSTony Lindgren 	addr = of_get_address(np, 0, NULL, NULL);
73552762fbdSTony Lindgren 	pa = of_translate_address(np, addr);
73652762fbdSTony Lindgren 	if (!pa)
73752762fbdSTony Lindgren 		return -EINVAL;
73852762fbdSTony Lindgren 
73952762fbdSTony Lindgren 	if (counter_32k <= 0 && clocksource == pa)
74052762fbdSTony Lindgren 		return dmtimer_clocksource_init(np);
74152762fbdSTony Lindgren 
74252762fbdSTony Lindgren 	if (clockevent == pa)
74352762fbdSTony Lindgren 		return dmtimer_clockevent_init(np);
74452762fbdSTony Lindgren 
74552762fbdSTony Lindgren 	return 0;
74652762fbdSTony Lindgren }
74752762fbdSTony Lindgren 
74852762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap2, "ti,omap2420-timer", dmtimer_systimer_init);
74952762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap3, "ti,omap3430-timer", dmtimer_systimer_init);
75052762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap4, "ti,omap4430-timer", dmtimer_systimer_init);
75152762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap5, "ti,omap5430-timer", dmtimer_systimer_init);
75252762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_am33x, "ti,am335x-timer", dmtimer_systimer_init);
75352762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_am3ms, "ti,am335x-timer-1ms", dmtimer_systimer_init);
75452762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_dm814, "ti,dm814-timer", dmtimer_systimer_init);
75552762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_dm816, "ti,dm816-timer", dmtimer_systimer_init);
756