Blame view

arch/arm/plat-omap/dmtimer.c 19 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>
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
39
  #include <linux/slab.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>
471b3aa70   Syed Mohammed, Khasim   ARM: OMAP: Pre-34...
44

df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
45
  static LIST_HEAD(omap_timer_list);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
46
  static DEFINE_SPINLOCK(dm_timer_lock);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
47

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
48
49
50
51
52
53
54
55
  /**
   * 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...
56
57
   */
  static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
58
  {
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
59
60
  	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...
61
  }
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
62

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
63
64
65
66
67
68
69
70
71
  /**
   * 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...
72
73
74
   */
  static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
  						u32 value)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
75
  {
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
76
77
  	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...
78
  }
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
79
80
  static void omap_timer_restore_context(struct omap_dm_timer *timer)
  {
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  	__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...
96
  static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
97
  {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
98
  	int c;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
99
100
  	if (!timer->sys_stat)
  		return;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
101
  	c = 0;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
102
  	while (!(__raw_readl(timer->sys_stat) & 1)) {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
103
104
105
106
107
108
109
  		c++;
  		if (c > 100000) {
  			printk(KERN_ERR "Timer failed to reset
  ");
  			return;
  		}
  	}
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
110
  }
77900a2fc   Timo Teras   ARM: OMAP: Port d...
111
112
  static void omap_dm_timer_reset(struct omap_dm_timer *timer)
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
113
  	if (timer->pdev->id != 1) {
e32f7ec2e   Timo Teras   ARM: OMAP: Fix 32...
114
115
116
  		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...
117

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
118
  	__omap_dm_timer_reset(timer, 0, 0);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
119
  }
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
120
  int omap_dm_timer_prepare(struct omap_dm_timer *timer)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
121
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
122
  	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
123

506c079b8   Jon Hunter   ARM: OMAP3+: Impl...
124
  	omap_dm_timer_enable(timer);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
125
126
127
128
129
130
131
  	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...
132
133
  	if (pdata->needs_manual_reset)
  		omap_dm_timer_reset(timer);
506c079b8   Jon Hunter   ARM: OMAP3+: Impl...
134
135
  	__omap_dm_timer_enable_posted(timer);
  	omap_dm_timer_disable(timer);
8c32c4f27   Vaibhav Hiremath   ARM:omap:am33xx: ...
136
  	return 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
137
138
139
140
  }
  
  struct omap_dm_timer *omap_dm_timer_request(void)
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
141
  	struct omap_dm_timer *timer = NULL, *t;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
142
  	unsigned long flags;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
143
  	int ret = 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
144
145
  
  	spin_lock_irqsave(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
146
147
  	list_for_each_entry(t, &omap_timer_list, node) {
  		if (t->reserved)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
148
  			continue;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
149
  		timer = t;
83379c81f   Timo Teras   ARM: OMAP: Update...
150
  		timer->reserved = 1;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
151
152
  		break;
  	}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
153
154
155
156
157
158
159
160
  
  	if (timer) {
  		ret = omap_dm_timer_prepare(timer);
  		if (ret) {
  			timer->reserved = 0;
  			timer = NULL;
  		}
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
161
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
162
163
164
  	if (!timer)
  		pr_debug("%s: timer request failed!
  ", __func__);
83379c81f   Timo Teras   ARM: OMAP: Update...
165

77900a2fc   Timo Teras   ARM: OMAP: Port d...
166
167
  	return timer;
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
168
  EXPORT_SYMBOL_GPL(omap_dm_timer_request);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
169
170
  
  struct omap_dm_timer *omap_dm_timer_request_specific(int id)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
171
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
172
  	struct omap_dm_timer *timer = NULL, *t;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
173
  	unsigned long flags;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
174
  	int ret = 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
175

77900a2fc   Timo Teras   ARM: OMAP: Port d...
176
  	spin_lock_irqsave(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
177
178
179
180
181
182
  	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...
183
  	}
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
184

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
185
186
187
188
189
190
191
  	if (timer) {
  		ret = omap_dm_timer_prepare(timer);
  		if (ret) {
  			timer->reserved = 0;
  			timer = NULL;
  		}
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
192
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
193
194
195
  	if (!timer)
  		pr_debug("%s: timer%d request failed!
  ", __func__, id);
83379c81f   Timo Teras   ARM: OMAP: Update...
196

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

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
201
  int omap_dm_timer_free(struct omap_dm_timer *timer)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
202
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
203
204
  	if (unlikely(!timer))
  		return -EINVAL;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
205
  	clk_put(timer->fclk);
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
206

77900a2fc   Timo Teras   ARM: OMAP: Port d...
207
208
  	WARN_ON(!timer->reserved);
  	timer->reserved = 0;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
209
  	return 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
210
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
211
  EXPORT_SYMBOL_GPL(omap_dm_timer_free);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
212

12583a70a   Timo Teras   ARM: OMAP: Add en...
213
214
  void omap_dm_timer_enable(struct omap_dm_timer *timer)
  {
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
215
  	pm_runtime_get_sync(&timer->pdev->dev);
12583a70a   Timo Teras   ARM: OMAP: Add en...
216
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
217
  EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
12583a70a   Timo Teras   ARM: OMAP: Add en...
218
219
220
  
  void omap_dm_timer_disable(struct omap_dm_timer *timer)
  {
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
221
  	pm_runtime_put(&timer->pdev->dev);
12583a70a   Timo Teras   ARM: OMAP: Add en...
222
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
223
  EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
12583a70a   Timo Teras   ARM: OMAP: Add en...
224

77900a2fc   Timo Teras   ARM: OMAP: Port d...
225
226
  int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
227
228
229
  	if (timer)
  		return timer->irq;
  	return -EINVAL;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
230
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
231
  EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
232
233
  
  #if defined(CONFIG_ARCH_OMAP1)
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
234
235
236
237
238
239
  /**
   * 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...
240
241
242
  	int i = 0;
  	struct omap_dm_timer *timer = NULL;
  	unsigned long flags;
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
243
244
245
246
247
248
  
  	/* 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...
249
250
  	spin_lock_irqsave(&dm_timer_lock, flags);
  	list_for_each_entry(timer, &omap_timer_list, node) {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
251
  		u32 l;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
252
  		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
253
254
  		if (l & OMAP_TIMER_CTRL_ST) {
  			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
255
256
257
258
  				inputmask &= ~(1 << 1);
  			else
  				inputmask &= ~(1 << 2);
  		}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
259
  		i++;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
260
  	}
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
261
  	spin_unlock_irqrestore(&dm_timer_lock, flags);
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
262
263
264
  
  	return inputmask;
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
265
  EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
a569c6ec3   Tony Lindgren   [ARM] 3427/1: ARM...
266

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

77900a2fc   Timo Teras   ARM: OMAP: Port d...
269
  struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
270
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
271
272
273
  	if (timer)
  		return timer->fclk;
  	return NULL;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
274
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
275
  EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
276

77900a2fc   Timo Teras   ARM: OMAP: Port d...
277
278
279
  __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
  {
  	BUG();
2121880e8   Dirk Behme   ARM: OMAP: Fix wa...
280
281
  
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
282
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
283
  EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
284

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

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
287
  int omap_dm_timer_trigger(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
288
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
289
290
291
292
  	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...
293
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
294
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
295
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
296
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
297
  EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
298

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

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
303
304
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
305
306
307
308
309
310
311
312
  	omap_dm_timer_enable(timer);
  
  	if (timer->loses_context) {
  		u32 ctx_loss_cnt_after =
  			timer->get_context_loss_count(&timer->pdev->dev);
  		if (ctx_loss_cnt_after != timer->ctx_loss_count)
  			omap_timer_restore_context(timer);
  	}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
313
314
315
316
317
  	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...
318
319
320
  
  	/* Save the context */
  	timer->context.tclr = l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
321
  	return 0;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
322
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
323
  EXPORT_SYMBOL_GPL(omap_dm_timer_start);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
324

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
325
  int omap_dm_timer_stop(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
326
  {
caf64f2fd   Tony Lindgren   omap: Make a subs...
327
  	unsigned long rate = 0;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
328
  	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
329

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
330
331
  	if (unlikely(!timer))
  		return -EINVAL;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
332
333
  	if (!pdata->needs_manual_reset)
  		rate = clk_get_rate(timer->fclk);
caf64f2fd   Tony Lindgren   omap: Make a subs...
334

ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
335
  	__omap_dm_timer_stop(timer, timer->posted, rate);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
336
337
  
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
338
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
339
  EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
340

f248076c0   Paul Walmsley   OMAP2/3 GPTIMER: ...
341
  int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
342
  {
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
343
  	int ret;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
344
345
346
347
348
349
  	struct dmtimer_platform_data *pdata;
  
  	if (unlikely(!timer))
  		return -EINVAL;
  
  	pdata = timer->pdev->dev.platform_data;
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
350

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

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
354
  	ret = pdata->set_timer_src(timer->pdev, source);
3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
355
356
  
  	return ret;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
357
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
358
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
359

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

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
365
366
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
367
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
368
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
369
370
371
372
  	if (autoreload)
  		l |= OMAP_TIMER_CTRL_AR;
  	else
  		l &= ~OMAP_TIMER_CTRL_AR;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
373
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
374
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
0f0d08070   Richard Woodruff   ARM: OMAP: DMTime...
375

77900a2fc   Timo Teras   ARM: OMAP: Port d...
376
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
377
378
379
380
  	/* Save the context */
  	timer->context.tclr = l;
  	timer->context.tldr = load;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
381
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
382
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
383
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
384

3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
385
  /* Optimized set_load which removes costly spin wait in timer_start */
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
386
  int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
387
388
389
                              unsigned int load)
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
390
391
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
392
393
394
395
396
397
398
399
  	omap_dm_timer_enable(timer);
  
  	if (timer->loses_context) {
  		u32 ctx_loss_cnt_after =
  			timer->get_context_loss_count(&timer->pdev->dev);
  		if (ctx_loss_cnt_after != timer->ctx_loss_count)
  			omap_timer_restore_context(timer);
  	}
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
400
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
64ce2907b   Paul Walmsley   ARM: OMAP2: skip ...
401
  	if (autoreload) {
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
402
  		l |= OMAP_TIMER_CTRL_AR;
64ce2907b   Paul Walmsley   ARM: OMAP2: skip ...
403
404
  		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
  	} else {
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
405
  		l &= ~OMAP_TIMER_CTRL_AR;
64ce2907b   Paul Walmsley   ARM: OMAP2: skip ...
406
  	}
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
407
  	l |= OMAP_TIMER_CTRL_ST;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
408
  	__omap_dm_timer_load_start(timer, l, load, timer->posted);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
409
410
411
412
413
  
  	/* Save the context */
  	timer->context.tclr = l;
  	timer->context.tldr = load;
  	timer->context.tcrr = load;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
414
  	return 0;
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
415
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
416
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
3fddd09e5   Richard Woodruff   ARM: OMAP: DMTime...
417

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
418
  int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
419
  			     unsigned int match)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
420
421
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
422
423
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
424
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
425
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
83379c81f   Timo Teras   ARM: OMAP: Update...
426
  	if (enable)
77900a2fc   Timo Teras   ARM: OMAP: Port d...
427
428
429
  		l |= OMAP_TIMER_CTRL_CE;
  	else
  		l &= ~OMAP_TIMER_CTRL_CE;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
430
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
431
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
432
433
434
435
436
  
  	/* Save the context */
  	timer->context.tclr = l;
  	timer->context.tmar = match;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
437
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
438
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
439
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
440

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
441
  int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
442
  			   int toggle, int trigger)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
443
444
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
445
446
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
447
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
448
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
449
450
451
452
453
454
455
  	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...
456
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
457
458
459
460
  
  	/* Save the context */
  	timer->context.tclr = l;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
461
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
462
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
463
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
464

8c32c4f27   Vaibhav Hiremath   ARM:omap:am33xx: ...
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  int omap_dm_timer_set_capture(struct omap_dm_timer *timer, bool lht,
  				bool hlt, bool cm)
  {
  	u32 l;
  
  	if (unlikely(!timer))
  		return -EINVAL;
  
  	omap_dm_timer_enable(timer);
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
  
  	if (lht && hlt)
  		l |= OMAP_TIMER_CTRL_TCM_BOTHEDGES;
  	else if (lht)
  		l |= OMAP_TIMER_CTRL_TCM_LOWTOHIGH;
  	else if (hlt)
  		l |= OMAP_TIMER_CTRL_TCM_HIGHTOLOW;
  	else
  		l &= ~OMAP_TIMER_CTRL_TCM_BOTHEDGES;
  
  	if (cm)
  		l |= OMAP_TIMER_CTRL_CAPTMODE;
  	else
  		l &= ~OMAP_TIMER_CTRL_CAPTMODE;
  
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
  
  	/* Save the context */
  	timer->context.tclr = l;
  	omap_dm_timer_disable(timer);
  	return 0;
  }
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_capture);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
498
  int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
499
500
  {
  	u32 l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
501
502
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
503
  	omap_dm_timer_enable(timer);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
504
  	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
77900a2fc   Timo Teras   ARM: OMAP: Port d...
505
506
507
508
509
  	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...
510
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
511
512
513
514
  
  	/* Save the context */
  	timer->context.tclr = l;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
515
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
516
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
517
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
518

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
519
  int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
77900a2fc   Timo Teras   ARM: OMAP: Port d...
520
  				  unsigned int value)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
521
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
522
523
  	if (unlikely(!timer))
  		return -EINVAL;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
524
  	omap_dm_timer_enable(timer);
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
525
  	__omap_dm_timer_int_enable(timer, value);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
526
527
528
529
530
  
  	/* Save the context */
  	timer->context.tier = value;
  	timer->context.twer = value;
  	omap_dm_timer_disable(timer);
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
531
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
532
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
533
  EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
534

77900a2fc   Timo Teras   ARM: OMAP: Port d...
535
  unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
536
  {
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
537
  	unsigned int l;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
538
539
540
  	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...
541
542
  		return 0;
  	}
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
543
  	l = __raw_readl(timer->irq_stat);
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
544
545
  
  	return l;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
546
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
547
  EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
548

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
549
  int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
550
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
551
552
  	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
  		return -EINVAL;
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
553
  	__omap_dm_timer_write_status(timer, value);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
554
555
  	/* Save the context */
  	timer->context.tisr = value;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
556
  	return 0;
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
557
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
558
  EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
559

77900a2fc   Timo Teras   ARM: OMAP: Port d...
560
  unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
561
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
562
563
564
  	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...
565
566
  		return 0;
  	}
ee17f1147   Tony Lindgren   ARM: OMAP: Add su...
567
  	return __omap_dm_timer_read_counter(timer, timer->posted);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
568
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
569
  EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
570

ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
571
  int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
83379c81f   Timo Teras   ARM: OMAP: Update...
572
  {
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
573
574
575
576
  	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...
577
  	}
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
578
  	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
579
580
581
  
  	/* Save the context */
  	timer->context.tcrr = value;
ab4eb8b09   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
582
  	return 0;
83379c81f   Timo Teras   ARM: OMAP: Update...
583
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
584
  EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
83379c81f   Timo Teras   ARM: OMAP: Update...
585

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

3392cdd33   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
590
  	list_for_each_entry(timer, &omap_timer_list, node) {
ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
591
  		if (!timer->reserved)
12583a70a   Timo Teras   ARM: OMAP: Add en...
592
  			continue;
77900a2fc   Timo Teras   ARM: OMAP: Port d...
593
  		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
594
  		    OMAP_TIMER_CTRL_ST) {
77900a2fc   Timo Teras   ARM: OMAP: Port d...
595
  			return 1;
fa4bb626c   Timo Teras   ARM: OMAP: Use GP...
596
  		}
77900a2fc   Timo Teras   ARM: OMAP: Port d...
597
598
599
  	}
  	return 0;
  }
6c366e329   Timo Kokkonen   ARM: OMAP: Export...
600
  EXPORT_SYMBOL_GPL(omap_dm_timers_active);
92105bb70   Tony Lindgren   [ARM] 2887/1: OMA...
601

df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
  /**
   * 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)
  {
  	int ret;
  	unsigned long flags;
  	struct omap_dm_timer *timer;
  	struct resource *mem, *irq, *ioarea;
  	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
  
  	if (!pdata) {
  		dev_err(&pdev->dev, "%s: no platform data.
  ", __func__);
  		return -ENODEV;
  	}
  
  	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  	if (unlikely(!irq)) {
  		dev_err(&pdev->dev, "%s: no IRQ resource.
  ", __func__);
  		return -ENODEV;
  	}
  
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (unlikely(!mem)) {
  		dev_err(&pdev->dev, "%s: no memory resource.
  ", __func__);
  		return -ENODEV;
  	}
  
  	ioarea = request_mem_region(mem->start, resource_size(mem),
  			pdev->name);
  	if (!ioarea) {
  		dev_err(&pdev->dev, "%s: region already claimed.
  ", __func__);
  		return -EBUSY;
  	}
  
  	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
  	if (!timer) {
  		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.
  ",
  			__func__);
  		ret = -ENOMEM;
  		goto err_free_ioregion;
  	}
  
  	timer->io_base = ioremap(mem->start, resource_size(mem));
  	if (!timer->io_base) {
  		dev_err(&pdev->dev, "%s: ioremap failed.
  ", __func__);
  		ret = -ENOMEM;
  		goto err_free_mem;
  	}
  
  	timer->id = pdev->id;
506c079b8   Jon Hunter   ARM: OMAP3+: Impl...
663
  	timer->errata = pdata->timer_errata;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
664
  	timer->irq = irq->start;
0dad9faea   Tony Lindgren   ARM: OMAP: dmtime...
665
  	timer->reserved = pdata->reserved;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
666
  	timer->pdev = pdev;
b481113a8   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
667
668
  	timer->loses_context = pdata->loses_context;
  	timer->get_context_loss_count = pdata->get_context_loss_count;
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
669

ffe07ceae   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
670
671
672
673
674
  	/* Skip pm_runtime_enable for OMAP1 */
  	if (!pdata->needs_manual_reset) {
  		pm_runtime_enable(&pdev->dev);
  		pm_runtime_irq_safe(&pdev->dev);
  	}
0dad9faea   Tony Lindgren   ARM: OMAP: dmtime...
675
676
677
678
679
  	if (!timer->reserved) {
  		pm_runtime_get_sync(&pdev->dev);
  		__omap_dm_timer_init_regs(timer);
  		pm_runtime_put(&pdev->dev);
  	}
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
  	/* 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);
  
  	dev_dbg(&pdev->dev, "Device Probed.
  ");
  
  	return 0;
  
  err_free_mem:
  	kfree(timer);
  
  err_free_ioregion:
  	release_mem_region(mem->start, resource_size(mem));
  
  	return ret;
  }
  
  /**
   * 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);
  			kfree(timer);
  			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 __...
728
  	.remove = __devexit_p(omap_dm_timer_remove),
df28472a1   Tarun Kanti DebBarma   ARM: OMAP: dmtime...
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  	.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");