xref: /openbmc/linux/drivers/clocksource/timer-ti-dm-systimer.c (revision 6cfcd5563b4fadbf49ba8fa481978e5e86d30322)
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)
22*6cfcd556STony 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;
47*6cfcd556STony Lindgren 	struct clk *fck;
48*6cfcd556STony 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 
7252762fbdSTony Lindgren static int __init dmtimer_systimer_type1_reset(struct dmtimer_systimer *t)
7352762fbdSTony Lindgren {
7452762fbdSTony Lindgren 	void __iomem *syss = t->base + OMAP_TIMER_V1_SYS_STAT_OFFSET;
7552762fbdSTony Lindgren 	int ret;
7652762fbdSTony Lindgren 	u32 l;
7752762fbdSTony Lindgren 
7852762fbdSTony Lindgren 	writel_relaxed(BIT(1) | BIT(2), t->base + t->ifctrl);
7952762fbdSTony Lindgren 	ret = readl_poll_timeout_atomic(syss, l, l & BIT(0), 100,
8052762fbdSTony Lindgren 					DMTIMER_RESET_WAIT);
8152762fbdSTony Lindgren 
8252762fbdSTony Lindgren 	return ret;
8352762fbdSTony Lindgren }
8452762fbdSTony Lindgren 
8552762fbdSTony Lindgren /* Note we must use io_base instead of func_base for type2 OCP regs */
8652762fbdSTony Lindgren static int __init dmtimer_systimer_type2_reset(struct dmtimer_systimer *t)
8752762fbdSTony Lindgren {
8852762fbdSTony Lindgren 	void __iomem *sysc = t->base + t->sysc;
8952762fbdSTony Lindgren 	u32 l;
9052762fbdSTony Lindgren 
9152762fbdSTony Lindgren 	l = readl_relaxed(sysc);
9252762fbdSTony Lindgren 	l |= BIT(0);
9352762fbdSTony Lindgren 	writel_relaxed(l, sysc);
9452762fbdSTony Lindgren 
9552762fbdSTony Lindgren 	return readl_poll_timeout_atomic(sysc, l, !(l & BIT(0)), 100,
9652762fbdSTony Lindgren 					 DMTIMER_RESET_WAIT);
9752762fbdSTony Lindgren }
9852762fbdSTony Lindgren 
9952762fbdSTony Lindgren static int __init dmtimer_systimer_reset(struct dmtimer_systimer *t)
10052762fbdSTony Lindgren {
10152762fbdSTony Lindgren 	int ret;
10252762fbdSTony Lindgren 
10352762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t))
10452762fbdSTony Lindgren 		ret = dmtimer_systimer_type1_reset(t);
10552762fbdSTony Lindgren 	else
10652762fbdSTony Lindgren 		ret = dmtimer_systimer_type2_reset(t);
10752762fbdSTony Lindgren 	if (ret < 0) {
10852762fbdSTony Lindgren 		pr_err("%s failed with %i\n", __func__, ret);
10952762fbdSTony Lindgren 
11052762fbdSTony Lindgren 		return ret;
11152762fbdSTony Lindgren 	}
11252762fbdSTony Lindgren 
11352762fbdSTony Lindgren 	return 0;
11452762fbdSTony Lindgren }
11552762fbdSTony Lindgren 
11652762fbdSTony Lindgren static const struct of_device_id counter_match_table[] = {
11752762fbdSTony Lindgren 	{ .compatible = "ti,omap-counter32k" },
11852762fbdSTony Lindgren 	{ /* Sentinel */ },
11952762fbdSTony Lindgren };
12052762fbdSTony Lindgren 
12152762fbdSTony Lindgren /*
12252762fbdSTony Lindgren  * Check if the SoC als has a usable working 32 KiHz counter. The 32 KiHz
12352762fbdSTony Lindgren  * counter is handled by timer-ti-32k, but we need to detect it as it
12452762fbdSTony Lindgren  * affects the preferred dmtimer system timer configuration. There is
12552762fbdSTony Lindgren  * typically no use for a dmtimer clocksource if the 32 KiHz counter is
12652762fbdSTony Lindgren  * present, except on am437x as described below.
12752762fbdSTony Lindgren  */
12852762fbdSTony Lindgren static void __init dmtimer_systimer_check_counter32k(void)
12952762fbdSTony Lindgren {
13052762fbdSTony Lindgren 	struct device_node *np;
13152762fbdSTony Lindgren 
13252762fbdSTony Lindgren 	if (counter_32k)
13352762fbdSTony Lindgren 		return;
13452762fbdSTony Lindgren 
13552762fbdSTony Lindgren 	np = of_find_matching_node(NULL, counter_match_table);
13652762fbdSTony Lindgren 	if (!np) {
13752762fbdSTony Lindgren 		counter_32k = -ENODEV;
13852762fbdSTony Lindgren 
13952762fbdSTony Lindgren 		return;
14052762fbdSTony Lindgren 	}
14152762fbdSTony Lindgren 
14252762fbdSTony Lindgren 	if (of_device_is_available(np))
14352762fbdSTony Lindgren 		counter_32k = 1;
14452762fbdSTony Lindgren 	else
14552762fbdSTony Lindgren 		counter_32k = -ENODEV;
14652762fbdSTony Lindgren 
14752762fbdSTony Lindgren 	of_node_put(np);
14852762fbdSTony Lindgren }
14952762fbdSTony Lindgren 
15052762fbdSTony Lindgren static const struct of_device_id dmtimer_match_table[] = {
15152762fbdSTony Lindgren 	{ .compatible = "ti,omap2420-timer", },
15252762fbdSTony Lindgren 	{ .compatible = "ti,omap3430-timer", },
15352762fbdSTony Lindgren 	{ .compatible = "ti,omap4430-timer", },
15452762fbdSTony Lindgren 	{ .compatible = "ti,omap5430-timer", },
15552762fbdSTony Lindgren 	{ .compatible = "ti,am335x-timer", },
15652762fbdSTony Lindgren 	{ .compatible = "ti,am335x-timer-1ms", },
15752762fbdSTony Lindgren 	{ .compatible = "ti,dm814-timer", },
15852762fbdSTony Lindgren 	{ .compatible = "ti,dm816-timer", },
15952762fbdSTony Lindgren 	{ /* Sentinel */ },
16052762fbdSTony Lindgren };
16152762fbdSTony Lindgren 
16252762fbdSTony Lindgren /*
16352762fbdSTony Lindgren  * Checks that system timers are configured to not reset and idle during
16452762fbdSTony Lindgren  * the generic timer-ti-dm device driver probe. And that the system timer
16552762fbdSTony Lindgren  * source clocks are properly configured. Also, let's not hog any DSP and
16652762fbdSTony Lindgren  * PWM capable timers unnecessarily as system timers.
16752762fbdSTony Lindgren  */
16852762fbdSTony Lindgren static bool __init dmtimer_is_preferred(struct device_node *np)
16952762fbdSTony Lindgren {
17052762fbdSTony Lindgren 	if (!of_device_is_available(np))
17152762fbdSTony Lindgren 		return false;
17252762fbdSTony Lindgren 
17352762fbdSTony Lindgren 	if (!of_property_read_bool(np->parent,
17452762fbdSTony Lindgren 				   "ti,no-reset-on-init"))
17552762fbdSTony Lindgren 		return false;
17652762fbdSTony Lindgren 
17752762fbdSTony Lindgren 	if (!of_property_read_bool(np->parent, "ti,no-idle"))
17852762fbdSTony Lindgren 		return false;
17952762fbdSTony Lindgren 
18052762fbdSTony Lindgren 	/* Secure gptimer12 is always clocked with a fixed source */
18152762fbdSTony Lindgren 	if (!of_property_read_bool(np, "ti,timer-secure")) {
18252762fbdSTony Lindgren 		if (!of_property_read_bool(np, "assigned-clocks"))
18352762fbdSTony Lindgren 			return false;
18452762fbdSTony Lindgren 
18552762fbdSTony Lindgren 		if (!of_property_read_bool(np, "assigned-clock-parents"))
18652762fbdSTony Lindgren 			return false;
18752762fbdSTony Lindgren 	}
18852762fbdSTony Lindgren 
18952762fbdSTony Lindgren 	if (of_property_read_bool(np, "ti,timer-dsp"))
19052762fbdSTony Lindgren 		return false;
19152762fbdSTony Lindgren 
19252762fbdSTony Lindgren 	if (of_property_read_bool(np, "ti,timer-pwm"))
19352762fbdSTony Lindgren 		return false;
19452762fbdSTony Lindgren 
19552762fbdSTony Lindgren 	return true;
19652762fbdSTony Lindgren }
19752762fbdSTony Lindgren 
19852762fbdSTony Lindgren /*
19952762fbdSTony Lindgren  * Finds the first available usable always-on timer, and assigns it to either
20052762fbdSTony Lindgren  * clockevent or clocksource depending if the counter_32k is available on the
20152762fbdSTony Lindgren  * SoC or not.
20252762fbdSTony Lindgren  *
20352762fbdSTony Lindgren  * Some omap3 boards with unreliable oscillator must not use the counter_32k
20452762fbdSTony Lindgren  * or dmtimer1 with 32 KiHz source. Additionally, the boards with unreliable
20552762fbdSTony Lindgren  * oscillator should really set counter_32k as disabled, and delete dmtimer1
20652762fbdSTony Lindgren  * ti,always-on property, but let's not count on it. For these quirky cases,
20752762fbdSTony Lindgren  * we prefer using the always-on secure dmtimer12 with the internal 32 KiHz
20852762fbdSTony Lindgren  * clock as the clocksource, and any available dmtimer as clockevent.
20952762fbdSTony Lindgren  *
21052762fbdSTony Lindgren  * For am437x, we are using am335x style dmtimer clocksource. It is unclear
21152762fbdSTony Lindgren  * if this quirk handling is really needed, but let's change it separately
21252762fbdSTony Lindgren  * based on testing as it might cause side effects.
21352762fbdSTony Lindgren  */
21452762fbdSTony Lindgren static void __init dmtimer_systimer_assign_alwon(void)
21552762fbdSTony Lindgren {
21652762fbdSTony Lindgren 	struct device_node *np;
21752762fbdSTony Lindgren 	u32 pa = 0;
21852762fbdSTony Lindgren 	bool quirk_unreliable_oscillator = false;
21952762fbdSTony Lindgren 
22052762fbdSTony Lindgren 	/* Quirk unreliable 32 KiHz oscillator with incomplete dts */
22152762fbdSTony Lindgren 	if (of_machine_is_compatible("ti,omap3-beagle") ||
22252762fbdSTony Lindgren 	    of_machine_is_compatible("timll,omap3-devkit8000")) {
22352762fbdSTony Lindgren 		quirk_unreliable_oscillator = true;
22452762fbdSTony Lindgren 		counter_32k = -ENODEV;
22552762fbdSTony Lindgren 	}
22652762fbdSTony Lindgren 
22752762fbdSTony Lindgren 	/* Quirk am437x using am335x style dmtimer clocksource */
22852762fbdSTony Lindgren 	if (of_machine_is_compatible("ti,am43"))
22952762fbdSTony Lindgren 		counter_32k = -ENODEV;
23052762fbdSTony Lindgren 
23152762fbdSTony Lindgren 	for_each_matching_node(np, dmtimer_match_table) {
23252762fbdSTony Lindgren 		if (!dmtimer_is_preferred(np))
23352762fbdSTony Lindgren 			continue;
23452762fbdSTony Lindgren 
23552762fbdSTony Lindgren 		if (of_property_read_bool(np, "ti,timer-alwon")) {
23652762fbdSTony Lindgren 			const __be32 *addr;
23752762fbdSTony Lindgren 
23852762fbdSTony Lindgren 			addr = of_get_address(np, 0, NULL, NULL);
23952762fbdSTony Lindgren 			pa = of_translate_address(np, addr);
24052762fbdSTony Lindgren 			if (pa) {
24152762fbdSTony Lindgren 				/* Quirky omap3 boards must use dmtimer12 */
24252762fbdSTony Lindgren 				if (quirk_unreliable_oscillator &&
24352762fbdSTony Lindgren 				    pa == 0x48318000)
24452762fbdSTony Lindgren 					continue;
24552762fbdSTony Lindgren 
24652762fbdSTony Lindgren 				of_node_put(np);
24752762fbdSTony Lindgren 				break;
24852762fbdSTony Lindgren 			}
24952762fbdSTony Lindgren 		}
25052762fbdSTony Lindgren 	}
25152762fbdSTony Lindgren 
25252762fbdSTony Lindgren 	/* Usually no need for dmtimer clocksource if we have counter32 */
25352762fbdSTony Lindgren 	if (counter_32k >= 0) {
25452762fbdSTony Lindgren 		clockevent = pa;
25552762fbdSTony Lindgren 		clocksource = 0;
25652762fbdSTony Lindgren 	} else {
25752762fbdSTony Lindgren 		clocksource = pa;
25852762fbdSTony Lindgren 		clockevent = DMTIMER_INST_DONT_CARE;
25952762fbdSTony Lindgren 	}
26052762fbdSTony Lindgren }
26152762fbdSTony Lindgren 
26252762fbdSTony Lindgren /* Finds the first usable dmtimer, used for the don't care case */
26352762fbdSTony Lindgren static u32 __init dmtimer_systimer_find_first_available(void)
26452762fbdSTony Lindgren {
26552762fbdSTony Lindgren 	struct device_node *np;
26652762fbdSTony Lindgren 	const __be32 *addr;
26752762fbdSTony Lindgren 	u32 pa = 0;
26852762fbdSTony Lindgren 
26952762fbdSTony Lindgren 	for_each_matching_node(np, dmtimer_match_table) {
27052762fbdSTony Lindgren 		if (!dmtimer_is_preferred(np))
27152762fbdSTony Lindgren 			continue;
27252762fbdSTony Lindgren 
27352762fbdSTony Lindgren 		addr = of_get_address(np, 0, NULL, NULL);
27452762fbdSTony Lindgren 		pa = of_translate_address(np, addr);
27552762fbdSTony Lindgren 		if (pa) {
27652762fbdSTony Lindgren 			if (pa == clocksource || pa == clockevent) {
27752762fbdSTony Lindgren 				pa = 0;
27852762fbdSTony Lindgren 				continue;
27952762fbdSTony Lindgren 			}
28052762fbdSTony Lindgren 
28152762fbdSTony Lindgren 			of_node_put(np);
28252762fbdSTony Lindgren 			break;
28352762fbdSTony Lindgren 		}
28452762fbdSTony Lindgren 	}
28552762fbdSTony Lindgren 
28652762fbdSTony Lindgren 	return pa;
28752762fbdSTony Lindgren }
28852762fbdSTony Lindgren 
28952762fbdSTony Lindgren /* Selects the best clocksource and clockevent to use */
29052762fbdSTony Lindgren static void __init dmtimer_systimer_select_best(void)
29152762fbdSTony Lindgren {
29252762fbdSTony Lindgren 	dmtimer_systimer_check_counter32k();
29352762fbdSTony Lindgren 	dmtimer_systimer_assign_alwon();
29452762fbdSTony Lindgren 
29552762fbdSTony Lindgren 	if (clockevent == DMTIMER_INST_DONT_CARE)
29652762fbdSTony Lindgren 		clockevent = dmtimer_systimer_find_first_available();
29752762fbdSTony Lindgren 
29852762fbdSTony Lindgren 	pr_debug("%s: counter_32k: %i clocksource: %08x clockevent: %08x\n",
29952762fbdSTony Lindgren 		 __func__, counter_32k, clocksource, clockevent);
30052762fbdSTony Lindgren }
30152762fbdSTony Lindgren 
30252762fbdSTony Lindgren /* Interface clocks are only available on some SoCs variants */
303*6cfcd556STony Lindgren static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
304*6cfcd556STony Lindgren 					      struct device_node *np,
30552762fbdSTony Lindgren 					      const char *name,
30652762fbdSTony Lindgren 					      unsigned long *rate)
30752762fbdSTony Lindgren {
30852762fbdSTony Lindgren 	struct clk *clock;
30952762fbdSTony Lindgren 	unsigned long r;
310*6cfcd556STony Lindgren 	bool is_ick = false;
31152762fbdSTony Lindgren 	int error;
31252762fbdSTony Lindgren 
313*6cfcd556STony Lindgren 	is_ick = !strncmp(name, "ick", 3);
314*6cfcd556STony Lindgren 
31552762fbdSTony Lindgren 	clock = of_clk_get_by_name(np, name);
316*6cfcd556STony Lindgren 	if ((PTR_ERR(clock) == -EINVAL) && is_ick)
31752762fbdSTony Lindgren 		return 0;
31852762fbdSTony Lindgren 	else if (IS_ERR(clock))
31952762fbdSTony Lindgren 		return PTR_ERR(clock);
32052762fbdSTony Lindgren 
32152762fbdSTony Lindgren 	error = clk_prepare_enable(clock);
32252762fbdSTony Lindgren 	if (error)
32352762fbdSTony Lindgren 		return error;
32452762fbdSTony Lindgren 
32552762fbdSTony Lindgren 	r = clk_get_rate(clock);
32652762fbdSTony Lindgren 	if (!r)
32752762fbdSTony Lindgren 		return -ENODEV;
32852762fbdSTony Lindgren 
329*6cfcd556STony Lindgren 	if (is_ick)
330*6cfcd556STony Lindgren 		t->ick = clock;
331*6cfcd556STony Lindgren 	else
332*6cfcd556STony Lindgren 		t->fck = clock;
333*6cfcd556STony Lindgren 
33452762fbdSTony Lindgren 	*rate = r;
33552762fbdSTony Lindgren 
33652762fbdSTony Lindgren 	return 0;
33752762fbdSTony Lindgren }
33852762fbdSTony Lindgren 
33952762fbdSTony Lindgren static void dmtimer_systimer_enable(struct dmtimer_systimer *t)
34052762fbdSTony Lindgren {
34152762fbdSTony Lindgren 	u32 val;
34252762fbdSTony Lindgren 
34352762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t))
34452762fbdSTony Lindgren 		val = DMTIMER_TYPE1_ENABLE;
34552762fbdSTony Lindgren 	else
34652762fbdSTony Lindgren 		val = DMTIMER_TYPE2_ENABLE;
34752762fbdSTony Lindgren 
34852762fbdSTony Lindgren 	writel_relaxed(val, t->base + t->sysc);
34952762fbdSTony Lindgren }
35052762fbdSTony Lindgren 
35152762fbdSTony Lindgren static void dmtimer_systimer_disable(struct dmtimer_systimer *t)
35252762fbdSTony Lindgren {
353*6cfcd556STony Lindgren 	if (!dmtimer_systimer_revision1(t))
354*6cfcd556STony Lindgren 		return;
355*6cfcd556STony Lindgren 
356*6cfcd556STony Lindgren 	writel_relaxed(DMTIMER_TYPE1_DISABLE, t->base + t->sysc);
35752762fbdSTony Lindgren }
35852762fbdSTony Lindgren 
35952762fbdSTony Lindgren static int __init dmtimer_systimer_setup(struct device_node *np,
36052762fbdSTony Lindgren 					 struct dmtimer_systimer *t)
36152762fbdSTony Lindgren {
36252762fbdSTony Lindgren 	unsigned long rate;
36352762fbdSTony Lindgren 	u8 regbase;
36452762fbdSTony Lindgren 	int error;
36552762fbdSTony Lindgren 
36652762fbdSTony Lindgren 	if (!of_device_is_compatible(np->parent, "ti,sysc"))
36752762fbdSTony Lindgren 		return -EINVAL;
36852762fbdSTony Lindgren 
36952762fbdSTony Lindgren 	t->base = of_iomap(np, 0);
37052762fbdSTony Lindgren 	if (!t->base)
37152762fbdSTony Lindgren 		return -ENXIO;
37252762fbdSTony Lindgren 
37352762fbdSTony Lindgren 	/*
37452762fbdSTony Lindgren 	 * Enable optional assigned-clock-parents configured at the timer
37552762fbdSTony Lindgren 	 * node level. For regular device drivers, this is done automatically
37652762fbdSTony Lindgren 	 * by bus related code such as platform_drv_probe().
37752762fbdSTony Lindgren 	 */
37852762fbdSTony Lindgren 	error = of_clk_set_defaults(np, false);
37952762fbdSTony Lindgren 	if (error < 0)
38052762fbdSTony Lindgren 		pr_err("%s: clock source init failed: %i\n", __func__, error);
38152762fbdSTony Lindgren 
38252762fbdSTony Lindgren 	/* For ti-sysc, we have timer clocks at the parent module level */
383*6cfcd556STony Lindgren 	error = dmtimer_systimer_init_clock(t, np->parent, "fck", &rate);
38452762fbdSTony Lindgren 	if (error)
38552762fbdSTony Lindgren 		goto err_unmap;
38652762fbdSTony Lindgren 
38752762fbdSTony Lindgren 	t->rate = rate;
38852762fbdSTony Lindgren 
389*6cfcd556STony Lindgren 	error = dmtimer_systimer_init_clock(t, np->parent, "ick", &rate);
39052762fbdSTony Lindgren 	if (error)
39152762fbdSTony Lindgren 		goto err_unmap;
39252762fbdSTony Lindgren 
39352762fbdSTony Lindgren 	if (dmtimer_systimer_revision1(t)) {
39452762fbdSTony Lindgren 		t->irq_stat = OMAP_TIMER_V1_STAT_OFFSET;
39552762fbdSTony Lindgren 		t->irq_ena = OMAP_TIMER_V1_INT_EN_OFFSET;
39652762fbdSTony Lindgren 		t->pend = _OMAP_TIMER_WRITE_PEND_OFFSET;
39752762fbdSTony Lindgren 		regbase = 0;
39852762fbdSTony Lindgren 	} else {
39952762fbdSTony Lindgren 		t->irq_stat = OMAP_TIMER_V2_IRQSTATUS;
40052762fbdSTony Lindgren 		t->irq_ena = OMAP_TIMER_V2_IRQENABLE_SET;
40152762fbdSTony Lindgren 		regbase = OMAP_TIMER_V2_FUNC_OFFSET;
40252762fbdSTony Lindgren 		t->pend = regbase + _OMAP_TIMER_WRITE_PEND_OFFSET;
40352762fbdSTony Lindgren 	}
40452762fbdSTony Lindgren 
40552762fbdSTony Lindgren 	t->sysc = OMAP_TIMER_OCP_CFG_OFFSET;
40652762fbdSTony Lindgren 	t->load = regbase + _OMAP_TIMER_LOAD_OFFSET;
40752762fbdSTony Lindgren 	t->counter = regbase + _OMAP_TIMER_COUNTER_OFFSET;
40852762fbdSTony Lindgren 	t->ctrl = regbase + _OMAP_TIMER_CTRL_OFFSET;
40952762fbdSTony Lindgren 	t->wakeup = regbase + _OMAP_TIMER_WAKEUP_EN_OFFSET;
41052762fbdSTony Lindgren 	t->ifctrl = regbase + _OMAP_TIMER_IF_CTRL_OFFSET;
41152762fbdSTony Lindgren 
41252762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
41352762fbdSTony Lindgren 	dmtimer_systimer_reset(t);
41452762fbdSTony Lindgren 	pr_debug("dmtimer rev %08x sysc %08x\n", readl_relaxed(t->base),
41552762fbdSTony Lindgren 		 readl_relaxed(t->base + t->sysc));
41652762fbdSTony Lindgren 
41752762fbdSTony Lindgren 	return 0;
41852762fbdSTony Lindgren 
41952762fbdSTony Lindgren err_unmap:
42052762fbdSTony Lindgren 	iounmap(t->base);
42152762fbdSTony Lindgren 
42252762fbdSTony Lindgren 	return error;
42352762fbdSTony Lindgren }
42452762fbdSTony Lindgren 
42552762fbdSTony Lindgren /* Clockevent */
42652762fbdSTony Lindgren static struct dmtimer_clockevent *
42752762fbdSTony Lindgren to_dmtimer_clockevent(struct clock_event_device *clockevent)
42852762fbdSTony Lindgren {
42952762fbdSTony Lindgren 	return container_of(clockevent, struct dmtimer_clockevent, dev);
43052762fbdSTony Lindgren }
43152762fbdSTony Lindgren 
43252762fbdSTony Lindgren static irqreturn_t dmtimer_clockevent_interrupt(int irq, void *data)
43352762fbdSTony Lindgren {
43452762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = data;
43552762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
43652762fbdSTony Lindgren 
43752762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_stat);
43852762fbdSTony Lindgren 	clkevt->dev.event_handler(&clkevt->dev);
43952762fbdSTony Lindgren 
44052762fbdSTony Lindgren 	return IRQ_HANDLED;
44152762fbdSTony Lindgren }
44252762fbdSTony Lindgren 
44352762fbdSTony Lindgren static int dmtimer_set_next_event(unsigned long cycles,
44452762fbdSTony Lindgren 				  struct clock_event_device *evt)
44552762fbdSTony Lindgren {
44652762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
44752762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
44852762fbdSTony Lindgren 	void __iomem *pend = t->base + t->pend;
44952762fbdSTony Lindgren 
45052762fbdSTony Lindgren 	writel_relaxed(0xffffffff - cycles, t->base + t->counter);
45152762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCRR)
45252762fbdSTony Lindgren 		cpu_relax();
45352762fbdSTony Lindgren 
45452762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST, t->base + t->ctrl);
45552762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCLR)
45652762fbdSTony Lindgren 		cpu_relax();
45752762fbdSTony Lindgren 
45852762fbdSTony Lindgren 	return 0;
45952762fbdSTony Lindgren }
46052762fbdSTony Lindgren 
46152762fbdSTony Lindgren static int dmtimer_clockevent_shutdown(struct clock_event_device *evt)
46252762fbdSTony Lindgren {
46352762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
46452762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
46552762fbdSTony Lindgren 	void __iomem *ctrl = t->base + t->ctrl;
46652762fbdSTony Lindgren 	u32 l;
46752762fbdSTony Lindgren 
46852762fbdSTony Lindgren 	l = readl_relaxed(ctrl);
46952762fbdSTony Lindgren 	if (l & OMAP_TIMER_CTRL_ST) {
47052762fbdSTony Lindgren 		l &= ~BIT(0);
47152762fbdSTony Lindgren 		writel_relaxed(l, ctrl);
47252762fbdSTony Lindgren 		/* Flush posted write */
47352762fbdSTony Lindgren 		l = readl_relaxed(ctrl);
47452762fbdSTony Lindgren 		/*  Wait for functional clock period x 3.5 */
47552762fbdSTony Lindgren 		udelay(3500000 / t->rate + 1);
47652762fbdSTony Lindgren 	}
47752762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_stat);
47852762fbdSTony Lindgren 
47952762fbdSTony Lindgren 	return 0;
48052762fbdSTony Lindgren }
48152762fbdSTony Lindgren 
48252762fbdSTony Lindgren static int dmtimer_set_periodic(struct clock_event_device *evt)
48352762fbdSTony Lindgren {
48452762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
48552762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
48652762fbdSTony Lindgren 	void __iomem *pend = t->base + t->pend;
48752762fbdSTony Lindgren 
48852762fbdSTony Lindgren 	dmtimer_clockevent_shutdown(evt);
48952762fbdSTony Lindgren 
49052762fbdSTony Lindgren 	/* Looks like we need to first set the load value separately */
49152762fbdSTony Lindgren 	writel_relaxed(clkevt->period, t->base + t->load);
49252762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TLDR)
49352762fbdSTony Lindgren 		cpu_relax();
49452762fbdSTony Lindgren 
49552762fbdSTony Lindgren 	writel_relaxed(clkevt->period, t->base + t->counter);
49652762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCRR)
49752762fbdSTony Lindgren 		cpu_relax();
49852762fbdSTony Lindgren 
49952762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
50052762fbdSTony Lindgren 		       t->base + t->ctrl);
50152762fbdSTony Lindgren 	while (readl_relaxed(pend) & WP_TCLR)
50252762fbdSTony Lindgren 		cpu_relax();
50352762fbdSTony Lindgren 
50452762fbdSTony Lindgren 	return 0;
50552762fbdSTony Lindgren }
50652762fbdSTony Lindgren 
50752762fbdSTony Lindgren static void omap_clockevent_idle(struct clock_event_device *evt)
50852762fbdSTony Lindgren {
50952762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
51052762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
51152762fbdSTony Lindgren 
51252762fbdSTony Lindgren 	dmtimer_systimer_disable(t);
513*6cfcd556STony Lindgren 	clk_disable(t->fck);
51452762fbdSTony Lindgren }
51552762fbdSTony Lindgren 
51652762fbdSTony Lindgren static void omap_clockevent_unidle(struct clock_event_device *evt)
51752762fbdSTony Lindgren {
51852762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt = to_dmtimer_clockevent(evt);
51952762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clkevt->t;
520*6cfcd556STony Lindgren 	int error;
521*6cfcd556STony Lindgren 
522*6cfcd556STony Lindgren 	error = clk_enable(t->fck);
523*6cfcd556STony Lindgren 	if (error)
524*6cfcd556STony Lindgren 		pr_err("could not enable timer fck on resume: %i\n", error);
52552762fbdSTony Lindgren 
52652762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
52752762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
52852762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
52952762fbdSTony Lindgren }
53052762fbdSTony Lindgren 
53152762fbdSTony Lindgren static int __init dmtimer_clockevent_init(struct device_node *np)
53252762fbdSTony Lindgren {
53352762fbdSTony Lindgren 	struct dmtimer_clockevent *clkevt;
53452762fbdSTony Lindgren 	struct clock_event_device *dev;
53552762fbdSTony Lindgren 	struct dmtimer_systimer *t;
53652762fbdSTony Lindgren 	int error;
53752762fbdSTony Lindgren 
53852762fbdSTony Lindgren 	clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
53952762fbdSTony Lindgren 	if (!clkevt)
54052762fbdSTony Lindgren 		return -ENOMEM;
54152762fbdSTony Lindgren 
54252762fbdSTony Lindgren 	t = &clkevt->t;
54352762fbdSTony Lindgren 	dev = &clkevt->dev;
54452762fbdSTony Lindgren 
54552762fbdSTony Lindgren 	/*
54652762fbdSTony Lindgren 	 * We mostly use cpuidle_coupled with ARM local timers for runtime,
54752762fbdSTony Lindgren 	 * so there's probably no use for CLOCK_EVT_FEAT_DYNIRQ here.
54852762fbdSTony Lindgren 	 */
54952762fbdSTony Lindgren 	dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
55052762fbdSTony Lindgren 	dev->rating = 300;
55152762fbdSTony Lindgren 	dev->set_next_event = dmtimer_set_next_event;
55252762fbdSTony Lindgren 	dev->set_state_shutdown = dmtimer_clockevent_shutdown;
55352762fbdSTony Lindgren 	dev->set_state_periodic = dmtimer_set_periodic;
55452762fbdSTony Lindgren 	dev->set_state_oneshot = dmtimer_clockevent_shutdown;
55552762fbdSTony Lindgren 	dev->tick_resume = dmtimer_clockevent_shutdown;
55652762fbdSTony Lindgren 	dev->cpumask = cpu_possible_mask;
55752762fbdSTony Lindgren 
55852762fbdSTony Lindgren 	dev->irq = irq_of_parse_and_map(np, 0);
55952762fbdSTony Lindgren 	if (!dev->irq) {
56052762fbdSTony Lindgren 		error = -ENXIO;
56152762fbdSTony Lindgren 		goto err_out_free;
56252762fbdSTony Lindgren 	}
56352762fbdSTony Lindgren 
56452762fbdSTony Lindgren 	error = dmtimer_systimer_setup(np, &clkevt->t);
56552762fbdSTony Lindgren 	if (error)
56652762fbdSTony Lindgren 		goto err_out_free;
56752762fbdSTony Lindgren 
56852762fbdSTony Lindgren 	clkevt->period = 0xffffffff - DIV_ROUND_CLOSEST(t->rate, HZ);
56952762fbdSTony Lindgren 
57052762fbdSTony Lindgren 	/*
57152762fbdSTony Lindgren 	 * For clock-event timers we never read the timer counter and
57252762fbdSTony Lindgren 	 * so we are not impacted by errata i103 and i767. Therefore,
57352762fbdSTony Lindgren 	 * we can safely ignore this errata for clock-event timers.
57452762fbdSTony Lindgren 	 */
57552762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_POSTED, t->base + t->ifctrl);
57652762fbdSTony Lindgren 
57752762fbdSTony Lindgren 	error = request_irq(dev->irq, dmtimer_clockevent_interrupt,
57852762fbdSTony Lindgren 			    IRQF_TIMER, "clockevent", clkevt);
57952762fbdSTony Lindgren 	if (error)
58052762fbdSTony Lindgren 		goto err_out_unmap;
58152762fbdSTony Lindgren 
58252762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
58352762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
58452762fbdSTony Lindgren 
58552762fbdSTony Lindgren 	pr_info("TI gptimer clockevent: %s%lu Hz at %pOF\n",
58652762fbdSTony Lindgren 		of_find_property(np, "ti,timer-alwon", NULL) ?
58752762fbdSTony Lindgren 		"always-on " : "", t->rate, np->parent);
58852762fbdSTony Lindgren 
58952762fbdSTony Lindgren 	clockevents_config_and_register(dev, t->rate,
59052762fbdSTony Lindgren 					3, /* Timer internal resynch latency */
59152762fbdSTony Lindgren 					0xffffffff);
59252762fbdSTony Lindgren 
593*6cfcd556STony Lindgren 	if (of_machine_is_compatible("ti,am33xx") ||
594*6cfcd556STony Lindgren 	    of_machine_is_compatible("ti,am43")) {
59552762fbdSTony Lindgren 		dev->suspend = omap_clockevent_idle;
59652762fbdSTony Lindgren 		dev->resume = omap_clockevent_unidle;
59752762fbdSTony Lindgren 	}
59852762fbdSTony Lindgren 
59952762fbdSTony Lindgren 	return 0;
60052762fbdSTony Lindgren 
60152762fbdSTony Lindgren err_out_unmap:
60252762fbdSTony Lindgren 	iounmap(t->base);
60352762fbdSTony Lindgren 
60452762fbdSTony Lindgren err_out_free:
60552762fbdSTony Lindgren 	kfree(clkevt);
60652762fbdSTony Lindgren 
60752762fbdSTony Lindgren 	return error;
60852762fbdSTony Lindgren }
60952762fbdSTony Lindgren 
61052762fbdSTony Lindgren /* Clocksource */
61152762fbdSTony Lindgren static struct dmtimer_clocksource *
61252762fbdSTony Lindgren to_dmtimer_clocksource(struct clocksource *cs)
61352762fbdSTony Lindgren {
61452762fbdSTony Lindgren 	return container_of(cs, struct dmtimer_clocksource, dev);
61552762fbdSTony Lindgren }
61652762fbdSTony Lindgren 
61752762fbdSTony Lindgren static u64 dmtimer_clocksource_read_cycles(struct clocksource *cs)
61852762fbdSTony Lindgren {
61952762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
62052762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
62152762fbdSTony Lindgren 
62252762fbdSTony Lindgren 	return (u64)readl_relaxed(t->base + t->counter);
62352762fbdSTony Lindgren }
62452762fbdSTony Lindgren 
62552762fbdSTony Lindgren static void __iomem *dmtimer_sched_clock_counter;
62652762fbdSTony Lindgren 
62752762fbdSTony Lindgren static u64 notrace dmtimer_read_sched_clock(void)
62852762fbdSTony Lindgren {
62952762fbdSTony Lindgren 	return readl_relaxed(dmtimer_sched_clock_counter);
63052762fbdSTony Lindgren }
63152762fbdSTony Lindgren 
63252762fbdSTony Lindgren static void dmtimer_clocksource_suspend(struct clocksource *cs)
63352762fbdSTony Lindgren {
63452762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
63552762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
63652762fbdSTony Lindgren 
63752762fbdSTony Lindgren 	clksrc->loadval = readl_relaxed(t->base + t->counter);
63852762fbdSTony Lindgren 	dmtimer_systimer_disable(t);
639*6cfcd556STony Lindgren 	clk_disable(t->fck);
64052762fbdSTony Lindgren }
64152762fbdSTony Lindgren 
64252762fbdSTony Lindgren static void dmtimer_clocksource_resume(struct clocksource *cs)
64352762fbdSTony Lindgren {
64452762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc = to_dmtimer_clocksource(cs);
64552762fbdSTony Lindgren 	struct dmtimer_systimer *t = &clksrc->t;
646*6cfcd556STony Lindgren 	int error;
647*6cfcd556STony Lindgren 
648*6cfcd556STony Lindgren 	error = clk_enable(t->fck);
649*6cfcd556STony Lindgren 	if (error)
650*6cfcd556STony Lindgren 		pr_err("could not enable timer fck on resume: %i\n", error);
65152762fbdSTony Lindgren 
65252762fbdSTony Lindgren 	dmtimer_systimer_enable(t);
65352762fbdSTony Lindgren 	writel_relaxed(clksrc->loadval, t->base + t->counter);
65452762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
65552762fbdSTony Lindgren 		       t->base + t->ctrl);
65652762fbdSTony Lindgren }
65752762fbdSTony Lindgren 
65852762fbdSTony Lindgren static int __init dmtimer_clocksource_init(struct device_node *np)
65952762fbdSTony Lindgren {
66052762fbdSTony Lindgren 	struct dmtimer_clocksource *clksrc;
66152762fbdSTony Lindgren 	struct dmtimer_systimer *t;
66252762fbdSTony Lindgren 	struct clocksource *dev;
66352762fbdSTony Lindgren 	int error;
66452762fbdSTony Lindgren 
66552762fbdSTony Lindgren 	clksrc = kzalloc(sizeof(*clksrc), GFP_KERNEL);
66652762fbdSTony Lindgren 	if (!clksrc)
66752762fbdSTony Lindgren 		return -ENOMEM;
66852762fbdSTony Lindgren 
66952762fbdSTony Lindgren 	dev = &clksrc->dev;
67052762fbdSTony Lindgren 	t = &clksrc->t;
67152762fbdSTony Lindgren 
67252762fbdSTony Lindgren 	error = dmtimer_systimer_setup(np, t);
67352762fbdSTony Lindgren 	if (error)
67452762fbdSTony Lindgren 		goto err_out_free;
67552762fbdSTony Lindgren 
67652762fbdSTony Lindgren 	dev->name = "dmtimer";
67752762fbdSTony Lindgren 	dev->rating = 300;
67852762fbdSTony Lindgren 	dev->read = dmtimer_clocksource_read_cycles;
67952762fbdSTony Lindgren 	dev->mask = CLOCKSOURCE_MASK(32);
68052762fbdSTony Lindgren 	dev->flags = CLOCK_SOURCE_IS_CONTINUOUS;
68152762fbdSTony Lindgren 
682*6cfcd556STony Lindgren 	/* Unlike for clockevent, legacy code sets suspend only for am4 */
683*6cfcd556STony Lindgren 	if (of_machine_is_compatible("ti,am43")) {
68452762fbdSTony Lindgren 		dev->suspend = dmtimer_clocksource_suspend;
68552762fbdSTony Lindgren 		dev->resume = dmtimer_clocksource_resume;
68652762fbdSTony Lindgren 	}
68752762fbdSTony Lindgren 
68852762fbdSTony Lindgren 	writel_relaxed(0, t->base + t->counter);
68952762fbdSTony Lindgren 	writel_relaxed(OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
69052762fbdSTony Lindgren 		       t->base + t->ctrl);
69152762fbdSTony Lindgren 
69252762fbdSTony Lindgren 	pr_info("TI gptimer clocksource: %s%pOF\n",
69352762fbdSTony Lindgren 		of_find_property(np, "ti,timer-alwon", NULL) ?
69452762fbdSTony Lindgren 		"always-on " : "", np->parent);
69552762fbdSTony Lindgren 
69652762fbdSTony Lindgren 	if (!dmtimer_sched_clock_counter) {
69752762fbdSTony Lindgren 		dmtimer_sched_clock_counter = t->base + t->counter;
69852762fbdSTony Lindgren 		sched_clock_register(dmtimer_read_sched_clock, 32, t->rate);
69952762fbdSTony Lindgren 	}
70052762fbdSTony Lindgren 
70152762fbdSTony Lindgren 	if (clocksource_register_hz(dev, t->rate))
70252762fbdSTony Lindgren 		pr_err("Could not register clocksource %pOF\n", np);
70352762fbdSTony Lindgren 
70452762fbdSTony Lindgren 	return 0;
70552762fbdSTony Lindgren 
70652762fbdSTony Lindgren err_out_free:
70752762fbdSTony Lindgren 	kfree(clksrc);
70852762fbdSTony Lindgren 
70952762fbdSTony Lindgren 	return -ENODEV;
71052762fbdSTony Lindgren }
71152762fbdSTony Lindgren 
71252762fbdSTony Lindgren /*
71352762fbdSTony Lindgren  * To detect between a clocksource and clockevent, we assume the device tree
71452762fbdSTony Lindgren  * has no interrupts configured for a clocksource timer.
71552762fbdSTony Lindgren  */
71652762fbdSTony Lindgren static int __init dmtimer_systimer_init(struct device_node *np)
71752762fbdSTony Lindgren {
71852762fbdSTony Lindgren 	const __be32 *addr;
71952762fbdSTony Lindgren 	u32 pa;
72052762fbdSTony Lindgren 
72152762fbdSTony Lindgren 	/* One time init for the preferred timer configuration */
72252762fbdSTony Lindgren 	if (!clocksource && !clockevent)
72352762fbdSTony Lindgren 		dmtimer_systimer_select_best();
72452762fbdSTony Lindgren 
72552762fbdSTony Lindgren 	if (!clocksource && !clockevent) {
726ac593e62SColin Ian King 		pr_err("%s: unable to detect system timers, update dtb?\n",
72752762fbdSTony Lindgren 		       __func__);
72852762fbdSTony Lindgren 
72952762fbdSTony Lindgren 		return -EINVAL;
73052762fbdSTony Lindgren 	}
73152762fbdSTony Lindgren 
73252762fbdSTony Lindgren 	addr = of_get_address(np, 0, NULL, NULL);
73352762fbdSTony Lindgren 	pa = of_translate_address(np, addr);
73452762fbdSTony Lindgren 	if (!pa)
73552762fbdSTony Lindgren 		return -EINVAL;
73652762fbdSTony Lindgren 
73752762fbdSTony Lindgren 	if (counter_32k <= 0 && clocksource == pa)
73852762fbdSTony Lindgren 		return dmtimer_clocksource_init(np);
73952762fbdSTony Lindgren 
74052762fbdSTony Lindgren 	if (clockevent == pa)
74152762fbdSTony Lindgren 		return dmtimer_clockevent_init(np);
74252762fbdSTony Lindgren 
74352762fbdSTony Lindgren 	return 0;
74452762fbdSTony Lindgren }
74552762fbdSTony Lindgren 
74652762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap2, "ti,omap2420-timer", dmtimer_systimer_init);
74752762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap3, "ti,omap3430-timer", dmtimer_systimer_init);
74852762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap4, "ti,omap4430-timer", dmtimer_systimer_init);
74952762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_omap5, "ti,omap5430-timer", dmtimer_systimer_init);
75052762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_am33x, "ti,am335x-timer", dmtimer_systimer_init);
75152762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_am3ms, "ti,am335x-timer-1ms", dmtimer_systimer_init);
75252762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_dm814, "ti,dm814-timer", dmtimer_systimer_init);
75352762fbdSTony Lindgren TIMER_OF_DECLARE(systimer_dm816, "ti,dm816-timer", dmtimer_systimer_init);
754