xref: /linux/drivers/clocksource/timer-sun5i.c (revision 4a59058f0b09682200c04b1db236b4a3b92128d7)
167905540SMaxime Ripard /*
267905540SMaxime Ripard  * Allwinner SoCs hstimer driver.
367905540SMaxime Ripard  *
467905540SMaxime Ripard  * Copyright (C) 2013 Maxime Ripard
567905540SMaxime Ripard  *
667905540SMaxime Ripard  * Maxime Ripard <maxime.ripard@free-electrons.com>
767905540SMaxime Ripard  *
867905540SMaxime Ripard  * This file is licensed under the terms of the GNU General Public
967905540SMaxime Ripard  * License version 2.  This program is licensed "as is" without any
1067905540SMaxime Ripard  * warranty of any kind, whether express or implied.
1167905540SMaxime Ripard  */
1267905540SMaxime Ripard 
1367905540SMaxime Ripard #include <linux/clk.h>
1467905540SMaxime Ripard #include <linux/clockchips.h>
1567905540SMaxime Ripard #include <linux/delay.h>
1667905540SMaxime Ripard #include <linux/interrupt.h>
1767905540SMaxime Ripard #include <linux/irq.h>
1867905540SMaxime Ripard #include <linux/irqreturn.h>
19e50a00beSMaxime Ripard #include <linux/reset.h>
20*4a59058fSMaxime Ripard #include <linux/slab.h>
2167905540SMaxime Ripard #include <linux/of.h>
2267905540SMaxime Ripard #include <linux/of_address.h>
2367905540SMaxime Ripard #include <linux/of_irq.h>
2467905540SMaxime Ripard 
2567905540SMaxime Ripard #define TIMER_IRQ_EN_REG		0x00
2667905540SMaxime Ripard #define TIMER_IRQ_EN(val)			BIT(val)
2767905540SMaxime Ripard #define TIMER_IRQ_ST_REG		0x04
2867905540SMaxime Ripard #define TIMER_CTL_REG(val)		(0x20 * (val) + 0x10)
2967905540SMaxime Ripard #define TIMER_CTL_ENABLE			BIT(0)
3067905540SMaxime Ripard #define TIMER_CTL_RELOAD			BIT(1)
3167905540SMaxime Ripard #define TIMER_CTL_CLK_PRES(val)			(((val) & 0x7) << 4)
3267905540SMaxime Ripard #define TIMER_CTL_ONESHOT			BIT(7)
3367905540SMaxime Ripard #define TIMER_INTVAL_LO_REG(val)	(0x20 * (val) + 0x14)
3467905540SMaxime Ripard #define TIMER_INTVAL_HI_REG(val)	(0x20 * (val) + 0x18)
3567905540SMaxime Ripard #define TIMER_CNTVAL_LO_REG(val)	(0x20 * (val) + 0x1c)
3667905540SMaxime Ripard #define TIMER_CNTVAL_HI_REG(val)	(0x20 * (val) + 0x20)
3767905540SMaxime Ripard 
3867905540SMaxime Ripard #define TIMER_SYNC_TICKS	3
3967905540SMaxime Ripard 
40*4a59058fSMaxime Ripard struct sun5i_timer {
41*4a59058fSMaxime Ripard 	void __iomem		*base;
42*4a59058fSMaxime Ripard 	struct clk		*clk;
43*4a59058fSMaxime Ripard 	u32			ticks_per_jiffy;
44*4a59058fSMaxime Ripard };
45*4a59058fSMaxime Ripard 
46*4a59058fSMaxime Ripard struct sun5i_timer_clksrc {
47*4a59058fSMaxime Ripard 	struct sun5i_timer	timer;
48*4a59058fSMaxime Ripard 	struct clocksource	clksrc;
49*4a59058fSMaxime Ripard };
50*4a59058fSMaxime Ripard 
51*4a59058fSMaxime Ripard #define to_sun5i_timer_clksrc(x) \
52*4a59058fSMaxime Ripard 	container_of(x, struct sun5i_timer_clksrc, clksrc)
53*4a59058fSMaxime Ripard 
54*4a59058fSMaxime Ripard struct sun5i_timer_clkevt {
55*4a59058fSMaxime Ripard 	struct sun5i_timer		timer;
56*4a59058fSMaxime Ripard 	struct clock_event_device	clkevt;
57*4a59058fSMaxime Ripard };
58*4a59058fSMaxime Ripard 
59*4a59058fSMaxime Ripard #define to_sun5i_timer_clkevt(x) \
60*4a59058fSMaxime Ripard 	container_of(x, struct sun5i_timer_clkevt, clkevt)
6167905540SMaxime Ripard 
6267905540SMaxime Ripard /*
6367905540SMaxime Ripard  * When we disable a timer, we need to wait at least for 2 cycles of
6467905540SMaxime Ripard  * the timer source clock. We will use for that the clocksource timer
6567905540SMaxime Ripard  * that is already setup and runs at the same frequency than the other
6667905540SMaxime Ripard  * timers, and we never will be disabled.
6767905540SMaxime Ripard  */
68*4a59058fSMaxime Ripard static void sun5i_clkevt_sync(struct sun5i_timer_clkevt *ce)
6967905540SMaxime Ripard {
70*4a59058fSMaxime Ripard 	u32 old = readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1));
7167905540SMaxime Ripard 
72*4a59058fSMaxime Ripard 	while ((old - readl(ce->timer.base + TIMER_CNTVAL_LO_REG(1))) < TIMER_SYNC_TICKS)
7367905540SMaxime Ripard 		cpu_relax();
7467905540SMaxime Ripard }
7567905540SMaxime Ripard 
76*4a59058fSMaxime Ripard static void sun5i_clkevt_time_stop(struct sun5i_timer_clkevt *ce, u8 timer)
7767905540SMaxime Ripard {
78*4a59058fSMaxime Ripard 	u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
79*4a59058fSMaxime Ripard 	writel(val & ~TIMER_CTL_ENABLE, ce->timer.base + TIMER_CTL_REG(timer));
8067905540SMaxime Ripard 
81*4a59058fSMaxime Ripard 	sun5i_clkevt_sync(ce);
8267905540SMaxime Ripard }
8367905540SMaxime Ripard 
84*4a59058fSMaxime Ripard static void sun5i_clkevt_time_setup(struct sun5i_timer_clkevt *ce, u8 timer, u32 delay)
8567905540SMaxime Ripard {
86*4a59058fSMaxime Ripard 	writel(delay, ce->timer.base + TIMER_INTVAL_LO_REG(timer));
8767905540SMaxime Ripard }
8867905540SMaxime Ripard 
89*4a59058fSMaxime Ripard static void sun5i_clkevt_time_start(struct sun5i_timer_clkevt *ce, u8 timer, bool periodic)
9067905540SMaxime Ripard {
91*4a59058fSMaxime Ripard 	u32 val = readl(ce->timer.base + TIMER_CTL_REG(timer));
9267905540SMaxime Ripard 
9367905540SMaxime Ripard 	if (periodic)
9467905540SMaxime Ripard 		val &= ~TIMER_CTL_ONESHOT;
9567905540SMaxime Ripard 	else
9667905540SMaxime Ripard 		val |= TIMER_CTL_ONESHOT;
9767905540SMaxime Ripard 
9867905540SMaxime Ripard 	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
99*4a59058fSMaxime Ripard 	       ce->timer.base + TIMER_CTL_REG(timer));
10067905540SMaxime Ripard }
10167905540SMaxime Ripard 
10267905540SMaxime Ripard static void sun5i_clkevt_mode(enum clock_event_mode mode,
103*4a59058fSMaxime Ripard 			      struct clock_event_device *clkevt)
10467905540SMaxime Ripard {
105*4a59058fSMaxime Ripard 	struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
106*4a59058fSMaxime Ripard 
10767905540SMaxime Ripard 	switch (mode) {
10867905540SMaxime Ripard 	case CLOCK_EVT_MODE_PERIODIC:
109*4a59058fSMaxime Ripard 		sun5i_clkevt_time_stop(ce, 0);
110*4a59058fSMaxime Ripard 		sun5i_clkevt_time_setup(ce, 0, ce->timer.ticks_per_jiffy);
111*4a59058fSMaxime Ripard 		sun5i_clkevt_time_start(ce, 0, true);
11267905540SMaxime Ripard 		break;
11367905540SMaxime Ripard 	case CLOCK_EVT_MODE_ONESHOT:
114*4a59058fSMaxime Ripard 		sun5i_clkevt_time_stop(ce, 0);
115*4a59058fSMaxime Ripard 		sun5i_clkevt_time_start(ce, 0, false);
11667905540SMaxime Ripard 		break;
11767905540SMaxime Ripard 	case CLOCK_EVT_MODE_UNUSED:
11867905540SMaxime Ripard 	case CLOCK_EVT_MODE_SHUTDOWN:
11967905540SMaxime Ripard 	default:
120*4a59058fSMaxime Ripard 		sun5i_clkevt_time_stop(ce, 0);
12167905540SMaxime Ripard 		break;
12267905540SMaxime Ripard 	}
12367905540SMaxime Ripard }
12467905540SMaxime Ripard 
12567905540SMaxime Ripard static int sun5i_clkevt_next_event(unsigned long evt,
126*4a59058fSMaxime Ripard 				   struct clock_event_device *clkevt)
12767905540SMaxime Ripard {
128*4a59058fSMaxime Ripard 	struct sun5i_timer_clkevt *ce = to_sun5i_timer_clkevt(clkevt);
129*4a59058fSMaxime Ripard 
130*4a59058fSMaxime Ripard 	sun5i_clkevt_time_stop(ce, 0);
131*4a59058fSMaxime Ripard 	sun5i_clkevt_time_setup(ce, 0, evt - TIMER_SYNC_TICKS);
132*4a59058fSMaxime Ripard 	sun5i_clkevt_time_start(ce, 0, false);
13367905540SMaxime Ripard 
13467905540SMaxime Ripard 	return 0;
13567905540SMaxime Ripard }
13667905540SMaxime Ripard 
13767905540SMaxime Ripard static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
13867905540SMaxime Ripard {
139*4a59058fSMaxime Ripard 	struct sun5i_timer_clkevt *ce = (struct sun5i_timer_clkevt *)dev_id;
14067905540SMaxime Ripard 
141*4a59058fSMaxime Ripard 	writel(0x1, ce->timer.base + TIMER_IRQ_ST_REG);
142*4a59058fSMaxime Ripard 	ce->clkevt.event_handler(&ce->clkevt);
14367905540SMaxime Ripard 
14467905540SMaxime Ripard 	return IRQ_HANDLED;
14567905540SMaxime Ripard }
14667905540SMaxime Ripard 
147*4a59058fSMaxime Ripard static cycle_t sun5i_clksrc_read(struct clocksource *clksrc)
148*4a59058fSMaxime Ripard {
149*4a59058fSMaxime Ripard 	struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
150*4a59058fSMaxime Ripard 
151*4a59058fSMaxime Ripard 	return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
152*4a59058fSMaxime Ripard }
153*4a59058fSMaxime Ripard 
154*4a59058fSMaxime Ripard static int __init sun5i_setup_clocksource(struct device_node *node,
155*4a59058fSMaxime Ripard 					  void __iomem *base,
156*4a59058fSMaxime Ripard 					  struct clk *clk, int irq)
157*4a59058fSMaxime Ripard {
158*4a59058fSMaxime Ripard 	struct sun5i_timer_clksrc *cs;
159*4a59058fSMaxime Ripard 	unsigned long rate;
160*4a59058fSMaxime Ripard 	int ret;
161*4a59058fSMaxime Ripard 
162*4a59058fSMaxime Ripard 	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
163*4a59058fSMaxime Ripard 	if (!cs)
164*4a59058fSMaxime Ripard 		return -ENOMEM;
165*4a59058fSMaxime Ripard 
166*4a59058fSMaxime Ripard 	ret = clk_prepare_enable(clk);
167*4a59058fSMaxime Ripard 	if (ret) {
168*4a59058fSMaxime Ripard 		pr_err("Couldn't enable parent clock\n");
169*4a59058fSMaxime Ripard 		goto err_free;
170*4a59058fSMaxime Ripard 	}
171*4a59058fSMaxime Ripard 
172*4a59058fSMaxime Ripard 	rate = clk_get_rate(clk);
173*4a59058fSMaxime Ripard 
174*4a59058fSMaxime Ripard 	cs->timer.base = base;
175*4a59058fSMaxime Ripard 	cs->timer.clk = clk;
176*4a59058fSMaxime Ripard 
177*4a59058fSMaxime Ripard 	writel(~0, base + TIMER_INTVAL_LO_REG(1));
178*4a59058fSMaxime Ripard 	writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
179*4a59058fSMaxime Ripard 	       base + TIMER_CTL_REG(1));
180*4a59058fSMaxime Ripard 
181*4a59058fSMaxime Ripard 	cs->clksrc.name = node->name;
182*4a59058fSMaxime Ripard 	cs->clksrc.rating = 340;
183*4a59058fSMaxime Ripard 	cs->clksrc.read = sun5i_clksrc_read;
184*4a59058fSMaxime Ripard 	cs->clksrc.mask = CLOCKSOURCE_MASK(32);
185*4a59058fSMaxime Ripard 	cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
186*4a59058fSMaxime Ripard 
187*4a59058fSMaxime Ripard 	ret = clocksource_register_hz(&cs->clksrc, rate);
188*4a59058fSMaxime Ripard 	if (ret) {
189*4a59058fSMaxime Ripard 		pr_err("Couldn't register clock source.\n");
190*4a59058fSMaxime Ripard 		goto err_disable_clk;
191*4a59058fSMaxime Ripard 	}
192*4a59058fSMaxime Ripard 
193*4a59058fSMaxime Ripard 	return 0;
194*4a59058fSMaxime Ripard 
195*4a59058fSMaxime Ripard err_disable_clk:
196*4a59058fSMaxime Ripard 	clk_disable_unprepare(clk);
197*4a59058fSMaxime Ripard err_free:
198*4a59058fSMaxime Ripard 	kfree(cs);
199*4a59058fSMaxime Ripard 	return ret;
200*4a59058fSMaxime Ripard }
201*4a59058fSMaxime Ripard 
202*4a59058fSMaxime Ripard static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base,
203*4a59058fSMaxime Ripard 					 struct clk *clk, int irq)
204*4a59058fSMaxime Ripard {
205*4a59058fSMaxime Ripard 	struct sun5i_timer_clkevt *ce;
206*4a59058fSMaxime Ripard 	unsigned long rate;
207*4a59058fSMaxime Ripard 	int ret;
208*4a59058fSMaxime Ripard 	u32 val;
209*4a59058fSMaxime Ripard 
210*4a59058fSMaxime Ripard 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
211*4a59058fSMaxime Ripard 	if (!ce)
212*4a59058fSMaxime Ripard 		return -ENOMEM;
213*4a59058fSMaxime Ripard 
214*4a59058fSMaxime Ripard 	ret = clk_prepare_enable(clk);
215*4a59058fSMaxime Ripard 	if (ret) {
216*4a59058fSMaxime Ripard 		pr_err("Couldn't enable parent clock\n");
217*4a59058fSMaxime Ripard 		goto err_free;
218*4a59058fSMaxime Ripard 	}
219*4a59058fSMaxime Ripard 
220*4a59058fSMaxime Ripard 	rate = clk_get_rate(clk);
221*4a59058fSMaxime Ripard 
222*4a59058fSMaxime Ripard 	ce->timer.base = base;
223*4a59058fSMaxime Ripard 	ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
224*4a59058fSMaxime Ripard 	ce->timer.clk = clk;
225*4a59058fSMaxime Ripard 
226*4a59058fSMaxime Ripard 	ce->clkevt.name = node->name;
227*4a59058fSMaxime Ripard 	ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
228*4a59058fSMaxime Ripard 	ce->clkevt.set_next_event = sun5i_clkevt_next_event;
229*4a59058fSMaxime Ripard 	ce->clkevt.set_mode = sun5i_clkevt_mode;
230*4a59058fSMaxime Ripard 	ce->clkevt.rating = 340;
231*4a59058fSMaxime Ripard 	ce->clkevt.irq = irq;
232*4a59058fSMaxime Ripard 	ce->clkevt.cpumask = cpu_possible_mask;
233*4a59058fSMaxime Ripard 
234*4a59058fSMaxime Ripard 	/* Enable timer0 interrupt */
235*4a59058fSMaxime Ripard 	val = readl(base + TIMER_IRQ_EN_REG);
236*4a59058fSMaxime Ripard 	writel(val | TIMER_IRQ_EN(0), base + TIMER_IRQ_EN_REG);
237*4a59058fSMaxime Ripard 
238*4a59058fSMaxime Ripard 	clockevents_config_and_register(&ce->clkevt, rate,
239*4a59058fSMaxime Ripard 					TIMER_SYNC_TICKS, 0xffffffff);
240*4a59058fSMaxime Ripard 
241*4a59058fSMaxime Ripard 	ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
242*4a59058fSMaxime Ripard 			  "sun5i_timer0", ce);
243*4a59058fSMaxime Ripard 	if (ret) {
244*4a59058fSMaxime Ripard 		pr_err("Unable to register interrupt\n");
245*4a59058fSMaxime Ripard 		goto err_disable_clk;
246*4a59058fSMaxime Ripard 	}
247*4a59058fSMaxime Ripard 
248*4a59058fSMaxime Ripard 	return 0;
249*4a59058fSMaxime Ripard 
250*4a59058fSMaxime Ripard err_disable_clk:
251*4a59058fSMaxime Ripard 	clk_disable_unprepare(clk);
252*4a59058fSMaxime Ripard err_free:
253*4a59058fSMaxime Ripard 	kfree(ce);
254*4a59058fSMaxime Ripard 	return ret;
255*4a59058fSMaxime Ripard }
256*4a59058fSMaxime Ripard 
25767905540SMaxime Ripard static void __init sun5i_timer_init(struct device_node *node)
25867905540SMaxime Ripard {
259e50a00beSMaxime Ripard 	struct reset_control *rstc;
260*4a59058fSMaxime Ripard 	void __iomem *timer_base;
26167905540SMaxime Ripard 	struct clk *clk;
262*4a59058fSMaxime Ripard 	int irq;
26367905540SMaxime Ripard 
264a45860d0SMaxime Ripard 	timer_base = of_io_request_and_map(node, 0, of_node_full_name(node));
26567905540SMaxime Ripard 	if (!timer_base)
26667905540SMaxime Ripard 		panic("Can't map registers");
26767905540SMaxime Ripard 
26867905540SMaxime Ripard 	irq = irq_of_parse_and_map(node, 0);
26967905540SMaxime Ripard 	if (irq <= 0)
27067905540SMaxime Ripard 		panic("Can't parse IRQ");
27167905540SMaxime Ripard 
27267905540SMaxime Ripard 	clk = of_clk_get(node, 0);
27367905540SMaxime Ripard 	if (IS_ERR(clk))
27467905540SMaxime Ripard 		panic("Can't get timer clock");
27567905540SMaxime Ripard 
276e50a00beSMaxime Ripard 	rstc = of_reset_control_get(node, NULL);
277e50a00beSMaxime Ripard 	if (!IS_ERR(rstc))
278e50a00beSMaxime Ripard 		reset_control_deassert(rstc);
279e50a00beSMaxime Ripard 
280*4a59058fSMaxime Ripard 	sun5i_setup_clocksource(node, timer_base, clk, irq);
281*4a59058fSMaxime Ripard 	sun5i_setup_clockevent(node, timer_base, clk, irq);
28267905540SMaxime Ripard }
28367905540SMaxime Ripard CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
28467905540SMaxime Ripard 		       sun5i_timer_init);
28567905540SMaxime Ripard CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
28667905540SMaxime Ripard 		       sun5i_timer_init);
287