Blame view

arch/arm/plat-omap/dmtimer.c 19.8 KB
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
1
2
3
4
5
  /*
   * linux/arch/arm/plat-omap/dmtimer.c
   *
   * OMAP Dual-Mode Timers
   *
97933d6ce   Tarun Kanti DebBarma   ARM: OMAP1: dmtim...
6
7
8
9
10
11
   * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
   * Tarun Kanti DebBarma <tarun.kanti@ti.com>
   * Thara Gopinath <thara@ti.com>
   *
   * dmtimer adaptation to platform_driver.
   *
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
12
   * Copyright (C) 2005 Nokia Corporation
77900a2fc   Timo Teras   ARM: OMAP: Port d...
13
14
   * OMAP2 support by Juha Yrjola
   * API improvements and OMAP2 clock framework support by Timo Teras
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
15
   *
44169075e   Santosh Shilimkar   ARM: OMAP4: Add m...
16
17
18
   * Copyright (C) 2009 Texas Instruments
   * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
   *
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
   * Free Software Foundation; either version 2 of the License, or (at your
   * option) any later version.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
   * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * You should have received a copy of the  GNU General Public License along
   * with this program; if not, write  to the Free Software Foundation, Inc.,
   * 675 Mass Ave, Cambridge, MA 02139, USA.
   */
869dec158   Axel Lin   ARM: OMAP: dmtime...
37
  #include <linux/module.h>
fced80c73   Russell King   [ARM] Convert asm...
38
  #include <linux/io.h>
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
39
  #include <linux/device.h>
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
40
  #include <linux/err.h>
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
41
  #include <linux/pm_runtime.h>
44169075e   Santosh Shilimkar   ARM: OMAP4: Add m...
42

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
43
  #include <plat/dmtimer.h>
0b30ec1cb   Jon Hunter   ARM: OMAP: Remove...
44
  #include <plat/omap-pm.h>
471b3aa70   Syed Mohammed, Khasim   ARM: OMAP: Pre-34...
45

2c799cef4   Tony Lindgren   ARM: OMAP: Remove...
46
  #include <mach/hardware.h>
b7b4ff764   Jon Hunter   ARM: OMAP2+: Add ...
47
  static u32 omap_reserved_systimers;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
48
  static LIST_HEAD(omap_timer_list);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
49
  static DEFINE_SPINLOCK(dm_timer_lock);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
50

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
51
52
53
54
55
56
57
58
  /**
   * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
   * @timer:      timer pointer over which read operation to perform
   * @reg:        lowest byte holds the register offset
   *
   * The posted mode bit is encoded in reg. Note that in posted mode write
   * pending bit must be checked. Otherwise a read of a non completed write
   * will produce an error.
0f0d08070   Richard Woodruff   ARM: OMAP: DMTime...
59
60
   */
  static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
61
  {
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
62
63
  	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  	return __omap_dm_timer_read(timer, reg, timer->posted);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
64
  }
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
65

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
66
67
68
69
70
71
72
73
74
  /**
   * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
   * @timer:      timer pointer over which write operation is to perform
   * @reg:        lowest byte holds the register offset
   * @value:      data to write into the register
   *
   * The posted mode bit is encoded in reg. Note that in posted mode the write
   * pending bit must be checked. Otherwise a write on a register which has a
   * pending write will be lost.
0f0d08070   Richard Woodruff   ARM: OMAP: DMTime...
75
76
77
   */
  static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
  						u32 value)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
78
  {
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
79
80
  	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  	__omap_dm_timer_write(timer, reg, value, timer->posted);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
81
  }
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
82
83
  static void omap_timer_restore_context(struct omap_dm_timer *timer)
  {
dffc9daee   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
84
  	if (timer->revision == 1)
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  		__raw_writel(timer->context.tistat, timer->sys_stat);
  
  	__raw_writel(timer->context.tisr, timer->irq_stat);
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
  				timer->context.twer);
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
  				timer->context.tcrr);
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
  				timer->context.tldr);
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
  				timer->context.tmar);
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
  				timer->context.tsicr);
  	__raw_writel(timer->context.tier, timer->irq_ena);
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
  				timer->context.tclr);
  }
