• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * linux/arch/arm/plat-omap/dmtimer.c
3  *
4  * OMAP Dual-Mode Timers
5  *
6  * Copyright (C) 2005 Nokia Corporation
7  * OMAP2 support by Juha Yrjola
8  * API improvements and OMAP2 clock framework support by Timo Teras
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
18  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * You should have received a copy of the  GNU General Public License along
25  * with this program; if not, write  to the Free Software Foundation, Inc.,
26  * 675 Mass Ave, Cambridge, MA 02139, USA.
27  */
28 
29 #include <linux/init.h>
30 #include <linux/spinlock.h>
31 #include <linux/errno.h>
32 #include <linux/list.h>
33 #include <linux/clk.h>
34 #include <linux/delay.h>
35 #include <linux/io.h>
36 #include <mach/hardware.h>
37 #include <mach/dmtimer.h>
38 #include <mach/irqs.h>
39 
40 /* register offsets */
41 #define _OMAP_TIMER_ID_OFFSET		0x00
42 #define _OMAP_TIMER_OCP_CFG_OFFSET	0x10
43 #define _OMAP_TIMER_SYS_STAT_OFFSET	0x14
44 #define _OMAP_TIMER_STAT_OFFSET		0x18
45 #define _OMAP_TIMER_INT_EN_OFFSET	0x1c
46 #define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
47 #define _OMAP_TIMER_CTRL_OFFSET		0x24
48 #define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
49 #define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
50 #define		OMAP_TIMER_CTRL_PT		(1 << 12)
51 #define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
52 #define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
53 #define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
54 #define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
55 #define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
56 #define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
57 #define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
58 #define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
59 #define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
60 #define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
61 #define _OMAP_TIMER_COUNTER_OFFSET	0x28
62 #define _OMAP_TIMER_LOAD_OFFSET		0x2c
63 #define _OMAP_TIMER_TRIGGER_OFFSET	0x30
64 #define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
65 #define		WP_NONE			0	/* no write pending bit */
66 #define		WP_TCLR			(1 << 0)
67 #define		WP_TCRR			(1 << 1)
68 #define		WP_TLDR			(1 << 2)
69 #define		WP_TTGR			(1 << 3)
70 #define		WP_TMAR			(1 << 4)
71 #define		WP_TPIR			(1 << 5)
72 #define		WP_TNIR			(1 << 6)
73 #define		WP_TCVR			(1 << 7)
74 #define		WP_TOCR			(1 << 8)
75 #define		WP_TOWR			(1 << 9)
76 #define _OMAP_TIMER_MATCH_OFFSET	0x38
77 #define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
78 #define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
79 #define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
80 #define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
81 #define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
82 #define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
83 #define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
84 #define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
85 
86 /* register offsets with the write pending bit encoded */
87 #define	WPSHIFT					16
88 
89 #define OMAP_TIMER_ID_REG			(_OMAP_TIMER_ID_OFFSET \
90 							| (WP_NONE << WPSHIFT))
91 
92 #define OMAP_TIMER_OCP_CFG_REG			(_OMAP_TIMER_OCP_CFG_OFFSET \
93 							| (WP_NONE << WPSHIFT))
94 
95 #define OMAP_TIMER_SYS_STAT_REG			(_OMAP_TIMER_SYS_STAT_OFFSET \
96 							| (WP_NONE << WPSHIFT))
97 
98 #define OMAP_TIMER_STAT_REG			(_OMAP_TIMER_STAT_OFFSET \
99 							| (WP_NONE << WPSHIFT))
100 
101 #define OMAP_TIMER_INT_EN_REG			(_OMAP_TIMER_INT_EN_OFFSET \
102 							| (WP_NONE << WPSHIFT))
103 
104 #define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
105 							| (WP_NONE << WPSHIFT))
106 
107 #define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
108 							| (WP_TCLR << WPSHIFT))
109 
110 #define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
111 							| (WP_TCRR << WPSHIFT))
112 
113 #define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
114 							| (WP_TLDR << WPSHIFT))
115 
116 #define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
117 							| (WP_TTGR << WPSHIFT))
118 
119 #define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
120 							| (WP_NONE << WPSHIFT))
121 
122 #define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
123 							| (WP_TMAR << WPSHIFT))
124 
125 #define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
126 							| (WP_NONE << WPSHIFT))
127 
128 #define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
129 							| (WP_NONE << WPSHIFT))
130 
131 #define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
132 							| (WP_NONE << WPSHIFT))
133 
134 #define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
135 							| (WP_TPIR << WPSHIFT))
136 
137 #define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
138 							| (WP_TNIR << WPSHIFT))
139 
140 #define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
141 							| (WP_TCVR << WPSHIFT))
142 
143 #define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
144 		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
145 
146 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
147 		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
148 
149 struct omap_dm_timer {
150 	unsigned long phys_base;
151 	int irq;
152 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
153 	struct clk *iclk, *fclk;
154 #endif
155 	void __iomem *io_base;
156 	unsigned reserved:1;
157 	unsigned enabled:1;
158 	unsigned posted:1;
159 };
160 
161 #ifdef CONFIG_ARCH_OMAP1
162 
163 #define omap_dm_clk_enable(x)
164 #define omap_dm_clk_disable(x)
165 #define omap2_dm_timers			NULL
166 #define omap2_dm_source_names		NULL
167 #define omap2_dm_source_clocks		NULL
168 #define omap3_dm_timers			NULL
169 #define omap3_dm_source_names		NULL
170 #define omap3_dm_source_clocks		NULL
171 
172 static struct omap_dm_timer omap1_dm_timers[] = {
173 	{ .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 },
174 	{ .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 },
175 	{ .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 },
176 	{ .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 },
177 	{ .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 },
178 	{ .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 },
179 	{ .phys_base = 0xfffb7400, .irq = INT_1610_GPTIMER7 },
180 	{ .phys_base = 0xfffbd400, .irq = INT_1610_GPTIMER8 },
181 };
182 
183 static const int dm_timer_count = ARRAY_SIZE(omap1_dm_timers);
184 
185 #elif defined(CONFIG_ARCH_OMAP2)
186 
187 #define omap_dm_clk_enable(x)		clk_enable(x)
188 #define omap_dm_clk_disable(x)		clk_disable(x)
189 #define omap1_dm_timers			NULL
190 #define omap3_dm_timers			NULL
191 #define omap3_dm_source_names		NULL
192 #define omap3_dm_source_clocks		NULL
193 
194 static struct omap_dm_timer omap2_dm_timers[] = {
195 	{ .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 },
196 	{ .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 },
197 	{ .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 },
198 	{ .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 },
199 	{ .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 },
200 	{ .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 },
201 	{ .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 },
202 	{ .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 },
203 	{ .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 },
204 	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
205 	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
206 	{ .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 },
207 };
208 
209 static const char *omap2_dm_source_names[] __initdata = {
210 	"sys_ck",
211 	"func_32k_ck",
212 	"alt_ck",
213 	NULL
214 };
215 
216 static struct clk **omap2_dm_source_clocks[3];
217 static const int dm_timer_count = ARRAY_SIZE(omap2_dm_timers);
218 
219 #elif defined(CONFIG_ARCH_OMAP3)
220 
221 #define omap_dm_clk_enable(x)		clk_enable(x)
222 #define omap_dm_clk_disable(x)		clk_disable(x)
223 #define omap1_dm_timers			NULL
224 #define omap2_dm_timers			NULL
225 #define omap2_dm_source_names		NULL
226 #define omap2_dm_source_clocks		NULL
227 
228 static struct omap_dm_timer omap3_dm_timers[] = {
229 	{ .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 },
230 	{ .phys_base = 0x49032000, .irq = INT_24XX_GPTIMER2 },
231 	{ .phys_base = 0x49034000, .irq = INT_24XX_GPTIMER3 },
232 	{ .phys_base = 0x49036000, .irq = INT_24XX_GPTIMER4 },
233 	{ .phys_base = 0x49038000, .irq = INT_24XX_GPTIMER5 },
234 	{ .phys_base = 0x4903A000, .irq = INT_24XX_GPTIMER6 },
235 	{ .phys_base = 0x4903C000, .irq = INT_24XX_GPTIMER7 },
236 	{ .phys_base = 0x4903E000, .irq = INT_24XX_GPTIMER8 },
237 	{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
238 	{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
239 	{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
240 	{ .phys_base = 0x48304000, .irq = INT_24XX_GPTIMER12 },
241 };
242 
243 static const char *omap3_dm_source_names[] __initdata = {
244 	"sys_ck",
245 	"omap_32k_fck",
246 	NULL
247 };
248 
249 static struct clk **omap3_dm_source_clocks[2];
250 static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers);
251 
252 #else
253 
254 #error OMAP architecture not supported!
255 
256 #endif
257 
258 static struct omap_dm_timer *dm_timers;
259 static char **dm_source_names;
260 static struct clk **dm_source_clocks;
261 
262 static spinlock_t dm_timer_lock;
263 
264 /*
265  * Reads timer registers in posted and non-posted mode. The posted mode bit
266  * is encoded in reg. Note that in posted mode write pending bit must be
267  * checked. Otherwise a read of a non completed write will produce an error.
268  */
omap_dm_timer_read_reg(struct omap_dm_timer * timer,u32 reg)269 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
270 {
271 	if (timer->posted)
272 		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
273 				& (reg >> WPSHIFT))
274 			cpu_relax();
275 	return readl(timer->io_base + (reg & 0xff));
276 }
277 
278 /*
279  * Writes timer registers in posted and non-posted mode. The posted mode bit
280  * is encoded in reg. Note that in posted mode the write pending bit must be
281  * checked. Otherwise a write on a register which has a pending write will be
282  * lost.
283  */
omap_dm_timer_write_reg(struct omap_dm_timer * timer,u32 reg,u32 value)284 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
285 						u32 value)
286 {
287 	if (timer->posted)
288 		while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
289 				& (reg >> WPSHIFT))
290 			cpu_relax();
291 	writel(value, timer->io_base + (reg & 0xff));
292 }
293 
omap_dm_timer_wait_for_reset(struct omap_dm_timer * timer)294 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
295 {
296 	int c;
297 
298 	c = 0;
299 	while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) {
300 		c++;
301 		if (c > 100000) {
302 			printk(KERN_ERR "Timer failed to reset\n");
303 			return;
304 		}
305 	}
306 }
307 
omap_dm_timer_reset(struct omap_dm_timer * timer)308 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
309 {
310 	u32 l;
311 
312 	if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
313 		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
314 		omap_dm_timer_wait_for_reset(timer);
315 	}
316 	omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
317 
318 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
319 	l |= 0x02 << 3;  /* Set to smart-idle mode */
320 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
321 
322 	/*
323 	 * Enable wake-up only for GPT1 on OMAP2 CPUs.
324 	 * FIXME: All timers should have wake-up enabled and clear
325 	 * PRCM status.
326 	 */
327 	if (cpu_class_is_omap2() && (timer == &dm_timers[0]))
328 		l |= 1 << 2;
329 	omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
330 
331 	/* Match hardware reset default of posted mode */
332 	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
333 			OMAP_TIMER_CTRL_POSTED);
334 	timer->posted = 1;
335 }
336 
omap_dm_timer_prepare(struct omap_dm_timer * timer)337 static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
338 {
339 	omap_dm_timer_enable(timer);
340 	omap_dm_timer_reset(timer);
341 }
342 
omap_dm_timer_request(void)343 struct omap_dm_timer *omap_dm_timer_request(void)
344 {
345 	struct omap_dm_timer *timer = NULL;
346 	unsigned long flags;
347 	int i;
348 
349 	spin_lock_irqsave(&dm_timer_lock, flags);
350 	for (i = 0; i < dm_timer_count; i++) {
351 		if (dm_timers[i].reserved)
352 			continue;
353 
354 		timer = &dm_timers[i];
355 		timer->reserved = 1;
356 		break;
357 	}
358 	spin_unlock_irqrestore(&dm_timer_lock, flags);
359 
360 	if (timer != NULL)
361 		omap_dm_timer_prepare(timer);
362 
363 	return timer;
364 }
365 
omap_dm_timer_request_specific(int id)366 struct omap_dm_timer *omap_dm_timer_request_specific(int id)
367 {
368 	struct omap_dm_timer *timer;
369 	unsigned long flags;
370 
371 	spin_lock_irqsave(&dm_timer_lock, flags);
372 	if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) {
373 		spin_unlock_irqrestore(&dm_timer_lock, flags);
374 		printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n",
375 		       __FILE__, __LINE__, __func__, id);
376 		dump_stack();
377 		return NULL;
378 	}
379 
380 	timer = &dm_timers[id-1];
381 	timer->reserved = 1;
382 	spin_unlock_irqrestore(&dm_timer_lock, flags);
383 
384 	omap_dm_timer_prepare(timer);
385 
386 	return timer;
387 }
388 
omap_dm_timer_free(struct omap_dm_timer * timer)389 void omap_dm_timer_free(struct omap_dm_timer *timer)
390 {
391 	omap_dm_timer_enable(timer);
392 	omap_dm_timer_reset(timer);
393 	omap_dm_timer_disable(timer);
394 
395 	WARN_ON(!timer->reserved);
396 	timer->reserved = 0;
397 }
398 
omap_dm_timer_enable(struct omap_dm_timer * timer)399 void omap_dm_timer_enable(struct omap_dm_timer *timer)
400 {
401 	if (timer->enabled)
402 		return;
403 
404 	omap_dm_clk_enable(timer->fclk);
405 	omap_dm_clk_enable(timer->iclk);
406 
407 	timer->enabled = 1;
408 }
409 
omap_dm_timer_disable(struct omap_dm_timer * timer)410 void omap_dm_timer_disable(struct omap_dm_timer *timer)
411 {
412 	if (!timer->enabled)
413 		return;
414 
415 	omap_dm_clk_disable(timer->iclk);
416 	omap_dm_clk_disable(timer->fclk);
417 
418 	timer->enabled = 0;
419 }
420 
omap_dm_timer_get_irq(struct omap_dm_timer * timer)421 int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
422 {
423 	return timer->irq;
424 }
425 
426 #if defined(CONFIG_ARCH_OMAP1)
427 
428 /**
429  * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
430  * @inputmask: current value of idlect mask
431  */
omap_dm_timer_modify_idlect_mask(__u32 inputmask)432 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
433 {
434 	int i;
435 
436 	/* If ARMXOR cannot be idled this function call is unnecessary */
437 	if (!(inputmask & (1 << 1)))
438 		return inputmask;
439 
440 	/* If any active timer is using ARMXOR return modified mask */
441 	for (i = 0; i < dm_timer_count; i++) {
442 		u32 l;
443 
444 		l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG);
445 		if (l & OMAP_TIMER_CTRL_ST) {
446 			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
447 				inputmask &= ~(1 << 1);
448 			else
449 				inputmask &= ~(1 << 2);
450 		}
451 	}
452 
453 	return inputmask;
454 }
455 
456 #elif defined(CONFIG_ARCH_OMAP2) || defined (CONFIG_ARCH_OMAP3)
457 
omap_dm_timer_get_fclk(struct omap_dm_timer * timer)458 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
459 {
460 	return timer->fclk;
461 }
462 
omap_dm_timer_modify_idlect_mask(__u32 inputmask)463 __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
464 {
465 	BUG();
466 
467 	return 0;
468 }
469 
470 #endif
471 
omap_dm_timer_trigger(struct omap_dm_timer * timer)472 void omap_dm_timer_trigger(struct omap_dm_timer *timer)
473 {
474 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
475 }
476 
omap_dm_timer_start(struct omap_dm_timer * timer)477 void omap_dm_timer_start(struct omap_dm_timer *timer)
478 {
479 	u32 l;
480 
481 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
482 	if (!(l & OMAP_TIMER_CTRL_ST)) {
483 		l |= OMAP_TIMER_CTRL_ST;
484 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
485 	}
486 }
487 
omap_dm_timer_stop(struct omap_dm_timer * timer)488 void omap_dm_timer_stop(struct omap_dm_timer *timer)
489 {
490 	u32 l;
491 
492 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
493 	if (l & OMAP_TIMER_CTRL_ST) {
494 		l &= ~0x1;
495 		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
496 	}
497 }
498 
499 #ifdef CONFIG_ARCH_OMAP1
500 
omap_dm_timer_set_source(struct omap_dm_timer * timer,int source)501 void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
502 {
503 	int n = (timer - dm_timers) << 1;
504 	u32 l;
505 
506 	l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
507 	l |= source << n;
508 	omap_writel(l, MOD_CONF_CTRL_1);
509 }
510 
511 #else
512 
omap_dm_timer_set_source(struct omap_dm_timer * timer,int source)513 void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
514 {
515 	if (source < 0 || source >= 3)
516 		return;
517 
518 	clk_disable(timer->fclk);
519 	clk_set_parent(timer->fclk, dm_source_clocks[source]);
520 	clk_enable(timer->fclk);
521 
522 	/* When the functional clock disappears, too quick writes seem to
523 	 * cause an abort. */
524 	__delay(150000);
525 }
526 
527 #endif
528 
omap_dm_timer_set_load(struct omap_dm_timer * timer,int autoreload,unsigned int load)529 void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
530 			    unsigned int load)
531 {
532 	u32 l;
533 
534 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
535 	if (autoreload)
536 		l |= OMAP_TIMER_CTRL_AR;
537 	else
538 		l &= ~OMAP_TIMER_CTRL_AR;
539 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
540 	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
541 
542 	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
543 }
544 
545 /* Optimized set_load which removes costly spin wait in timer_start */
omap_dm_timer_set_load_start(struct omap_dm_timer * timer,int autoreload,unsigned int load)546 void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
547                             unsigned int load)
548 {
549 	u32 l;
550 
551 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
552 	if (autoreload) {
553 		l |= OMAP_TIMER_CTRL_AR;
554 		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
555 	} else {
556 		l &= ~OMAP_TIMER_CTRL_AR;
557 	}
558 	l |= OMAP_TIMER_CTRL_ST;
559 
560 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
561 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
562 }
563 
omap_dm_timer_set_match(struct omap_dm_timer * timer,int enable,unsigned int match)564 void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
565 			     unsigned int match)
566 {
567 	u32 l;
568 
569 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
570 	if (enable)
571 		l |= OMAP_TIMER_CTRL_CE;
572 	else
573 		l &= ~OMAP_TIMER_CTRL_CE;
574 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
575 	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
576 }
577 
omap_dm_timer_set_pwm(struct omap_dm_timer * timer,int def_on,int toggle,int trigger)578 void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
579 			   int toggle, int trigger)
580 {
581 	u32 l;
582 
583 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
584 	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
585 	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
586 	if (def_on)
587 		l |= OMAP_TIMER_CTRL_SCPWM;
588 	if (toggle)
589 		l |= OMAP_TIMER_CTRL_PT;
590 	l |= trigger << 10;
591 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
592 }
593 
omap_dm_timer_set_prescaler(struct omap_dm_timer * timer,int prescaler)594 void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
595 {
596 	u32 l;
597 
598 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
599 	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
600 	if (prescaler >= 0x00 && prescaler <= 0x07) {
601 		l |= OMAP_TIMER_CTRL_PRE;
602 		l |= prescaler << 2;
603 	}
604 	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
605 }
606 
omap_dm_timer_set_int_enable(struct omap_dm_timer * timer,unsigned int value)607 void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
608 				  unsigned int value)
609 {
610 	omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
611 	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
612 }
613 
omap_dm_timer_read_status(struct omap_dm_timer * timer)614 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
615 {
616 	unsigned int l;
617 
618 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG);
619 
620 	return l;
621 }
622 
omap_dm_timer_write_status(struct omap_dm_timer * timer,unsigned int value)623 void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
624 {
625 	omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
626 }
627 
omap_dm_timer_read_counter(struct omap_dm_timer * timer)628 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
629 {
630 	unsigned int l;
631 
632 	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
633 
634 	return l;
635 }
636 
omap_dm_timer_write_counter(struct omap_dm_timer * timer,unsigned int value)637 void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
638 {
639 	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
640 }
641 
omap_dm_timers_active(void)642 int omap_dm_timers_active(void)
643 {
644 	int i;
645 
646 	for (i = 0; i < dm_timer_count; i++) {
647 		struct omap_dm_timer *timer;
648 
649 		timer = &dm_timers[i];
650 
651 		if (!timer->enabled)
652 			continue;
653 
654 		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
655 		    OMAP_TIMER_CTRL_ST) {
656 			return 1;
657 		}
658 	}
659 	return 0;
660 }
661 
omap_dm_timer_init(void)662 int __init omap_dm_timer_init(void)
663 {
664 	struct omap_dm_timer *timer;
665 	int i;
666 
667 	if (!(cpu_is_omap16xx() || cpu_class_is_omap2()))
668 		return -ENODEV;
669 
670 	spin_lock_init(&dm_timer_lock);
671 
672 	if (cpu_class_is_omap1())
673 		dm_timers = omap1_dm_timers;
674 	else if (cpu_is_omap24xx()) {
675 		dm_timers = omap2_dm_timers;
676 		dm_source_names = (char **)omap2_dm_source_names;
677 		dm_source_clocks = (struct clk **)omap2_dm_source_clocks;
678 	} else if (cpu_is_omap34xx()) {
679 		dm_timers = omap3_dm_timers;
680 		dm_source_names = (char **)omap3_dm_source_names;
681 		dm_source_clocks = (struct clk **)omap3_dm_source_clocks;
682 	}
683 
684 	if (cpu_class_is_omap2())
685 		for (i = 0; dm_source_names[i] != NULL; i++)
686 			dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);
687 
688 	if (cpu_is_omap243x())
689 		dm_timers[0].phys_base = 0x49018000;
690 
691 	for (i = 0; i < dm_timer_count; i++) {
692 		timer = &dm_timers[i];
693 		timer->io_base = IO_ADDRESS(timer->phys_base);
694 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
695 		if (cpu_class_is_omap2()) {
696 			char clk_name[16];
697 			sprintf(clk_name, "gpt%d_ick", i + 1);
698 			timer->iclk = clk_get(NULL, clk_name);
699 			sprintf(clk_name, "gpt%d_fck", i + 1);
700 			timer->fclk = clk_get(NULL, clk_name);
701 		}
702 #endif
703 	}
704 
705 	return 0;
706 }
707