xref: /linux/arch/arm/mach-omap2/timer.c (revision 60e13231561b3a4c5269bfa1ef6c0569ad6f28ec)
1 /*
2  * linux/arch/arm/mach-omap2/timer.c
3  *
4  * OMAP2 GP timer support.
5  *
6  * Copyright (C) 2009 Nokia Corporation
7  *
8  * Update to use new clocksource/clockevent layers
9  * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
10  * Copyright (C) 2007 MontaVista Software, Inc.
11  *
12  * Original driver:
13  * Copyright (C) 2005 Nokia Corporation
14  * Author: Paul Mundt <paul.mundt@nokia.com>
15  *         Juha Yrjölä <juha.yrjola@nokia.com>
16  * OMAP Dual-mode timer framework support by Timo Teras
17  *
18  * Some parts based off of TI's 24xx code:
19  *
20  * Copyright (C) 2004-2009 Texas Instruments, Inc.
21  *
22  * Roughly modelled after the OMAP1 MPU timer code.
23  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
24  *
25  * This file is subject to the terms and conditions of the GNU General Public
26  * License. See the file "COPYING" in the main directory of this archive
27  * for more details.
28  */
29 #include <linux/init.h>
30 #include <linux/time.h>
31 #include <linux/interrupt.h>
32 #include <linux/err.h>
33 #include <linux/clk.h>
34 #include <linux/delay.h>
35 #include <linux/irq.h>
36 #include <linux/clocksource.h>
37 #include <linux/clockchips.h>
38 
39 #include <asm/mach/time.h>
40 #include <plat/dmtimer.h>
41 #include <asm/localtimer.h>
42 #include <asm/sched_clock.h>
43 #include <plat/common.h>
44 #include <plat/omap_hwmod.h>
45 
46 /* Parent clocks, eventually these will come from the clock framework */
47 
48 #define OMAP2_MPU_SOURCE	"sys_ck"
49 #define OMAP3_MPU_SOURCE	OMAP2_MPU_SOURCE
50 #define OMAP4_MPU_SOURCE	"sys_clkin_ck"
51 #define OMAP2_32K_SOURCE	"func_32k_ck"
52 #define OMAP3_32K_SOURCE	"omap_32k_fck"
53 #define OMAP4_32K_SOURCE	"sys_32k_ck"
54 
55 #ifdef CONFIG_OMAP_32K_TIMER
56 #define OMAP2_CLKEV_SOURCE	OMAP2_32K_SOURCE
57 #define OMAP3_CLKEV_SOURCE	OMAP3_32K_SOURCE
58 #define OMAP4_CLKEV_SOURCE	OMAP4_32K_SOURCE
59 #define OMAP3_SECURE_TIMER	12
60 #else
61 #define OMAP2_CLKEV_SOURCE	OMAP2_MPU_SOURCE
62 #define OMAP3_CLKEV_SOURCE	OMAP3_MPU_SOURCE
63 #define OMAP4_CLKEV_SOURCE	OMAP4_MPU_SOURCE
64 #define OMAP3_SECURE_TIMER	1
65 #endif
66 
67 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
68 #define MAX_GPTIMER_ID		12
69 
70 u32 sys_timer_reserved;
71 
72 /* Clockevent code */
73 
74 static struct omap_dm_timer clkev;
75 static struct clock_event_device clockevent_gpt;
76 
77 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
78 {
79 	struct clock_event_device *evt = &clockevent_gpt;
80 
81 	__omap_dm_timer_write_status(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
82 
83 	evt->event_handler(evt);
84 	return IRQ_HANDLED;
85 }
86 
87 static struct irqaction omap2_gp_timer_irq = {
88 	.name		= "gp timer",
89 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
90 	.handler	= omap2_gp_timer_interrupt,
91 };
92 
93 static int omap2_gp_timer_set_next_event(unsigned long cycles,
94 					 struct clock_event_device *evt)
95 {
96 	__omap_dm_timer_load_start(clkev.io_base, OMAP_TIMER_CTRL_ST,
97 						0xffffffff - cycles, 1);
98 
99 	return 0;
100 }
101 
102 static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
103 				    struct clock_event_device *evt)
104 {
105 	u32 period;
106 
107 	__omap_dm_timer_stop(clkev.io_base, 1, clkev.rate);
108 
109 	switch (mode) {
110 	case CLOCK_EVT_MODE_PERIODIC:
111 		period = clkev.rate / HZ;
112 		period -= 1;
113 		/* Looks like we need to first set the load value separately */
114 		__omap_dm_timer_write(clkev.io_base, OMAP_TIMER_LOAD_REG,
115 					0xffffffff - period, 1);
116 		__omap_dm_timer_load_start(clkev.io_base,
117 					OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
118 						0xffffffff - period, 1);
119 		break;
120 	case CLOCK_EVT_MODE_ONESHOT:
121 		break;
122 	case CLOCK_EVT_MODE_UNUSED:
123 	case CLOCK_EVT_MODE_SHUTDOWN:
124 	case CLOCK_EVT_MODE_RESUME:
125 		break;
126 	}
127 }
128 
129 static struct clock_event_device clockevent_gpt = {
130 	.name		= "gp timer",
131 	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
132 	.shift		= 32,
133 	.set_next_event	= omap2_gp_timer_set_next_event,
134 	.set_mode	= omap2_gp_timer_set_mode,
135 };
136 
137 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
138 						int gptimer_id,
139 						const char *fck_source)
140 {
141 	char name[10]; /* 10 = sizeof("gptXX_Xck0") */
142 	struct omap_hwmod *oh;
143 	size_t size;
144 	int res = 0;
145 
146 	sprintf(name, "timer%d", gptimer_id);
147 	omap_hwmod_setup_one(name);
148 	oh = omap_hwmod_lookup(name);
149 	if (!oh)
150 		return -ENODEV;
151 
152 	timer->irq = oh->mpu_irqs[0].irq;
153 	timer->phys_base = oh->slaves[0]->addr->pa_start;
154 	size = oh->slaves[0]->addr->pa_end - timer->phys_base;
155 
156 	/* Static mapping, never released */
157 	timer->io_base = ioremap(timer->phys_base, size);
158 	if (!timer->io_base)
159 		return -ENXIO;
160 
161 	/* After the dmtimer is using hwmod these clocks won't be needed */
162 	sprintf(name, "gpt%d_fck", gptimer_id);
163 	timer->fclk = clk_get(NULL, name);
164 	if (IS_ERR(timer->fclk))
165 		return -ENODEV;
166 
167 	sprintf(name, "gpt%d_ick", gptimer_id);
168 	timer->iclk = clk_get(NULL, name);
169 	if (IS_ERR(timer->iclk)) {
170 		clk_put(timer->fclk);
171 		return -ENODEV;
172 	}
173 
174 	omap_hwmod_enable(oh);
175 
176 	sys_timer_reserved |= (1 << (gptimer_id - 1));
177 
178 	if (gptimer_id != 12) {
179 		struct clk *src;
180 
181 		src = clk_get(NULL, fck_source);
182 		if (IS_ERR(src)) {
183 			res = -EINVAL;
184 		} else {
185 			res = __omap_dm_timer_set_source(timer->fclk, src);
186 			if (IS_ERR_VALUE(res))
187 				pr_warning("%s: timer%i cannot set source\n",
188 						__func__, gptimer_id);
189 			clk_put(src);
190 		}
191 	}
192 	__omap_dm_timer_reset(timer->io_base, 1, 1);
193 	timer->posted = 1;
194 
195 	timer->rate = clk_get_rate(timer->fclk);
196 
197 	timer->reserved = 1;
198 
199 	return res;
200 }
201 
202 static void __init omap2_gp_clockevent_init(int gptimer_id,
203 						const char *fck_source)
204 {
205 	int res;
206 
207 	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
208 	BUG_ON(res);
209 
210 	omap2_gp_timer_irq.dev_id = (void *)&clkev;
211 	setup_irq(clkev.irq, &omap2_gp_timer_irq);
212 
213 	__omap_dm_timer_int_enable(clkev.io_base, OMAP_TIMER_INT_OVERFLOW);
214 
215 	clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
216 				     clockevent_gpt.shift);
217 	clockevent_gpt.max_delta_ns =
218 		clockevent_delta2ns(0xffffffff, &clockevent_gpt);
219 	clockevent_gpt.min_delta_ns =
220 		clockevent_delta2ns(3, &clockevent_gpt);
221 		/* Timer internal resynch latency. */
222 
223 	clockevent_gpt.cpumask = cpumask_of(0);
224 	clockevents_register_device(&clockevent_gpt);
225 
226 	pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
227 		gptimer_id, clkev.rate);
228 }
229 
230 /* Clocksource code */
231 
232 #ifdef CONFIG_OMAP_32K_TIMER
233 /*
234  * When 32k-timer is enabled, don't use GPTimer for clocksource
235  * instead, just leave default clocksource which uses the 32k
236  * sync counter.  See clocksource setup in plat-omap/counter_32k.c
237  */
238 
239 static void __init omap2_gp_clocksource_init(int unused, const char *dummy)
240 {
241 	omap_init_clocksource_32k();
242 }
243 
244 #else
245 
246 static struct omap_dm_timer clksrc;
247 
248 /*
249  * clocksource
250  */
251 static DEFINE_CLOCK_DATA(cd);
252 static cycle_t clocksource_read_cycles(struct clocksource *cs)
253 {
254 	return (cycle_t)__omap_dm_timer_read_counter(clksrc.io_base, 1);
255 }
256 
257 static struct clocksource clocksource_gpt = {
258 	.name		= "gp timer",
259 	.rating		= 300,
260 	.read		= clocksource_read_cycles,
261 	.mask		= CLOCKSOURCE_MASK(32),
262 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
263 };
264 
265 static void notrace dmtimer_update_sched_clock(void)
266 {
267 	u32 cyc;
268 
269 	cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
270 
271 	update_sched_clock(&cd, cyc, (u32)~0);
272 }
273 
274 unsigned long long notrace sched_clock(void)
275 {
276 	u32 cyc = 0;
277 
278 	if (clksrc.reserved)
279 		cyc = __omap_dm_timer_read_counter(clksrc.io_base, 1);
280 
281 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
282 }
283 
284 /* Setup free-running counter for clocksource */
285 static void __init omap2_gp_clocksource_init(int gptimer_id,
286 						const char *fck_source)
287 {
288 	int res;
289 
290 	res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source);
291 	BUG_ON(res);
292 
293 	pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
294 		gptimer_id, clksrc.rate);
295 
296 	__omap_dm_timer_load_start(clksrc.io_base,
297 			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
298 	init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate);
299 
300 	if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
301 		pr_err("Could not register clocksource %s\n",
302 			clocksource_gpt.name);
303 }
304 #endif
305 
306 #define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src,			\
307 				clksrc_nr, clksrc_src)			\
308 static void __init omap##name##_timer_init(void)			\
309 {									\
310 	omap2_gp_clockevent_init((clkev_nr), clkev_src);		\
311 	omap2_gp_clocksource_init((clksrc_nr), clksrc_src);		\
312 }
313 
314 #define OMAP_SYS_TIMER(name)						\
315 struct sys_timer omap##name##_timer = {					\
316 	.init	= omap##name##_timer_init,				\
317 };
318 
319 #ifdef CONFIG_ARCH_OMAP2
320 OMAP_SYS_TIMER_INIT(2, 1, OMAP2_CLKEV_SOURCE, 2, OMAP2_MPU_SOURCE)
321 OMAP_SYS_TIMER(2)
322 #endif
323 
324 #ifdef CONFIG_ARCH_OMAP3
325 OMAP_SYS_TIMER_INIT(3, 1, OMAP3_CLKEV_SOURCE, 2, OMAP3_MPU_SOURCE)
326 OMAP_SYS_TIMER(3)
327 OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
328 			2, OMAP3_MPU_SOURCE)
329 OMAP_SYS_TIMER(3_secure)
330 #endif
331 
332 #ifdef CONFIG_ARCH_OMAP4
333 static void __init omap4_timer_init(void)
334 {
335 #ifdef CONFIG_LOCAL_TIMERS
336 	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
337 	BUG_ON(!twd_base);
338 #endif
339 	omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE);
340 	omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE);
341 }
342 OMAP_SYS_TIMER(4)
343 #endif
344