1f5bf0ee4SLinus Walleij /*
2f5bf0ee4SLinus Walleij  * Faraday Technology FTTMR010 timer driver
3f5bf0ee4SLinus Walleij  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
4f5bf0ee4SLinus Walleij  *
5f5bf0ee4SLinus Walleij  * Based on a rewrite of arch/arm/mach-gemini/timer.c:
6f5bf0ee4SLinus Walleij  * Copyright (C) 2001-2006 Storlink, Corp.
7f5bf0ee4SLinus Walleij  * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
8f5bf0ee4SLinus Walleij  */
9f5bf0ee4SLinus Walleij #include <linux/interrupt.h>
10f5bf0ee4SLinus Walleij #include <linux/io.h>
11f5bf0ee4SLinus Walleij #include <linux/of.h>
12f5bf0ee4SLinus Walleij #include <linux/of_address.h>
13f5bf0ee4SLinus Walleij #include <linux/of_irq.h>
14f5bf0ee4SLinus Walleij #include <linux/clockchips.h>
15f5bf0ee4SLinus Walleij #include <linux/clocksource.h>
16f5bf0ee4SLinus Walleij #include <linux/sched_clock.h>
1728e71e2fSLinus Walleij #include <linux/clk.h>
18e7bad212SLinus Walleij #include <linux/slab.h>
19d0d76d57SLinus Walleij #include <linux/bitops.h>
20385c98fcSLinus Walleij #include <linux/delay.h>
21f5bf0ee4SLinus Walleij 
22f5bf0ee4SLinus Walleij /*
23f5bf0ee4SLinus Walleij  * Register definitions for the timers
24f5bf0ee4SLinus Walleij  */
25f5bf0ee4SLinus Walleij #define TIMER1_COUNT		(0x00)
26f5bf0ee4SLinus Walleij #define TIMER1_LOAD		(0x04)
27f5bf0ee4SLinus Walleij #define TIMER1_MATCH1		(0x08)
28f5bf0ee4SLinus Walleij #define TIMER1_MATCH2		(0x0c)
29f5bf0ee4SLinus Walleij #define TIMER2_COUNT		(0x10)
30f5bf0ee4SLinus Walleij #define TIMER2_LOAD		(0x14)
31f5bf0ee4SLinus Walleij #define TIMER2_MATCH1		(0x18)
32f5bf0ee4SLinus Walleij #define TIMER2_MATCH2		(0x1c)
33f5bf0ee4SLinus Walleij #define TIMER3_COUNT		(0x20)
34f5bf0ee4SLinus Walleij #define TIMER3_LOAD		(0x24)
35f5bf0ee4SLinus Walleij #define TIMER3_MATCH1		(0x28)
36f5bf0ee4SLinus Walleij #define TIMER3_MATCH2		(0x2c)
37f5bf0ee4SLinus Walleij #define TIMER_CR		(0x30)
38f5bf0ee4SLinus Walleij #define TIMER_INTR_STATE	(0x34)
39f5bf0ee4SLinus Walleij #define TIMER_INTR_MASK		(0x38)
40f5bf0ee4SLinus Walleij 
41d0d76d57SLinus Walleij #define TIMER_1_CR_ENABLE	BIT(0)
42d0d76d57SLinus Walleij #define TIMER_1_CR_CLOCK	BIT(1)
43d0d76d57SLinus Walleij #define TIMER_1_CR_INT		BIT(2)
44d0d76d57SLinus Walleij #define TIMER_2_CR_ENABLE	BIT(3)
45d0d76d57SLinus Walleij #define TIMER_2_CR_CLOCK	BIT(4)
46d0d76d57SLinus Walleij #define TIMER_2_CR_INT		BIT(5)
47d0d76d57SLinus Walleij #define TIMER_3_CR_ENABLE	BIT(6)
48d0d76d57SLinus Walleij #define TIMER_3_CR_CLOCK	BIT(7)
49d0d76d57SLinus Walleij #define TIMER_3_CR_INT		BIT(8)
50d0d76d57SLinus Walleij #define TIMER_1_CR_UPDOWN	BIT(9)
51d0d76d57SLinus Walleij #define TIMER_2_CR_UPDOWN	BIT(10)
52d0d76d57SLinus Walleij #define TIMER_3_CR_UPDOWN	BIT(11)
53f5bf0ee4SLinus Walleij 
54ec14ba1eSLinus Walleij /*
55ec14ba1eSLinus Walleij  * The Aspeed AST2400 moves bits around in the control register
56ec14ba1eSLinus Walleij  * and lacks bits for setting the timer to count upwards.
57ec14ba1eSLinus Walleij  */
58ec14ba1eSLinus Walleij #define TIMER_1_CR_ASPEED_ENABLE	BIT(0)
59ec14ba1eSLinus Walleij #define TIMER_1_CR_ASPEED_CLOCK		BIT(1)
60ec14ba1eSLinus Walleij #define TIMER_1_CR_ASPEED_INT		BIT(2)
61ec14ba1eSLinus Walleij #define TIMER_2_CR_ASPEED_ENABLE	BIT(4)
62ec14ba1eSLinus Walleij #define TIMER_2_CR_ASPEED_CLOCK		BIT(5)
63ec14ba1eSLinus Walleij #define TIMER_2_CR_ASPEED_INT		BIT(6)
64ec14ba1eSLinus Walleij #define TIMER_3_CR_ASPEED_ENABLE	BIT(8)
65ec14ba1eSLinus Walleij #define TIMER_3_CR_ASPEED_CLOCK		BIT(9)
66ec14ba1eSLinus Walleij #define TIMER_3_CR_ASPEED_INT		BIT(10)
67ec14ba1eSLinus Walleij 
68d0d76d57SLinus Walleij #define TIMER_1_INT_MATCH1	BIT(0)
69d0d76d57SLinus Walleij #define TIMER_1_INT_MATCH2	BIT(1)
70d0d76d57SLinus Walleij #define TIMER_1_INT_OVERFLOW	BIT(2)
71d0d76d57SLinus Walleij #define TIMER_2_INT_MATCH1	BIT(3)
72d0d76d57SLinus Walleij #define TIMER_2_INT_MATCH2	BIT(4)
73d0d76d57SLinus Walleij #define TIMER_2_INT_OVERFLOW	BIT(5)
74d0d76d57SLinus Walleij #define TIMER_3_INT_MATCH1	BIT(6)
75d0d76d57SLinus Walleij #define TIMER_3_INT_MATCH2	BIT(7)
76d0d76d57SLinus Walleij #define TIMER_3_INT_OVERFLOW	BIT(8)
77f5bf0ee4SLinus Walleij #define TIMER_INT_ALL_MASK	0x1ff
78f5bf0ee4SLinus Walleij 
79e7bad212SLinus Walleij struct fttmr010 {
80e7bad212SLinus Walleij 	void __iomem *base;
81e7bad212SLinus Walleij 	unsigned int tick_rate;
82ec14ba1eSLinus Walleij 	bool count_down;
83ec14ba1eSLinus Walleij 	u32 t1_enable_val;
84e7bad212SLinus Walleij 	struct clock_event_device clkevt;
85385c98fcSLinus Walleij #ifdef CONFIG_ARM
86385c98fcSLinus Walleij 	struct delay_timer delay_timer;
87385c98fcSLinus Walleij #endif
88e7bad212SLinus Walleij };
89e7bad212SLinus Walleij 
90385c98fcSLinus Walleij /*
91385c98fcSLinus Walleij  * A local singleton used by sched_clock and delay timer reads, which are
92385c98fcSLinus Walleij  * fast and stateless
93385c98fcSLinus Walleij  */
94e7bad212SLinus Walleij static struct fttmr010 *local_fttmr;
95e7bad212SLinus Walleij 
96e7bad212SLinus Walleij static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
97e7bad212SLinus Walleij {
98e7bad212SLinus Walleij 	return container_of(evt, struct fttmr010, clkevt);
99e7bad212SLinus Walleij }
100f5bf0ee4SLinus Walleij 
101385c98fcSLinus Walleij static unsigned long fttmr010_read_current_timer_up(void)
102385c98fcSLinus Walleij {
103385c98fcSLinus Walleij 	return readl(local_fttmr->base + TIMER2_COUNT);
104385c98fcSLinus Walleij }
105385c98fcSLinus Walleij 
106385c98fcSLinus Walleij static unsigned long fttmr010_read_current_timer_down(void)
107385c98fcSLinus Walleij {
108385c98fcSLinus Walleij 	return ~readl(local_fttmr->base + TIMER2_COUNT);
109385c98fcSLinus Walleij }
110385c98fcSLinus Walleij 
111c4779902SLinus Walleij static u64 notrace fttmr010_read_sched_clock_up(void)
112c4779902SLinus Walleij {
113c4779902SLinus Walleij 	return fttmr010_read_current_timer_up();
114c4779902SLinus Walleij }
115c4779902SLinus Walleij 
116c4779902SLinus Walleij static u64 notrace fttmr010_read_sched_clock_down(void)
117c4779902SLinus Walleij {
118c4779902SLinus Walleij 	return fttmr010_read_current_timer_down();
119c4779902SLinus Walleij }
120385c98fcSLinus Walleij 
121f5bf0ee4SLinus Walleij static int fttmr010_timer_set_next_event(unsigned long cycles,
122f5bf0ee4SLinus Walleij 				       struct clock_event_device *evt)
123f5bf0ee4SLinus Walleij {
124e7bad212SLinus Walleij 	struct fttmr010 *fttmr010 = to_fttmr010(evt);
125f5bf0ee4SLinus Walleij 	u32 cr;
126f5bf0ee4SLinus Walleij 
127ec14ba1eSLinus Walleij 	/* Stop */
128ec14ba1eSLinus Walleij 	cr = readl(fttmr010->base + TIMER_CR);
129ec14ba1eSLinus Walleij 	cr &= ~fttmr010->t1_enable_val;
130ec14ba1eSLinus Walleij 	writel(cr, fttmr010->base + TIMER_CR);
131ec14ba1eSLinus Walleij 
132ec14ba1eSLinus Walleij 	/* Setup the match register forward/backward in time */
133e7bad212SLinus Walleij 	cr = readl(fttmr010->base + TIMER1_COUNT);
134ec14ba1eSLinus Walleij 	if (fttmr010->count_down)
135ec14ba1eSLinus Walleij 		cr -= cycles;
136ec14ba1eSLinus Walleij 	else
137ec14ba1eSLinus Walleij 		cr += cycles;
138ec14ba1eSLinus Walleij 	writel(cr, fttmr010->base + TIMER1_MATCH1);
139ec14ba1eSLinus Walleij 
140ec14ba1eSLinus Walleij 	/* Start */
141ec14ba1eSLinus Walleij 	cr = readl(fttmr010->base + TIMER_CR);
142ec14ba1eSLinus Walleij 	cr |= fttmr010->t1_enable_val;
143ec14ba1eSLinus Walleij 	writel(cr, fttmr010->base + TIMER_CR);
144f5bf0ee4SLinus Walleij 
145f5bf0ee4SLinus Walleij 	return 0;
146f5bf0ee4SLinus Walleij }
147f5bf0ee4SLinus Walleij 
148f5bf0ee4SLinus Walleij static int fttmr010_timer_shutdown(struct clock_event_device *evt)
149f5bf0ee4SLinus Walleij {
150e7bad212SLinus Walleij 	struct fttmr010 *fttmr010 = to_fttmr010(evt);
151f5bf0ee4SLinus Walleij 	u32 cr;
152f5bf0ee4SLinus Walleij 
153ec14ba1eSLinus Walleij 	/* Stop */
154e7bad212SLinus Walleij 	cr = readl(fttmr010->base + TIMER_CR);
155ec14ba1eSLinus Walleij 	cr &= ~fttmr010->t1_enable_val;
156e7bad212SLinus Walleij 	writel(cr, fttmr010->base + TIMER_CR);
157e7bad212SLinus Walleij 
158e7bad212SLinus Walleij 	return 0;
159e7bad212SLinus Walleij }
160e7bad212SLinus Walleij 
161e7bad212SLinus Walleij static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
162e7bad212SLinus Walleij {
163e7bad212SLinus Walleij 	struct fttmr010 *fttmr010 = to_fttmr010(evt);
164e7bad212SLinus Walleij 	u32 cr;
165e7bad212SLinus Walleij 
166ec14ba1eSLinus Walleij 	/* Stop */
167e7bad212SLinus Walleij 	cr = readl(fttmr010->base + TIMER_CR);
168ec14ba1eSLinus Walleij 	cr &= ~fttmr010->t1_enable_val;
169e7bad212SLinus Walleij 	writel(cr, fttmr010->base + TIMER_CR);
170f5bf0ee4SLinus Walleij 
171ec14ba1eSLinus Walleij 	/* Setup counter start from 0 or ~0 */
172e7bad212SLinus Walleij 	writel(0, fttmr010->base + TIMER1_COUNT);
173ec14ba1eSLinus Walleij 	if (fttmr010->count_down)
174ec14ba1eSLinus Walleij 		writel(~0, fttmr010->base + TIMER1_LOAD);
175ec14ba1eSLinus Walleij 	else
176e7bad212SLinus Walleij 		writel(0, fttmr010->base + TIMER1_LOAD);
177f5bf0ee4SLinus Walleij 
178e7bad212SLinus Walleij 	/* Enable interrupt */
179e7bad212SLinus Walleij 	cr = readl(fttmr010->base + TIMER_INTR_MASK);
180f5bf0ee4SLinus Walleij 	cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
181f5bf0ee4SLinus Walleij 	cr |= TIMER_1_INT_MATCH1;
182e7bad212SLinus Walleij 	writel(cr, fttmr010->base + TIMER_INTR_MASK);
183f5bf0ee4SLinus Walleij 
184f5bf0ee4SLinus Walleij 	return 0;
185f5bf0ee4SLinus Walleij }
186f5bf0ee4SLinus Walleij 
187f5bf0ee4SLinus Walleij static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
188f5bf0ee4SLinus Walleij {
189e7bad212SLinus Walleij 	struct fttmr010 *fttmr010 = to_fttmr010(evt);
190e7bad212SLinus Walleij 	u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);
191f5bf0ee4SLinus Walleij 	u32 cr;
192f5bf0ee4SLinus Walleij 
193ec14ba1eSLinus Walleij 	/* Stop */
194e7bad212SLinus Walleij 	cr = readl(fttmr010->base + TIMER_CR);
195ec14ba1eSLinus Walleij 	cr &= ~fttmr010->t1_enable_val;
196e7bad212SLinus Walleij 	writel(cr, fttmr010->base + TIMER_CR);
197f5bf0ee4SLinus Walleij 
198ec14ba1eSLinus Walleij 	/* Setup timer to fire at 1/HZ intervals. */
199ec14ba1eSLinus Walleij 	if (fttmr010->count_down) {
200ec14ba1eSLinus Walleij 		writel(period, fttmr010->base + TIMER1_LOAD);
201ec14ba1eSLinus Walleij 		writel(0, fttmr010->base + TIMER1_MATCH1);
202ec14ba1eSLinus Walleij 	} else {
203f5bf0ee4SLinus Walleij 		cr = 0xffffffff - (period - 1);
204e7bad212SLinus Walleij 		writel(cr, fttmr010->base + TIMER1_COUNT);
205e7bad212SLinus Walleij 		writel(cr, fttmr010->base + TIMER1_LOAD);
206f5bf0ee4SLinus Walleij 
207ec14ba1eSLinus Walleij 		/* Enable interrupt on overflow */
208e7bad212SLinus Walleij 		cr = readl(fttmr010->base + TIMER_INTR_MASK);
209f5bf0ee4SLinus Walleij 		cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
210f5bf0ee4SLinus Walleij 		cr |= TIMER_1_INT_OVERFLOW;
211e7bad212SLinus Walleij 		writel(cr, fttmr010->base + TIMER_INTR_MASK);
212ec14ba1eSLinus Walleij 	}
213f5bf0ee4SLinus Walleij 
214f5bf0ee4SLinus Walleij 	/* Start the timer */
215e7bad212SLinus Walleij 	cr = readl(fttmr010->base + TIMER_CR);
216ec14ba1eSLinus Walleij 	cr |= fttmr010->t1_enable_val;
217e7bad212SLinus Walleij 	writel(cr, fttmr010->base + TIMER_CR);
218f5bf0ee4SLinus Walleij 
219f5bf0ee4SLinus Walleij 	return 0;
220f5bf0ee4SLinus Walleij }
221f5bf0ee4SLinus Walleij 
222f5bf0ee4SLinus Walleij /*
223f5bf0ee4SLinus Walleij  * IRQ handler for the timer
224f5bf0ee4SLinus Walleij  */
225f5bf0ee4SLinus Walleij static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
226f5bf0ee4SLinus Walleij {
227e7bad212SLinus Walleij 	struct clock_event_device *evt = dev_id;
228f5bf0ee4SLinus Walleij 
229f5bf0ee4SLinus Walleij 	evt->event_handler(evt);
230f5bf0ee4SLinus Walleij 	return IRQ_HANDLED;
231f5bf0ee4SLinus Walleij }
232f5bf0ee4SLinus Walleij 
233ef89718aSDaniel Lezcano static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
234f5bf0ee4SLinus Walleij {
235e7bad212SLinus Walleij 	struct fttmr010 *fttmr010;
236f5bf0ee4SLinus Walleij 	int irq;
237dd98442eSLinus Walleij 	struct clk *clk;
238dd98442eSLinus Walleij 	int ret;
239ec14ba1eSLinus Walleij 	u32 val;
240dd98442eSLinus Walleij 
241dd98442eSLinus Walleij 	/*
242dd98442eSLinus Walleij 	 * These implementations require a clock reference.
243dd98442eSLinus Walleij 	 * FIXME: we currently only support clocking using PCLK
244dd98442eSLinus Walleij 	 * and using EXTCLK is not supported in the driver.
245dd98442eSLinus Walleij 	 */
246dd98442eSLinus Walleij 	clk = of_clk_get_by_name(np, "PCLK");
247dd98442eSLinus Walleij 	if (IS_ERR(clk)) {
248dd98442eSLinus Walleij 		pr_err("could not get PCLK\n");
249dd98442eSLinus Walleij 		return PTR_ERR(clk);
250dd98442eSLinus Walleij 	}
251dd98442eSLinus Walleij 	ret = clk_prepare_enable(clk);
252dd98442eSLinus Walleij 	if (ret) {
253dd98442eSLinus Walleij 		pr_err("failed to enable PCLK\n");
254dd98442eSLinus Walleij 		return ret;
255dd98442eSLinus Walleij 	}
256f5bf0ee4SLinus Walleij 
257e7bad212SLinus Walleij 	fttmr010 = kzalloc(sizeof(*fttmr010), GFP_KERNEL);
258e7bad212SLinus Walleij 	if (!fttmr010) {
259e7bad212SLinus Walleij 		ret = -ENOMEM;
260e7bad212SLinus Walleij 		goto out_disable_clock;
261e7bad212SLinus Walleij 	}
262e7bad212SLinus Walleij 	fttmr010->tick_rate = clk_get_rate(clk);
263e7bad212SLinus Walleij 
264e7bad212SLinus Walleij 	fttmr010->base = of_iomap(np, 0);
265e7bad212SLinus Walleij 	if (!fttmr010->base) {
266*1893428bSArvind Yadav 		pr_err("Can't remap registers\n");
267e7bad212SLinus Walleij 		ret = -ENXIO;
268e7bad212SLinus Walleij 		goto out_free;
269f5bf0ee4SLinus Walleij 	}
270f5bf0ee4SLinus Walleij 	/* IRQ for timer 1 */
271f5bf0ee4SLinus Walleij 	irq = irq_of_parse_and_map(np, 0);
272f5bf0ee4SLinus Walleij 	if (irq <= 0) {
273*1893428bSArvind Yadav 		pr_err("Can't parse IRQ\n");
274e7bad212SLinus Walleij 		ret = -EINVAL;
275e7bad212SLinus Walleij 		goto out_unmap;
276f5bf0ee4SLinus Walleij 	}
277f5bf0ee4SLinus Walleij 
278f5bf0ee4SLinus Walleij 	/*
279ec14ba1eSLinus Walleij 	 * The Aspeed AST2400 moves bits around in the control register,
280ec14ba1eSLinus Walleij 	 * otherwise it works the same.
281ec14ba1eSLinus Walleij 	 */
282ef89718aSDaniel Lezcano 	if (is_aspeed) {
283ec14ba1eSLinus Walleij 		fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE |
284ec14ba1eSLinus Walleij 			TIMER_1_CR_ASPEED_INT;
285ec14ba1eSLinus Walleij 		/* Downward not available */
286ec14ba1eSLinus Walleij 		fttmr010->count_down = true;
287ec14ba1eSLinus Walleij 	} else {
288ec14ba1eSLinus Walleij 		fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
289ec14ba1eSLinus Walleij 	}
290ec14ba1eSLinus Walleij 
291ec14ba1eSLinus Walleij 	/*
292f5bf0ee4SLinus Walleij 	 * Reset the interrupt mask and status
293f5bf0ee4SLinus Walleij 	 */
294e7bad212SLinus Walleij 	writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK);
295e7bad212SLinus Walleij 	writel(0, fttmr010->base + TIMER_INTR_STATE);
296ec14ba1eSLinus Walleij 
297ec14ba1eSLinus Walleij 	/*
298ec14ba1eSLinus Walleij 	 * Enable timer 1 count up, timer 2 count up, except on Aspeed,
299ec14ba1eSLinus Walleij 	 * where everything just counts down.
300ec14ba1eSLinus Walleij 	 */
301ef89718aSDaniel Lezcano 	if (is_aspeed)
302ec14ba1eSLinus Walleij 		val = TIMER_2_CR_ASPEED_ENABLE;
303ec14ba1eSLinus Walleij 	else {
304ec14ba1eSLinus Walleij 		val = TIMER_2_CR_ENABLE;
305ec14ba1eSLinus Walleij 		if (!fttmr010->count_down)
306ec14ba1eSLinus Walleij 			val |= TIMER_1_CR_UPDOWN | TIMER_2_CR_UPDOWN;
307ec14ba1eSLinus Walleij 	}
308ec14ba1eSLinus Walleij 	writel(val, fttmr010->base + TIMER_CR);
309f5bf0ee4SLinus Walleij 
310f5bf0ee4SLinus Walleij 	/*
311f5bf0ee4SLinus Walleij 	 * Setup free-running clocksource timer (interrupts
312f5bf0ee4SLinus Walleij 	 * disabled.)
313f5bf0ee4SLinus Walleij 	 */
314e7bad212SLinus Walleij 	local_fttmr = fttmr010;
315b589da8bSLinus Walleij 	writel(0, fttmr010->base + TIMER2_COUNT);
316b589da8bSLinus Walleij 	writel(0, fttmr010->base + TIMER2_MATCH1);
317b589da8bSLinus Walleij 	writel(0, fttmr010->base + TIMER2_MATCH2);
318ec14ba1eSLinus Walleij 
319ec14ba1eSLinus Walleij 	if (fttmr010->count_down) {
320ec14ba1eSLinus Walleij 		writel(~0, fttmr010->base + TIMER2_LOAD);
321ec14ba1eSLinus Walleij 		clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
322ec14ba1eSLinus Walleij 				      "FTTMR010-TIMER2",
323ec14ba1eSLinus Walleij 				      fttmr010->tick_rate,
324ec14ba1eSLinus Walleij 				      300, 32, clocksource_mmio_readl_down);
325740e237aSLinus Walleij 		sched_clock_register(fttmr010_read_sched_clock_down, 32,
326740e237aSLinus Walleij 				     fttmr010->tick_rate);
327ec14ba1eSLinus Walleij 	} else {
328ec14ba1eSLinus Walleij 		writel(0, fttmr010->base + TIMER2_LOAD);
329b589da8bSLinus Walleij 		clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
330b589da8bSLinus Walleij 				      "FTTMR010-TIMER2",
331e7bad212SLinus Walleij 				      fttmr010->tick_rate,
332f5bf0ee4SLinus Walleij 				      300, 32, clocksource_mmio_readl_up);
333740e237aSLinus Walleij 		sched_clock_register(fttmr010_read_sched_clock_up, 32,
334e7bad212SLinus Walleij 				     fttmr010->tick_rate);
335740e237aSLinus Walleij 	}
336f5bf0ee4SLinus Walleij 
337f5bf0ee4SLinus Walleij 	/*
338e7bad212SLinus Walleij 	 * Setup clockevent timer (interrupt-driven) on timer 1.
339f5bf0ee4SLinus Walleij 	 */
340e7bad212SLinus Walleij 	writel(0, fttmr010->base + TIMER1_COUNT);
341e7bad212SLinus Walleij 	writel(0, fttmr010->base + TIMER1_LOAD);
342e7bad212SLinus Walleij 	writel(0, fttmr010->base + TIMER1_MATCH1);
343e7bad212SLinus Walleij 	writel(0, fttmr010->base + TIMER1_MATCH2);
344e7bad212SLinus Walleij 	ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER,
345e7bad212SLinus Walleij 			  "FTTMR010-TIMER1", &fttmr010->clkevt);
346e7bad212SLinus Walleij 	if (ret) {
347e7bad212SLinus Walleij 		pr_err("FTTMR010-TIMER1 no IRQ\n");
348e7bad212SLinus Walleij 		goto out_unmap;
349e7bad212SLinus Walleij 	}
350e7bad212SLinus Walleij 
351e7bad212SLinus Walleij 	fttmr010->clkevt.name = "FTTMR010-TIMER1";
352e7bad212SLinus Walleij 	/* Reasonably fast and accurate clock event */
353e7bad212SLinus Walleij 	fttmr010->clkevt.rating = 300;
354e7bad212SLinus Walleij 	fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
355e7bad212SLinus Walleij 		CLOCK_EVT_FEAT_ONESHOT;
356e7bad212SLinus Walleij 	fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event;
357e7bad212SLinus Walleij 	fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown;
358e7bad212SLinus Walleij 	fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic;
359e7bad212SLinus Walleij 	fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot;
360e7bad212SLinus Walleij 	fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown;
361e7bad212SLinus Walleij 	fttmr010->clkevt.cpumask = cpumask_of(0);
362e7bad212SLinus Walleij 	fttmr010->clkevt.irq = irq;
363e7bad212SLinus Walleij 	clockevents_config_and_register(&fttmr010->clkevt,
364e7bad212SLinus Walleij 					fttmr010->tick_rate,
365f5bf0ee4SLinus Walleij 					1, 0xffffffff);
366f5bf0ee4SLinus Walleij 
367385c98fcSLinus Walleij #ifdef CONFIG_ARM
368385c98fcSLinus Walleij 	/* Also use this timer for delays */
369385c98fcSLinus Walleij 	if (fttmr010->count_down)
370385c98fcSLinus Walleij 		fttmr010->delay_timer.read_current_timer =
371385c98fcSLinus Walleij 			fttmr010_read_current_timer_down;
372385c98fcSLinus Walleij 	else
373385c98fcSLinus Walleij 		fttmr010->delay_timer.read_current_timer =
374385c98fcSLinus Walleij 			fttmr010_read_current_timer_up;
375385c98fcSLinus Walleij 	fttmr010->delay_timer.freq = fttmr010->tick_rate;
376385c98fcSLinus Walleij 	register_current_timer_delay(&fttmr010->delay_timer);
377385c98fcSLinus Walleij #endif
378385c98fcSLinus Walleij 
379f5bf0ee4SLinus Walleij 	return 0;
380e7bad212SLinus Walleij 
381e7bad212SLinus Walleij out_unmap:
382e7bad212SLinus Walleij 	iounmap(fttmr010->base);
383e7bad212SLinus Walleij out_free:
384e7bad212SLinus Walleij 	kfree(fttmr010);
385e7bad212SLinus Walleij out_disable_clock:
386e7bad212SLinus Walleij 	clk_disable_unprepare(clk);
387e7bad212SLinus Walleij 
388e7bad212SLinus Walleij 	return ret;
389f5bf0ee4SLinus Walleij }
390ef89718aSDaniel Lezcano 
391ef89718aSDaniel Lezcano static __init int aspeed_timer_init(struct device_node *np)
392ef89718aSDaniel Lezcano {
393ef89718aSDaniel Lezcano 	return fttmr010_common_init(np, true);
394ef89718aSDaniel Lezcano }
395ef89718aSDaniel Lezcano 
396ef89718aSDaniel Lezcano static __init int fttmr010_timer_init(struct device_node *np)
397ef89718aSDaniel Lezcano {
398ef89718aSDaniel Lezcano 	return fttmr010_common_init(np, false);
399ef89718aSDaniel Lezcano }
400ef89718aSDaniel Lezcano 
40117273395SDaniel Lezcano TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
40217273395SDaniel Lezcano TIMER_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init);
40317273395SDaniel Lezcano TIMER_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init);
40417273395SDaniel Lezcano TIMER_OF_DECLARE(ast2400, "aspeed,ast2400-timer", aspeed_timer_init);
40517273395SDaniel Lezcano TIMER_OF_DECLARE(ast2500, "aspeed,ast2500-timer", aspeed_timer_init);
406