77900a2fc   Timo Teras   ARM: OMAP: Port d...
102
  static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
103
  {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
104
  	int c;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
105
106
  	if (!timer->sys_stat)
  		return;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
107
  	c = 0;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
108
  	while (!(__raw_readl(timer->sys_stat) & 1)) {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
109
110
111
112
113
114
115
  		c++;
  		if (c > 100000) {
  			printk(KERN_ERR "Timer failed to reset
  ");
  			return;
  		}
  	}
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
116
  }
77900a2fc   Timo Teras   ARM: OMAP: Port d...
117
118
  static void omap_dm_timer_reset(struct omap_dm_timer *timer)
  {
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
119
  	omap_dm_timer_enable(timer);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
120
  	if (timer->pdev->id != 1) {
e32f7ec2e   Timo Teras   ARM: OMAP: Fix 32...
121
122
123
  		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
  		omap_dm_timer_wait_for_reset(timer);
  	}
0f0d08070   Richard Woodruff   ARM: OMAP: DMTime...
124

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
125
  	__omap_dm_timer_reset(timer, 0, 0);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
126
  	omap_dm_timer_disable(timer);
0f0d08070   Richard Woodruff   ARM: OMAP: DMTime...
127
  	timer->posted = 1;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
128
  }
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
129
  int omap_dm_timer_prepare(struct omap_dm_timer *timer)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
130
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
131
  	int ret;
bca458084   Jon Hunter   ARM: OMAP1: Fix d...
132
133
134
135
136
137
138
139
140
141
142
143
  	/*
  	 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
  	 * do not call clk_get() for these devices.
  	 */
  	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
  		timer->fclk = clk_get(&timer->pdev->dev, "fck");
  		if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
  			timer->fclk = NULL;
  			dev_err(&timer->pdev->dev, ": No fclk handle.
  ");
  			return -EINVAL;
  		}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
144
  	}
6615975bc   Jon Hunter   ARM: OMAP: Add fl...
145
  	if (timer->capability & OMAP_TIMER_NEEDS_RESET)
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
146
147
148
149
150
151
  		omap_dm_timer_reset(timer);
  
  	ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
  
  	timer->posted = 1;
  	return ret;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
152
  }
b7b4ff764   Jon Hunter   ARM: OMAP2+: Add ...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  static inline u32 omap_dm_timer_reserved_systimer(int id)
  {
  	return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
  }
  
  int omap_dm_timer_reserve_systimer(int id)
  {
  	if (omap_dm_timer_reserved_systimer(id))
  		return -ENODEV;
  
  	omap_reserved_systimers |= (1 << (id - 1));
  
  	return 0;
  }
77900a2fc   Timo Teras   ARM: OMAP: Port d...
167
168
  struct omap_dm_timer *omap_dm_timer_request(void)
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
169
  	struct omap_dm_timer *timer = NULL, *t;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
170
  	unsigned long flags;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
171
  	int ret = 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
