• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * arch/arm/plat-omap/include/plat/dmtimer.h
3  *
4  * OMAP Dual-Mode Timers
5  *
6  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
7  * Tarun Kanti DebBarma <tarun.kanti@ti.com>
8  * Thara Gopinath <thara@ti.com>
9  *
10  * Platform device conversion and hwmod support.
11  *
12  * Copyright (C) 2005 Nokia Corporation
13  * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
14  * PWM and clock framwork support by Timo Teras.
15  *
16  * This program is free software; you can redistribute it and/or modify it
17  * under the terms of the GNU General Public License as published by the
18  * Free Software Foundation; either version 2 of the License, or (at your
19  * option) any later version.
20  *
21  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
24  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * You should have received a copy of the  GNU General Public License along
31  * with this program; if not, write  to the Free Software Foundation, Inc.,
32  * 675 Mass Ave, Cambridge, MA 02139, USA.
33  */
34 
35 #include <linux/delay.h>
36 #include <linux/io.h>
37 #include <linux/platform_device.h>
38 
39 #ifndef __ASM_ARCH_DMTIMER_H
40 #define __ASM_ARCH_DMTIMER_H
41 
42 /* clock sources */
43 #define OMAP_TIMER_SRC_SYS_CLK			0x00
44 #define OMAP_TIMER_SRC_32_KHZ			0x01
45 #define OMAP_TIMER_SRC_EXT_CLK			0x02
46 
47 /* timer interrupt enable bits */
48 #define OMAP_TIMER_INT_CAPTURE			(1 << 2)
49 #define OMAP_TIMER_INT_OVERFLOW			(1 << 1)
50 #define OMAP_TIMER_INT_MATCH			(1 << 0)
51 
52 /* trigger types */
53 #define OMAP_TIMER_TRIGGER_NONE			0x00
54 #define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
55 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
56 
57 /* posted mode types */
58 #define OMAP_TIMER_NONPOSTED			0x00
59 #define OMAP_TIMER_POSTED			0x01
60 
61 /* timer capabilities used in hwmod database */
62 #define OMAP_TIMER_SECURE				0x80000000
63 #define OMAP_TIMER_ALWON				0x40000000
64 #define OMAP_TIMER_HAS_PWM				0x20000000
65 #define OMAP_TIMER_NEEDS_RESET				0x10000000
66 #define OMAP_TIMER_HAS_DSP_IRQ				0x08000000
67 
68 /*
69  * timer errata flags
70  *
71  * Errata i103/i767 impacts all OMAP3/4/5 devices including AM33xx. This
72  * errata prevents us from using posted mode on these devices, unless the
73  * timer counter register is never read. For more details please refer to
74  * the OMAP3/4/5 errata documents.
75  */
76 #define OMAP_TIMER_ERRATA_I103_I767			0x80000000
77 
78 struct omap_timer_capability_dev_attr {
79 	u32 timer_capability;
80 };
81 
82 struct timer_regs {
83 	u32 tidr;
84 	u32 tier;
85 	u32 twer;
86 	u32 tclr;
87 	u32 tcrr;
88 	u32 tldr;
89 	u32 ttrg;
90 	u32 twps;
91 	u32 tmar;
92 	u32 tcar1;
93 	u32 tsicr;
94 	u32 tcar2;
95 	u32 tpir;
96 	u32 tnir;
97 	u32 tcvr;
98 	u32 tocr;
99 	u32 towr;
100 };
101 
102 struct omap_dm_timer {
103 	int id;
104 	int irq;
105 	struct clk *fclk;
106 
107 	void __iomem	*io_base;
108 	void __iomem	*irq_stat;	/* TISR/IRQSTATUS interrupt status */
109 	void __iomem	*irq_ena;	/* irq enable */
110 	void __iomem	*irq_dis;	/* irq disable, only on v2 ip */
111 	void __iomem	*pend;		/* write pending */
112 	void __iomem	*func_base;	/* function register base */
113 
114 	unsigned long rate;
115 	unsigned reserved:1;
116 	unsigned posted:1;
117 	struct timer_regs context;
118 	int (*get_context_loss_count)(struct device *);
119 	int ctx_loss_count;
120 	int revision;
121 	u32 capability;
122 	u32 errata;
123 	struct platform_device *pdev;
124 	struct list_head node;
125 };
126 
127 int omap_dm_timer_reserve_systimer(int id);
128 struct omap_dm_timer *omap_dm_timer_request(void);
129 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
130 struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap);
131 struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np);
132 int omap_dm_timer_free(struct omap_dm_timer *timer);
133 void omap_dm_timer_enable(struct omap_dm_timer *timer);
134 void omap_dm_timer_disable(struct omap_dm_timer *timer);
135 
136 int omap_dm_timer_get_irq(struct omap_dm_timer *timer);
137 
138 u32 omap_dm_timer_modify_idlect_mask(u32 inputmask);
139 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer);
140 
141 int omap_dm_timer_trigger(struct omap_dm_timer *timer);
142 int omap_dm_timer_start(struct omap_dm_timer *timer);
143 int omap_dm_timer_stop(struct omap_dm_timer *timer);
144 
145 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
146 int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
147 int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
148 int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
149 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger);
150 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler);
151 
152 int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value);
153 int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask);
154 
155 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer);
156 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value);
157 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer);
158 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value);
159 
160 int omap_dm_timers_active(void);
161 
162 /*
163  * Do not use the defines below, they are not needed. They should be only
164  * used by dmtimer.c and sys_timer related code.
165  */
166 
167 /*
168  * The interrupt registers are different between v1 and v2 ip.
169  * These registers are offsets from timer->iobase.
170  */
171 #define OMAP_TIMER_ID_OFFSET		0x00
172 #define OMAP_TIMER_OCP_CFG_OFFSET	0x10
173 
174 #define OMAP_TIMER_V1_SYS_STAT_OFFSET	0x14
175 #define OMAP_TIMER_V1_STAT_OFFSET	0x18
176 #define OMAP_TIMER_V1_INT_EN_OFFSET	0x1c
177 
178 #define OMAP_TIMER_V2_IRQSTATUS_RAW	0x24
179 #define OMAP_TIMER_V2_IRQSTATUS		0x28
180 #define OMAP_TIMER_V2_IRQENABLE_SET	0x2c
181 #define OMAP_TIMER_V2_IRQENABLE_CLR	0x30
182 
183 /*
184  * The functional registers have a different base on v1 and v2 ip.
185  * These registers are offsets from timer->func_base. The func_base
186  * is samae as io_base for v1 and io_base + 0x14 for v2 ip.
187  *
188  */
189 #define OMAP_TIMER_V2_FUNC_OFFSET		0x14
190 
191 #define _OMAP_TIMER_WAKEUP_EN_OFFSET	0x20
192 #define _OMAP_TIMER_CTRL_OFFSET		0x24
193 #define		OMAP_TIMER_CTRL_GPOCFG		(1 << 14)
194 #define		OMAP_TIMER_CTRL_CAPTMODE	(1 << 13)
195 #define		OMAP_TIMER_CTRL_PT		(1 << 12)
196 #define		OMAP_TIMER_CTRL_TCM_LOWTOHIGH	(0x1 << 8)
197 #define		OMAP_TIMER_CTRL_TCM_HIGHTOLOW	(0x2 << 8)
198 #define		OMAP_TIMER_CTRL_TCM_BOTHEDGES	(0x3 << 8)
199 #define		OMAP_TIMER_CTRL_SCPWM		(1 << 7)
200 #define		OMAP_TIMER_CTRL_CE		(1 << 6) /* compare enable */
201 #define		OMAP_TIMER_CTRL_PRE		(1 << 5) /* prescaler enable */
202 #define		OMAP_TIMER_CTRL_PTV_SHIFT	2 /* prescaler value shift */
203 #define		OMAP_TIMER_CTRL_POSTED		(1 << 2)
204 #define		OMAP_TIMER_CTRL_AR		(1 << 1) /* auto-reload enable */
205 #define		OMAP_TIMER_CTRL_ST		(1 << 0) /* start timer */
206 #define _OMAP_TIMER_COUNTER_OFFSET	0x28
207 #define _OMAP_TIMER_LOAD_OFFSET		0x2c
208 #define _OMAP_TIMER_TRIGGER_OFFSET	0x30
209 #define _OMAP_TIMER_WRITE_PEND_OFFSET	0x34
210 #define		WP_NONE			0	/* no write pending bit */
211 #define		WP_TCLR			(1 << 0)
212 #define		WP_TCRR			(1 << 1)
213 #define		WP_TLDR			(1 << 2)
214 #define		WP_TTGR			(1 << 3)
215 #define		WP_TMAR			(1 << 4)
216 #define		WP_TPIR			(1 << 5)
217 #define		WP_TNIR			(1 << 6)
218 #define		WP_TCVR			(1 << 7)
219 #define		WP_TOCR			(1 << 8)
220 #define		WP_TOWR			(1 << 9)
221 #define _OMAP_TIMER_MATCH_OFFSET	0x38
222 #define _OMAP_TIMER_CAPTURE_OFFSET	0x3c
223 #define _OMAP_TIMER_IF_CTRL_OFFSET	0x40
224 #define _OMAP_TIMER_CAPTURE2_OFFSET		0x44	/* TCAR2, 34xx only */
225 #define _OMAP_TIMER_TICK_POS_OFFSET		0x48	/* TPIR, 34xx only */
226 #define _OMAP_TIMER_TICK_NEG_OFFSET		0x4c	/* TNIR, 34xx only */
227 #define _OMAP_TIMER_TICK_COUNT_OFFSET		0x50	/* TCVR, 34xx only */
228 #define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET	0x54	/* TOCR, 34xx only */
229 #define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET	0x58	/* TOWR, 34xx only */
230 
231 /* register offsets with the write pending bit encoded */
232 #define	WPSHIFT					16
233 
234 #define OMAP_TIMER_WAKEUP_EN_REG		(_OMAP_TIMER_WAKEUP_EN_OFFSET \
235 							| (WP_NONE << WPSHIFT))
236 
237 #define OMAP_TIMER_CTRL_REG			(_OMAP_TIMER_CTRL_OFFSET \
238 							| (WP_TCLR << WPSHIFT))
239 
240 #define OMAP_TIMER_COUNTER_REG			(_OMAP_TIMER_COUNTER_OFFSET \
241 							| (WP_TCRR << WPSHIFT))
242 
243 #define OMAP_TIMER_LOAD_REG			(_OMAP_TIMER_LOAD_OFFSET \
244 							| (WP_TLDR << WPSHIFT))
245 
246 #define OMAP_TIMER_TRIGGER_REG			(_OMAP_TIMER_TRIGGER_OFFSET \
247 							| (WP_TTGR << WPSHIFT))
248 
249 #define OMAP_TIMER_WRITE_PEND_REG		(_OMAP_TIMER_WRITE_PEND_OFFSET \
250 							| (WP_NONE << WPSHIFT))
251 
252 #define OMAP_TIMER_MATCH_REG			(_OMAP_TIMER_MATCH_OFFSET \
253 							| (WP_TMAR << WPSHIFT))
254 
255 #define OMAP_TIMER_CAPTURE_REG			(_OMAP_TIMER_CAPTURE_OFFSET \
256 							| (WP_NONE << WPSHIFT))
257 
258 #define OMAP_TIMER_IF_CTRL_REG			(_OMAP_TIMER_IF_CTRL_OFFSET \
259 							| (WP_NONE << WPSHIFT))
260 
261 #define OMAP_TIMER_CAPTURE2_REG			(_OMAP_TIMER_CAPTURE2_OFFSET \
262 							| (WP_NONE << WPSHIFT))
263 
264 #define OMAP_TIMER_TICK_POS_REG			(_OMAP_TIMER_TICK_POS_OFFSET \
265 							| (WP_TPIR << WPSHIFT))
266 
267 #define OMAP_TIMER_TICK_NEG_REG			(_OMAP_TIMER_TICK_NEG_OFFSET \
268 							| (WP_TNIR << WPSHIFT))
269 
270 #define OMAP_TIMER_TICK_COUNT_REG		(_OMAP_TIMER_TICK_COUNT_OFFSET \
271 							| (WP_TCVR << WPSHIFT))
272 
273 #define OMAP_TIMER_TICK_INT_MASK_SET_REG				\
274 		(_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
275 
276 #define OMAP_TIMER_TICK_INT_MASK_COUNT_REG				\
277 		(_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
278 
__omap_dm_timer_read(struct omap_dm_timer * timer,u32 reg,int posted)279 static inline u32 __omap_dm_timer_read(struct omap_dm_timer *timer, u32 reg,
280 						int posted)
281 {
282 	if (posted)
283 		while (readl_relaxed(timer->pend) & (reg >> WPSHIFT))
284 			cpu_relax();
285 
286 	return readl_relaxed(timer->func_base + (reg & 0xff));
287 }
288 
__omap_dm_timer_write(struct omap_dm_timer * timer,u32 reg,u32 val,int posted)289 static inline void __omap_dm_timer_write(struct omap_dm_timer *timer,
290 					u32 reg, u32 val, int posted)
291 {
292 	if (posted)
293 		while (readl_relaxed(timer->pend) & (reg >> WPSHIFT))
294 			cpu_relax();
295 
296 	writel_relaxed(val, timer->func_base + (reg & 0xff));
297 }
298 
__omap_dm_timer_init_regs(struct omap_dm_timer * timer)299 static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer)
300 {
301 	u32 tidr;
302 
303 	/* Assume v1 ip if bits [31:16] are zero */
304 	tidr = readl_relaxed(timer->io_base);
305 	if (!(tidr >> 16)) {
306 		timer->revision = 1;
307 		timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET;
308 		timer->irq_ena = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
309 		timer->irq_dis = timer->io_base + OMAP_TIMER_V1_INT_EN_OFFSET;
310 		timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET;
311 		timer->func_base = timer->io_base;
312 	} else {
313 		timer->revision = 2;
314 		timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS;
315 		timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET;
316 		timer->irq_dis = timer->io_base + OMAP_TIMER_V2_IRQENABLE_CLR;
317 		timer->pend = timer->io_base +
318 			_OMAP_TIMER_WRITE_PEND_OFFSET +
319 				OMAP_TIMER_V2_FUNC_OFFSET;
320 		timer->func_base = timer->io_base + OMAP_TIMER_V2_FUNC_OFFSET;
321 	}
322 }
323 
324 /*
325  * __omap_dm_timer_enable_posted - enables write posted mode
326  * @timer:      pointer to timer instance handle
327  *
328  * Enables the write posted mode for the timer. When posted mode is enabled
329  * writes to certain timer registers are immediately acknowledged by the
330  * internal bus and hence prevents stalling the CPU waiting for the write to
331  * complete. Enabling this feature can improve performance for writing to the
332  * timer registers.
333  */
__omap_dm_timer_enable_posted(struct omap_dm_timer * timer)334 static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
335 {
336 	if (timer->posted)
337 		return;
338 
339 	if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) {
340 		timer->posted = OMAP_TIMER_NONPOSTED;
341 		__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0);
342 		return;
343 	}
344 
345 	__omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
346 			      OMAP_TIMER_CTRL_POSTED, 0);
347 	timer->context.tsicr = OMAP_TIMER_CTRL_POSTED;
348 	timer->posted = OMAP_TIMER_POSTED;
349 }
350 
351 /**
352  * __omap_dm_timer_override_errata - override errata flags for a timer
353  * @timer:      pointer to timer handle
354  * @errata:	errata flags to be ignored
355  *
356  * For a given timer, override a timer errata by clearing the flags
357  * specified by the errata argument. A specific erratum should only be
358  * overridden for a timer if the timer is used in such a way the erratum
359  * has no impact.
360  */
__omap_dm_timer_override_errata(struct omap_dm_timer * timer,u32 errata)361 static inline void __omap_dm_timer_override_errata(struct omap_dm_timer *timer,
362 						   u32 errata)
363 {
364 	timer->errata &= ~errata;
365 }
366 
__omap_dm_timer_stop(struct omap_dm_timer * timer,int posted,unsigned long rate)367 static inline void __omap_dm_timer_stop(struct omap_dm_timer *timer,
368 					int posted, unsigned long rate)
369 {
370 	u32 l;
371 
372 	l = __omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
373 	if (l & OMAP_TIMER_CTRL_ST) {
374 		l &= ~0x1;
375 		__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, l, posted);
376 #ifdef CONFIG_ARCH_OMAP2PLUS
377 		/* Readback to make sure write has completed */
378 		__omap_dm_timer_read(timer, OMAP_TIMER_CTRL_REG, posted);
379 		/*
380 		 * Wait for functional clock period x 3.5 to make sure that
381 		 * timer is stopped
382 		 */
383 		udelay(3500000 / rate + 1);
384 #endif
385 	}
386 
387 	/* Ack possibly pending interrupt */
388 	writel_relaxed(OMAP_TIMER_INT_OVERFLOW, timer->irq_stat);
389 }
390 
__omap_dm_timer_load_start(struct omap_dm_timer * timer,u32 ctrl,unsigned int load,int posted)391 static inline void __omap_dm_timer_load_start(struct omap_dm_timer *timer,
392 						u32 ctrl, unsigned int load,
393 						int posted)
394 {
395 	__omap_dm_timer_write(timer, OMAP_TIMER_COUNTER_REG, load, posted);
396 	__omap_dm_timer_write(timer, OMAP_TIMER_CTRL_REG, ctrl, posted);
397 }
398 
__omap_dm_timer_int_enable(struct omap_dm_timer * timer,unsigned int value)399 static inline void __omap_dm_timer_int_enable(struct omap_dm_timer *timer,
400 						unsigned int value)
401 {
402 	writel_relaxed(value, timer->irq_ena);
403 	__omap_dm_timer_write(timer, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
404 }
405 
406 static inline unsigned int
__omap_dm_timer_read_counter(struct omap_dm_timer * timer,int posted)407 __omap_dm_timer_read_counter(struct omap_dm_timer *timer, int posted)
408 {
409 	return __omap_dm_timer_read(timer, OMAP_TIMER_COUNTER_REG, posted);
410 }
411 
__omap_dm_timer_write_status(struct omap_dm_timer * timer,unsigned int value)412 static inline void __omap_dm_timer_write_status(struct omap_dm_timer *timer,
413 						unsigned int value)
414 {
415 	writel_relaxed(value, timer->irq_stat);
416 }
417 
418 #endif /* __ASM_ARCH_DMTIMER_H */
419