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