172
173
  
  	spin_lock_irqsave(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
174
175
  	list_for_each_entry(t, &omap_timer_list, node) {
  		if (t->reserved)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
176
  			continue;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
177
  		timer = t;
83379c81f   Timo Teras   ARM: OMAP: Update...
178
  		timer->reserved = 1;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
179
180
  		break;
  	}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
181
182
183
184
185
186
187
188
  
  	if (timer) {
  		ret = omap_dm_timer_prepare(timer);
  		if (ret) {
  			timer->reserved = 0;
  			timer = NULL;
  		}
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
189
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
190
191
192
  	if (!timer)
  		pr_debug("%s: timer request failed!
  ", __func__);
83379c81f   Timo Teras   ARM: OMAP: Update...
193

77900a2fc   Timo Teras   ARM: OMAP: Port d...
194
195
  	return timer;
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
196
  EXPORT_SYMBOL_GPL(omap_dm_timer_request);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
197
198
  
  struct omap_dm_timer *omap_dm_timer_request_specific(int id)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
199
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
200
  	struct omap_dm_timer *timer = NULL, *t;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
201
  	unsigned long flags;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
202
  	int ret = 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
203

77900a2fc   Timo Teras   ARM: OMAP: Port d...
204
  	spin_lock_irqsave(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
205
206
207
208
209
210
  	list_for_each_entry(t, &omap_timer_list, node) {
  		if (t->pdev->id == id && !t->reserved) {
  			timer = t;
  			timer->reserved = 1;
  			break;
  		}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
211
  	}
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
212

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
213
214
215
216
217
218
219
  	if (timer) {
  		ret = omap_dm_timer_prepare(timer);
  		if (ret) {
  			timer->reserved = 0;
  			timer = NULL;
  		}
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
220
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
221
222
223
  	if (!timer)
  		pr_debug("%s: timer%d request failed!
  ", __func__, id);
83379c81f   Timo Teras   ARM: OMAP: Update...
224

77900a2fc   Timo Teras   ARM: OMAP: Port d...
225
  	return timer;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
226
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
227
  EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
228

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
229
  int omap_dm_timer_free(struct omap_dm_timer *timer)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
230
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
231
232
  	if (unlikely(!timer))
  		return -EINVAL;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
233
  	clk_put(timer->fclk);
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
234

77900a2fc   Timo Teras   ARM: OMAP: Port d...
235
236
  	WARN_ON(!timer->reserved);
  	timer->reserved = 0;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
237
  	return 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
238
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
239
  EXPORT_SYMBOL_GPL(omap_dm_timer_free);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
240

12583a70a   Timo Teras   ARM: OMAP: Add en...
241
242
  void omap_dm_timer_enable(struct omap_dm_timer *timer)
  {
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
243
  	pm_runtime_get_sync(&timer->pdev->dev);
12583a70a   Timo Teras   ARM: OMAP: Add en...
244
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
245
  EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
12583a70a   Timo Teras   ARM: OMAP: Add en...
246
247
248
  
  void omap_dm_timer_disable(struct omap_dm_timer *timer)
  {
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
249
  	pm_runtime_put(&timer->pdev->dev);
12583a70a   Timo Teras   ARM: OMAP: Add en...
250
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
251
  EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
12583a70a   Timo Teras   ARM: OMAP: Add en...
252

77900a2fc   Timo Teras   ARM: OMAP: Port d...
253
254
  int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
255
256
257
  	if (timer)
  		return timer->irq;
  	return -EINVAL;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
258
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
259
  EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
260
261
  
  #if defined(CONFIG_ARCH_OMAP1)
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
262
263
264
265
266
267
  /**
   * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
   * @inputmask: current value of idlect mask
   */
  __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
268
269
270
  	int i = 0;
  	struct omap_dm_timer *timer = NULL;
  	unsigned long flags;
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
271
272
273
274
275
276
  
  	/* If ARMXOR cannot be idled this function call is unnecessary */
  	if (!(inputmask & (1 << 1)))
  		return inputmask;
  
  	/* If any active timer is using ARMXOR return modified mask */
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
277
278
  	spin_lock_irqsave(&dm_timer_lock, flags);
  	list_for_each_entry(timer, &omap_timer_list, node) {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
279
  		u32 l;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
280
  		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
281
282
  		if (l & OMAP_TIMER_CTRL_ST) {
  			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
283
284
285
286
  				inputmask &= ~(1 << 1);
  			else
  				inputmask &= ~(1 << 2);
  		}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
287
  		i++;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
288
  	}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
289
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
290
291
292
  
  	return inputmask;
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
293
  EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
294

140455fa0   Tony Lindgren   omap2/3/4: Replac...
295
  #else
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
296

77900a2fc   Timo Teras   ARM: OMAP: Port d...
297
  struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
298
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
299
300
301
  	if (timer)
  		return timer->fclk;
  	return NULL;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
302
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
303
  EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
304

77900a2fc   Timo Teras   ARM: OMAP: Port d...
305
306
307
  __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  {
  	BUG();
2121880e8   Dirk Behme   ARM: OMAP: Fix wa...
308
309
  
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
310
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
311
  EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
312

77900a2fc   Timo Teras   ARM: OMAP: Port d...
313
  #endif
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
314

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
315
  int omap_dm_timer_trigger(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
316
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
317
318
319
320
  	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  		pr_err("%s: timer not available or enabled.
  ", __func__);
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
321
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
322
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
323
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
324
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
325
  EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
326

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
327
  int omap_dm_timer_start(struct omap_dm_timer *timer)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
328
329
  {
  	u32 l;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
330

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
331
332
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
333
  	omap_dm_timer_enable(timer);
1c2d076b5   Jon Hunter   ARM: OMAP: Remove...
334
  	if (!(timer->capability & OMAP_TIMER_ALWON)) {
0b30ec1cb   Jon Hunter   ARM: OMAP: Remove...
335
336
  		if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
  				timer->ctx_loss_count)
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
337
338
  			omap_timer_restore_context(timer);
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
339
340
341
342
343
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  	if (!(l & OMAP_TIMER_CTRL_ST)) {
  		l |= OMAP_TIMER_CTRL_ST;
  		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  	}
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
344
345
346
  
  	/* Save the context */
  	timer->context.tclr = l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
347
  	return 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
348
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
349
  EXPORT_SYMBOL_GPL(omap_dm_timer_start);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
350

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
351
  int omap_dm_timer_stop(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
352
  {
caf64f2fd   Tony Lindgren   omap: Make a subs...
353
  	unsigned long rate = 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
354

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
355
356
  	if (unlikely(!timer))
  		return -EINVAL;
6615975bc   Jon Hunter   ARM: OMAP: Add fl...
357
  	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
358
  		rate = clk_get_rate(timer->fclk);
caf64f2fd   Tony Lindgren   omap: Make a subs...
359

ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
360
  	__omap_dm_timer_stop(timer, timer->posted, rate);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
361

0b30ec1cb   Jon Hunter   ARM: OMAP: Remove...
362
  	if (!(timer->capability & OMAP_TIMER_ALWON))
dffc9daee   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
363
  		timer->ctx_loss_count =
0b30ec1cb   Jon Hunter   ARM: OMAP: Remove...
364
  			omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
dffc9daee   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
365
366
367
368
369
370
371
372
373
374
  
  	/*
  	 * Since the register values are computed and written within
  	 * __omap_dm_timer_stop, we need to use read to retrieve the
  	 * context.
  	 */
  	timer->context.tclr =
  			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  	timer->context.tisr = __raw_readl(timer->irq_stat);
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
375
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
376
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
377
  EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
378

f248076c0   Paul Walmsley   OMAP2/3 GPTIMER: ...
379
  int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
380
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
381
  	int ret;
2b2d35230   Jon Hunter   ARM: OMAP2+: Move...
382
383
  	char *parent_name = NULL;
  	struct clk *fclk, *parent;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
384
385
386
387
388
389
  	struct dmtimer_platform_data *pdata;
  
  	if (unlikely(!timer))
  		return -EINVAL;
  
  	pdata = timer->pdev->dev.platform_data;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
390

77900a2fc   Timo Teras   ARM: OMAP: Port d...
391
  	if (source < 0 || source >= 3)
f248076c0   Paul Walmsley   OMAP2/3 GPTIMER: ...
392
  		return -EINVAL;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
393

2b2d35230   Jon Hunter   ARM: OMAP2+: Move...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  	/*
  	 * FIXME: Used for OMAP1 devices only because they do not currently
  	 * use the clock framework to set the parent clock. To be removed
  	 * once OMAP1 migrated to using clock framework for dmtimers
  	 */
  	if (pdata->set_timer_src)
  		return pdata->set_timer_src(timer->pdev, source);
  
  	fclk = clk_get(&timer->pdev->dev, "fck");
  	if (IS_ERR_OR_NULL(fclk)) {
  		pr_err("%s: fck not found
  ", __func__);
  		return -EINVAL;
  	}
  
  	switch (source) {
  	case OMAP_TIMER_SRC_SYS_CLK:
c59b537d8   Jon Hunter   ARM: OMAP2+: Simp...
411
  		parent_name = "timer_sys_ck";
2b2d35230   Jon Hunter   ARM: OMAP2+: Move...
412
413
414
  		break;
  
  	case OMAP_TIMER_SRC_32_KHZ:
c59b537d8   Jon Hunter   ARM: OMAP2+: Simp...
415
  		parent_name = "timer_32k_ck";
2b2d35230   Jon Hunter   ARM: OMAP2+: Move...
416
417
418
  		break;
  
  	case OMAP_TIMER_SRC_EXT_CLK:
c59b537d8   Jon Hunter   ARM: OMAP2+: Simp...
419
  		parent_name = "timer_ext_ck";
2b2d35230   Jon Hunter   ARM: OMAP2+: Move...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  		break;
  	}
  
  	parent = clk_get(&timer->pdev->dev, parent_name);
  	if (IS_ERR_OR_NULL(parent)) {
  		pr_err("%s: %s not found
  ", __func__, parent_name);
  		ret = -EINVAL;
  		goto out;
  	}
  
  	ret = clk_set_parent(fclk, parent);
  	if (IS_ERR_VALUE(ret))
  		pr_err("%s: failed to set %s as parent
  ", __func__,
  			parent_name);
  
  	clk_put(parent);
  out:
  	clk_put(fclk);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
440
441
  
  	return ret;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
442
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
443
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
444

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
445
  int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
446
  			    unsigned int load)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
447
448
  {
  	u32 l;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
449

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
450
451
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
452
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
453
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
454
455
456
457
  	if (autoreload)
  		l |= OMAP_TIMER_CTRL_AR;
  	else
  		l &= ~OMAP_TIMER_CTRL_AR;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
458
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
459
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
0f0d08070   Richard Woodruff   ARM: OMAP: DMTime...
460

77900a2fc   Timo Teras   ARM: OMAP: Port d...
461
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
462
463
464
465
  	/* Save the context */
  	timer->context.tclr = l;
  	timer->context.tldr = load;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
466
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
467
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
468
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
469

3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
470
  /* Optimized set_load which removes costly spin wait in timer_start */
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
471
  int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
472
473
474
                              unsigned int load)
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
475
476
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
477
  	omap_dm_timer_enable(timer);
1c2d076b5   Jon Hunter   ARM: OMAP: Remove...
478
  	if (!(timer->capability & OMAP_TIMER_ALWON)) {
0b30ec1cb   Jon Hunter   ARM: OMAP: Remove...
479
480
  		if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
  				timer->ctx_loss_count)
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
481
482
  			omap_timer_restore_context(timer);
  	}
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
483
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
64ce2907b   Paul Walmsley   ARM: OMAP2: skip ...
484
  	if (autoreload) {
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
485
  		l |= OMAP_TIMER_CTRL_AR;
64ce2907b   Paul Walmsley   ARM: OMAP2: skip ...
486
487
  		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
  	} else {
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
488
  		l &= ~OMAP_TIMER_CTRL_AR;
64ce2907b   Paul Walmsley   ARM: OMAP2: skip ...
489
  	}
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
490
  	l |= OMAP_TIMER_CTRL_ST;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
491
  	__omap_dm_timer_load_start(timer, l, load, timer->posted);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
492
493
494
495
496
  
  	/* Save the context */
  	timer->context.tclr = l;
  	timer->context.tldr = load;
  	timer->context.tcrr = load;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
497
  	return 0;
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
498
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
499
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
500

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
501
  int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
502
  			     unsigned int match)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
503
504
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
505
506
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
507
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
508
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
83379c81f   Timo Teras   ARM: OMAP: Update...
509
  	if (enable)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
510
511
512
  		l |= OMAP_TIMER_CTRL_CE;
  	else
  		l &= ~OMAP_TIMER_CTRL_CE;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
513
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
514
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
515
516
517
518
519
  
  	/* Save the context */
  	timer->context.tclr = l;
  	timer->context.tmar = match;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
520
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
521
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
522
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
523

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
524
  int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
525
  			   int toggle, int trigger)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
526
527
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
528
529
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
530
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
531
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
532
533
534
535
536
537
538
  	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
  	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
  	if (def_on)
  		l |= OMAP_TIMER_CTRL_SCPWM;
  	if (toggle)
  		l |= OMAP_TIMER_CTRL_PT;
  	l |= trigger << 10;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
539
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
540
541
542
543
  
  	/* Save the context */
  	timer->context.tclr = l;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
544
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
545
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
546
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
547

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
548
  int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
549
550
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
551
552
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
553
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
554
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
555
556
557
558
559
  	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
  	if (prescaler >= 0x00 && prescaler <= 0x07) {
  		l |= OMAP_TIMER_CTRL_PRE;
  		l |= prescaler << 2;
  	}
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
560
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
561
562
563
564
  
  	/* Save the context */
  	timer->context.tclr = l;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
565
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
566
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
567
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
568

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
569
  int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
570
  				  unsigned int value)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
571
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
572
573
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
574
  	omap_dm_timer_enable(timer);
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
575
  	__omap_dm_timer_int_enable(timer, value);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
576
577
578
579
580
  
  	/* Save the context */
  	timer->context.tier = value;
  	timer->context.twer = value;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
581
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
582
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
583
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
584

77900a2fc   Timo Teras   ARM: OMAP: Port d...
585
  unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
586
  {
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
587
  	unsigned int l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
588
589
590
  	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  		pr_err("%s: timer not available or enabled.
  ", __func__);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
591
592
  		return 0;
  	}
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
593
  	l = __raw_readl(timer->irq_stat);
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
594
595
  
  	return l;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
596
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
597
  EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
598

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
599
  int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
600
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
601
602
  	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
  		return -EINVAL;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
603
  	__omap_dm_timer_write_status(timer, value);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
604
605
  	/* Save the context */
  	timer->context.tisr = value;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
606
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
607
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
608
  EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
609

77900a2fc   Timo Teras   ARM: OMAP: Port d...
610
  unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
611
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
612
613
614
  	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  		pr_err("%s: timer not iavailable or enabled.
  ", __func__);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
615
616
  		return 0;
  	}
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
617
  	return __omap_dm_timer_read_counter(timer, timer->posted);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
618
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
619
  EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
620

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
621
  int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
83379c81f   Timo Teras   ARM: OMAP: Update...
622
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
623
624
625
626
  	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
  		pr_err("%s: timer not available or enabled.
  ", __func__);
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
627
  	}
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
628
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
629
630
631
  
  	/* Save the context */
  	timer->context.tcrr = value;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
632
  	return 0;
83379c81f   Timo Teras   ARM: OMAP: Update...
633
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
634
  EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
83379c81f   Timo Teras   ARM: OMAP: Update...
635

77900a2fc   Timo Teras   ARM: OMAP: Port d...
636
  int omap_dm_timers_active(void)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
637
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
638
  	struct omap_dm_timer *timer;
12583a70a   Timo Teras   ARM: OMAP: Add en...
639

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
640
  	list_for_each_entry(timer, &omap_timer_list, node) {
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
641
  		if (!timer->reserved)
12583a70a   Timo Teras   ARM: OMAP: Add en...
642
  			continue;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
643
  		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
644
  		    OMAP_TIMER_CTRL_ST) {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
645
  			return 1;
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
646
  		}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
647
648
649
  	}
  	return 0;
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
650
  EXPORT_SYMBOL_GPL(omap_dm_timers_active);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
651

df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
652
653
654
655
656
657
658
659
660
  /**
   * omap_dm_timer_probe - probe function called for every registered device
   * @pdev:	pointer to current timer platform device
   *
   * Called by driver framework at the end of device registration for all
   * timer devices.
   */
  static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
  {
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
661
662
  	unsigned long flags;
  	struct omap_dm_timer *timer;
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
663
664
  	struct resource *mem, *irq;
  	struct device *dev = &pdev->dev;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
665
666
667
  	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
  
  	if (!pdata) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
668
669
  		dev_err(dev, "%s: no platform data.
  ", __func__);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
670
671
672
673
674
  		return -ENODEV;
  	}
  
  	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  	if (unlikely(!irq)) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
675
676
  		dev_err(dev, "%s: no IRQ resource.
  ", __func__);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
677
678
679
680
681
  		return -ENODEV;
  	}
  
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (unlikely(!mem)) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
682
683
  		dev_err(dev, "%s: no memory resource.
  ", __func__);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
684
685
  		return -ENODEV;
  	}
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
686
  	timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
687
  	if (!timer) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
688
689
690
  		dev_err(dev, "%s: memory alloc failed!
  ", __func__);
  		return  -ENOMEM;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
691
  	}
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
692
  	timer->io_base = devm_request_and_ioremap(dev, mem);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
693
  	if (!timer->io_base) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
694
695
696
  		dev_err(dev, "%s: region already claimed.
  ", __func__);
  		return -ENOMEM;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
697
698
699
700
  	}
  
  	timer->id = pdev->id;
  	timer->irq = irq->start;
b7b4ff764   Jon Hunter   ARM: OMAP2+: Add ...
701
  	timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
702
  	timer->pdev = pdev;
d1c1691be   Jon Hunter   ARM: OMAP: Add DM...
703
  	timer->capability = pdata->timer_capability;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
704

ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
705
  	/* Skip pm_runtime_enable for OMAP1 */
6615975bc   Jon Hunter   ARM: OMAP: Add fl...
706
  	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
707
708
  		pm_runtime_enable(dev);
  		pm_runtime_irq_safe(dev);
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
709
  	}
0dad9faea   Tony Lindgren   ARM: OMAP: dmtime...
710
  	if (!timer->reserved) {
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
711
  		pm_runtime_get_sync(dev);
0dad9faea   Tony Lindgren   ARM: OMAP: dmtime...
712
  		__omap_dm_timer_init_regs(timer);
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
713
  		pm_runtime_put(dev);
0dad9faea   Tony Lindgren   ARM: OMAP: dmtime...
714
  	}
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
715
716
717
718
  	/* add the timer element to the list */
  	spin_lock_irqsave(&dm_timer_lock, flags);
  	list_add_tail(&timer->node, &omap_timer_list);
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
74dd9ec62   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
719
720
  	dev_dbg(dev, "Device Probed.
  ");
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
721
722
  
  	return 0;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
  }
  
  /**
   * omap_dm_timer_remove - cleanup a registered timer device
   * @pdev:	pointer to current timer platform device
   *
   * Called by driver framework whenever a timer device is unregistered.
   * In addition to freeing platform resources it also deletes the timer
   * entry from the local list.
   */
  static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
  {
  	struct omap_dm_timer *timer;
  	unsigned long flags;
  	int ret = -EINVAL;
  
  	spin_lock_irqsave(&dm_timer_lock, flags);
  	list_for_each_entry(timer, &omap_timer_list, node)
  		if (timer->pdev->id == pdev->id) {
  			list_del(&timer->node);
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
743
744
745
746
747
748
749
750
751
752
  			ret = 0;
  			break;
  		}
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
  
  	return ret;
  }
  
  static struct platform_driver omap_dm_timer_driver = {
  	.probe  = omap_dm_timer_probe,
4c23c8da9   Arnd Bergmann   ARM: omap: use __...
753
  	.remove = __devexit_p(omap_dm_timer_remove),
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
  	.driver = {
  		.name   = "omap_timer",
  	},
  };
  
  static int __init omap_dm_timer_driver_init(void)
  {
  	return platform_driver_register(&omap_dm_timer_driver);
  }
  
  static void __exit omap_dm_timer_driver_exit(void)
  {
  	platform_driver_unregister(&omap_dm_timer_driver);
  }
  
  early_platform_init("earlytimer", &omap_dm_timer_driver);
  module_init(omap_dm_timer_driver_init);
  module_exit(omap_dm_timer_driver_exit);
  
  MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("platform:" DRIVER_NAME);
  MODULE_AUTHOR("Texas Instruments Inc");