Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * linux/arch/arm/plat-omap/dmtimer.c
  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 * dmtimer adaptation to platform_driver.
 11 *
 12 * Copyright (C) 2005 Nokia Corporation
 13 * OMAP2 support by Juha Yrjola
 14 * API improvements and OMAP2 clock framework support by Timo Teras
 15 *
 16 * Copyright (C) 2009 Texas Instruments
 17 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
 18 *
 19 * This program is free software; you can redistribute it and/or modify it
 20 * under the terms of the GNU General Public License as published by the
 21 * Free Software Foundation; either version 2 of the License, or (at your
 22 * option) any later version.
 23 *
 24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 27 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32 *
 33 * You should have received a copy of the  GNU General Public License along
 34 * with this program; if not, write  to the Free Software Foundation, Inc.,
 35 * 675 Mass Ave, Cambridge, MA 02139, USA.
 36 */
 37
 
 
 38#include <linux/module.h>
 39#include <linux/io.h>
 40#include <linux/slab.h>
 41#include <linux/err.h>
 42#include <linux/pm_runtime.h>
 
 
 
 
 43
 44#include <plat/dmtimer.h>
 45
 46#include <mach/hardware.h>
 47
 48static LIST_HEAD(omap_timer_list);
 49static DEFINE_SPINLOCK(dm_timer_lock);
 50
 
 
 
 
 
 
 
 51/**
 52 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
 53 * @timer:      timer pointer over which read operation to perform
 54 * @reg:        lowest byte holds the register offset
 55 *
 56 * The posted mode bit is encoded in reg. Note that in posted mode write
 57 * pending bit must be checked. Otherwise a read of a non completed write
 58 * will produce an error.
 59 */
 60static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
 61{
 62	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
 63	return __omap_dm_timer_read(timer, reg, timer->posted);
 64}
 65
 66/**
 67 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
 68 * @timer:      timer pointer over which write operation is to perform
 69 * @reg:        lowest byte holds the register offset
 70 * @value:      data to write into the register
 71 *
 72 * The posted mode bit is encoded in reg. Note that in posted mode the write
 73 * pending bit must be checked. Otherwise a write on a register which has a
 74 * pending write will be lost.
 75 */
 76static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
 77						u32 value)
 78{
 79	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
 80	__omap_dm_timer_write(timer, reg, value, timer->posted);
 81}
 82
 83static void omap_timer_restore_context(struct omap_dm_timer *timer)
 84{
 85	if (timer->revision == 1)
 86		__raw_writel(timer->context.tistat, timer->sys_stat);
 87
 88	__raw_writel(timer->context.tisr, timer->irq_stat);
 89	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
 90				timer->context.twer);
 91	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
 92				timer->context.tcrr);
 93	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
 94				timer->context.tldr);
 95	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
 96				timer->context.tmar);
 97	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
 98				timer->context.tsicr);
 99	__raw_writel(timer->context.tier, timer->irq_ena);
100	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
101				timer->context.tclr);
102}
103
104static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
105{
106	int c;
107
108	if (!timer->sys_stat)
109		return;
110
111	c = 0;
112	while (!(__raw_readl(timer->sys_stat) & 1)) {
113		c++;
114		if (c > 100000) {
115			printk(KERN_ERR "Timer failed to reset\n");
116			return;
117		}
 
 
 
118	}
 
 
 
 
 
 
 
 
 
119}
120
121static void omap_dm_timer_reset(struct omap_dm_timer *timer)
122{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123	omap_dm_timer_enable(timer);
124	if (timer->pdev->id != 1) {
125		omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
126		omap_dm_timer_wait_for_reset(timer);
 
 
 
 
127	}
128
129	__omap_dm_timer_reset(timer, 0, 0);
130	omap_dm_timer_disable(timer);
131	timer->posted = 1;
 
 
 
 
 
132}
133
134int omap_dm_timer_prepare(struct omap_dm_timer *timer)
135{
136	struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
137	int ret;
138
139	timer->fclk = clk_get(&timer->pdev->dev, "fck");
140	if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
141		timer->fclk = NULL;
142		dev_err(&timer->pdev->dev, ": No fclk handle.\n");
143		return -EINVAL;
144	}
145
146	if (pdata->needs_manual_reset)
147		omap_dm_timer_reset(timer);
 
 
148
149	ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
150
151	timer->posted = 1;
152	return ret;
153}
154
155struct omap_dm_timer *omap_dm_timer_request(void)
156{
157	struct omap_dm_timer *timer = NULL, *t;
 
158	unsigned long flags;
159	int ret = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
161	spin_lock_irqsave(&dm_timer_lock, flags);
162	list_for_each_entry(t, &omap_timer_list, node) {
163		if (t->reserved)
164			continue;
165
166		timer = t;
167		timer->reserved = 1;
168		break;
169	}
170
171	if (timer) {
172		ret = omap_dm_timer_prepare(timer);
173		if (ret) {
174			timer->reserved = 0;
175			timer = NULL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176		}
177	}
 
178	spin_unlock_irqrestore(&dm_timer_lock, flags);
179
 
 
 
 
 
180	if (!timer)
181		pr_debug("%s: timer request failed!\n", __func__);
182
183	return timer;
184}
 
 
 
 
 
185EXPORT_SYMBOL_GPL(omap_dm_timer_request);
186
187struct omap_dm_timer *omap_dm_timer_request_specific(int id)
188{
189	struct omap_dm_timer *timer = NULL, *t;
190	unsigned long flags;
191	int ret = 0;
192
193	spin_lock_irqsave(&dm_timer_lock, flags);
194	list_for_each_entry(t, &omap_timer_list, node) {
195		if (t->pdev->id == id && !t->reserved) {
196			timer = t;
197			timer->reserved = 1;
198			break;
199		}
200	}
201
202	if (timer) {
203		ret = omap_dm_timer_prepare(timer);
204		if (ret) {
205			timer->reserved = 0;
206			timer = NULL;
207		}
208	}
209	spin_unlock_irqrestore(&dm_timer_lock, flags);
210
211	if (!timer)
212		pr_debug("%s: timer%d request failed!\n", __func__, id);
 
 
 
 
 
 
 
 
 
 
 
 
213
214	return timer;
 
 
 
 
 
 
 
 
 
 
 
 
215}
216EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
217
218int omap_dm_timer_free(struct omap_dm_timer *timer)
219{
220	if (unlikely(!timer))
221		return -EINVAL;
222
223	clk_put(timer->fclk);
224
225	WARN_ON(!timer->reserved);
226	timer->reserved = 0;
227	return 0;
228}
229EXPORT_SYMBOL_GPL(omap_dm_timer_free);
230
231void omap_dm_timer_enable(struct omap_dm_timer *timer)
232{
 
 
233	pm_runtime_get_sync(&timer->pdev->dev);
 
 
 
 
 
 
 
 
 
 
 
 
234}
235EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
236
237void omap_dm_timer_disable(struct omap_dm_timer *timer)
238{
239	pm_runtime_put_sync(&timer->pdev->dev);
240}
241EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
242
243int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
244{
245	if (timer)
246		return timer->irq;
247	return -EINVAL;
248}
249EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
250
251#if defined(CONFIG_ARCH_OMAP1)
252
253/**
254 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
255 * @inputmask: current value of idlect mask
256 */
257__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
258{
259	int i = 0;
260	struct omap_dm_timer *timer = NULL;
261	unsigned long flags;
262
263	/* If ARMXOR cannot be idled this function call is unnecessary */
264	if (!(inputmask & (1 << 1)))
265		return inputmask;
266
267	/* If any active timer is using ARMXOR return modified mask */
268	spin_lock_irqsave(&dm_timer_lock, flags);
269	list_for_each_entry(timer, &omap_timer_list, node) {
270		u32 l;
271
272		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
273		if (l & OMAP_TIMER_CTRL_ST) {
274			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
275				inputmask &= ~(1 << 1);
276			else
277				inputmask &= ~(1 << 2);
278		}
279		i++;
280	}
281	spin_unlock_irqrestore(&dm_timer_lock, flags);
282
283	return inputmask;
284}
285EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
286
287#else
288
289struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
290{
291	if (timer)
292		return timer->fclk;
293	return NULL;
294}
295EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
296
297__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
298{
299	BUG();
300
301	return 0;
302}
303EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
304
305#endif
306
307int omap_dm_timer_trigger(struct omap_dm_timer *timer)
308{
309	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
310		pr_err("%s: timer not available or enabled.\n", __func__);
311		return -EINVAL;
312	}
313
314	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
315	return 0;
316}
317EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
318
319int omap_dm_timer_start(struct omap_dm_timer *timer)
320{
321	u32 l;
322
323	if (unlikely(!timer))
324		return -EINVAL;
325
326	omap_dm_timer_enable(timer);
327
328	if (timer->loses_context) {
329		u32 ctx_loss_cnt_after =
330			timer->get_context_loss_count(&timer->pdev->dev);
331		if (ctx_loss_cnt_after != timer->ctx_loss_count)
332			omap_timer_restore_context(timer);
333	}
334
335	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
336	if (!(l & OMAP_TIMER_CTRL_ST)) {
337		l |= OMAP_TIMER_CTRL_ST;
338		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
339	}
340
341	/* Save the context */
342	timer->context.tclr = l;
343	return 0;
344}
345EXPORT_SYMBOL_GPL(omap_dm_timer_start);
346
347int omap_dm_timer_stop(struct omap_dm_timer *timer)
348{
349	unsigned long rate = 0;
350	struct dmtimer_platform_data *pdata;
351
352	if (unlikely(!timer))
353		return -EINVAL;
354
355	pdata = timer->pdev->dev.platform_data;
356	if (!pdata->needs_manual_reset)
357		rate = clk_get_rate(timer->fclk);
358
359	__omap_dm_timer_stop(timer, timer->posted, rate);
360
361	if (timer->loses_context && timer->get_context_loss_count)
362		timer->ctx_loss_count =
363			timer->get_context_loss_count(&timer->pdev->dev);
364
365	/*
366	 * Since the register values are computed and written within
367	 * __omap_dm_timer_stop, we need to use read to retrieve the
368	 * context.
369	 */
370	timer->context.tclr =
371			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
372	timer->context.tisr = __raw_readl(timer->irq_stat);
373	omap_dm_timer_disable(timer);
374	return 0;
375}
376EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
377
378int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
379{
380	int ret;
 
 
381	struct dmtimer_platform_data *pdata;
382
383	if (unlikely(!timer))
384		return -EINVAL;
385
386	pdata = timer->pdev->dev.platform_data;
387
388	if (source < 0 || source >= 3)
389		return -EINVAL;
390
391	ret = pdata->set_timer_src(timer->pdev, source);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
393	return ret;
394}
395EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
396
397int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
398			    unsigned int load)
399{
400	u32 l;
401
402	if (unlikely(!timer))
403		return -EINVAL;
404
405	omap_dm_timer_enable(timer);
406	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
407	if (autoreload)
408		l |= OMAP_TIMER_CTRL_AR;
409	else
410		l &= ~OMAP_TIMER_CTRL_AR;
411	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
412	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
413
414	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
415	/* Save the context */
416	timer->context.tclr = l;
417	timer->context.tldr = load;
418	omap_dm_timer_disable(timer);
419	return 0;
420}
421EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
422
423/* Optimized set_load which removes costly spin wait in timer_start */
424int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
425                            unsigned int load)
426{
427	u32 l;
428
429	if (unlikely(!timer))
430		return -EINVAL;
431
432	omap_dm_timer_enable(timer);
433
434	if (timer->loses_context) {
435		u32 ctx_loss_cnt_after =
436			timer->get_context_loss_count(&timer->pdev->dev);
437		if (ctx_loss_cnt_after != timer->ctx_loss_count)
438			omap_timer_restore_context(timer);
439	}
440
441	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
442	if (autoreload) {
443		l |= OMAP_TIMER_CTRL_AR;
444		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
445	} else {
446		l &= ~OMAP_TIMER_CTRL_AR;
447	}
448	l |= OMAP_TIMER_CTRL_ST;
449
450	__omap_dm_timer_load_start(timer, l, load, timer->posted);
451
452	/* Save the context */
453	timer->context.tclr = l;
454	timer->context.tldr = load;
455	timer->context.tcrr = load;
456	return 0;
457}
458EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
459
460int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
461			     unsigned int match)
462{
463	u32 l;
464
465	if (unlikely(!timer))
466		return -EINVAL;
467
468	omap_dm_timer_enable(timer);
469	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
470	if (enable)
471		l |= OMAP_TIMER_CTRL_CE;
472	else
473		l &= ~OMAP_TIMER_CTRL_CE;
474	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
475	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
 
476
477	/* Save the context */
478	timer->context.tclr = l;
479	timer->context.tmar = match;
480	omap_dm_timer_disable(timer);
481	return 0;
482}
483EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
484
485int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
486			   int toggle, int trigger)
487{
488	u32 l;
489
490	if (unlikely(!timer))
491		return -EINVAL;
492
493	omap_dm_timer_enable(timer);
494	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
495	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
496	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
497	if (def_on)
498		l |= OMAP_TIMER_CTRL_SCPWM;
499	if (toggle)
500		l |= OMAP_TIMER_CTRL_PT;
501	l |= trigger << 10;
502	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
503
504	/* Save the context */
505	timer->context.tclr = l;
506	omap_dm_timer_disable(timer);
507	return 0;
508}
509EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
510
511int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
512{
513	u32 l;
514
515	if (unlikely(!timer))
516		return -EINVAL;
517
518	omap_dm_timer_enable(timer);
519	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
520	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
521	if (prescaler >= 0x00 && prescaler <= 0x07) {
522		l |= OMAP_TIMER_CTRL_PRE;
523		l |= prescaler << 2;
524	}
525	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
526
527	/* Save the context */
528	timer->context.tclr = l;
529	omap_dm_timer_disable(timer);
530	return 0;
531}
532EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
533
534int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
535				  unsigned int value)
536{
537	if (unlikely(!timer))
538		return -EINVAL;
539
540	omap_dm_timer_enable(timer);
541	__omap_dm_timer_int_enable(timer, value);
542
543	/* Save the context */
544	timer->context.tier = value;
545	timer->context.twer = value;
546	omap_dm_timer_disable(timer);
547	return 0;
548}
549EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
550
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
552{
553	unsigned int l;
554
555	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
556		pr_err("%s: timer not available or enabled.\n", __func__);
557		return 0;
558	}
559
560	l = __raw_readl(timer->irq_stat);
561
562	return l;
563}
564EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
565
566int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
567{
568	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
569		return -EINVAL;
570
571	__omap_dm_timer_write_status(timer, value);
572	/* Save the context */
573	timer->context.tisr = value;
574	return 0;
575}
576EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
577
578unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
579{
580	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
581		pr_err("%s: timer not iavailable or enabled.\n", __func__);
582		return 0;
583	}
584
585	return __omap_dm_timer_read_counter(timer, timer->posted);
586}
587EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
588
589int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
590{
591	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
592		pr_err("%s: timer not available or enabled.\n", __func__);
593		return -EINVAL;
594	}
595
596	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
597
598	/* Save the context */
599	timer->context.tcrr = value;
600	return 0;
601}
602EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
603
604int omap_dm_timers_active(void)
605{
606	struct omap_dm_timer *timer;
607
608	list_for_each_entry(timer, &omap_timer_list, node) {
609		if (!timer->reserved)
610			continue;
611
612		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
613		    OMAP_TIMER_CTRL_ST) {
614			return 1;
615		}
616	}
617	return 0;
618}
619EXPORT_SYMBOL_GPL(omap_dm_timers_active);
620
 
 
621/**
622 * omap_dm_timer_probe - probe function called for every registered device
623 * @pdev:	pointer to current timer platform device
624 *
625 * Called by driver framework at the end of device registration for all
626 * timer devices.
627 */
628static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
629{
630	int ret;
631	unsigned long flags;
632	struct omap_dm_timer *timer;
633	struct resource *mem, *irq, *ioarea;
634	struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
 
 
 
 
 
 
635
636	if (!pdata) {
637		dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
638		return -ENODEV;
639	}
640
641	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
642	if (unlikely(!irq)) {
643		dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
644		return -ENODEV;
645	}
646
647	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
648	if (unlikely(!mem)) {
649		dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
650		return -ENODEV;
651	}
652
653	ioarea = request_mem_region(mem->start, resource_size(mem),
654			pdev->name);
655	if (!ioarea) {
656		dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
657		return -EBUSY;
658	}
659
660	timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
661	if (!timer) {
662		dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
663			__func__);
664		ret = -ENOMEM;
665		goto err_free_ioregion;
666	}
667
668	timer->io_base = ioremap(mem->start, resource_size(mem));
669	if (!timer->io_base) {
670		dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
671		ret = -ENOMEM;
672		goto err_free_mem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673	}
674
675	timer->id = pdev->id;
 
 
676	timer->irq = irq->start;
677	timer->reserved = pdata->reserved;
678	timer->pdev = pdev;
679	timer->loses_context = pdata->loses_context;
680	timer->get_context_loss_count = pdata->get_context_loss_count;
681
682	/* Skip pm_runtime_enable for OMAP1 */
683	if (!pdata->needs_manual_reset) {
684		pm_runtime_enable(&pdev->dev);
685		pm_runtime_irq_safe(&pdev->dev);
686	}
687
688	if (!timer->reserved) {
689		pm_runtime_get_sync(&pdev->dev);
 
 
 
 
 
690		__omap_dm_timer_init_regs(timer);
691		pm_runtime_put(&pdev->dev);
692	}
693
694	/* add the timer element to the list */
695	spin_lock_irqsave(&dm_timer_lock, flags);
696	list_add_tail(&timer->node, &omap_timer_list);
697	spin_unlock_irqrestore(&dm_timer_lock, flags);
698
699	dev_dbg(&pdev->dev, "Device Probed.\n");
700
701	return 0;
702
703err_free_mem:
704	kfree(timer);
705
706err_free_ioregion:
707	release_mem_region(mem->start, resource_size(mem));
708
709	return ret;
710}
711
712/**
713 * omap_dm_timer_remove - cleanup a registered timer device
714 * @pdev:	pointer to current timer platform device
715 *
716 * Called by driver framework whenever a timer device is unregistered.
717 * In addition to freeing platform resources it also deletes the timer
718 * entry from the local list.
719 */
720static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
721{
722	struct omap_dm_timer *timer;
723	unsigned long flags;
724	int ret = -EINVAL;
725
726	spin_lock_irqsave(&dm_timer_lock, flags);
727	list_for_each_entry(timer, &omap_timer_list, node)
728		if (timer->pdev->id == pdev->id) {
 
729			list_del(&timer->node);
730			kfree(timer);
731			ret = 0;
732			break;
733		}
734	spin_unlock_irqrestore(&dm_timer_lock, flags);
735
 
 
736	return ret;
737}
738
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739static struct platform_driver omap_dm_timer_driver = {
740	.probe  = omap_dm_timer_probe,
741	.remove = __devexit_p(omap_dm_timer_remove),
742	.driver = {
743		.name   = "omap_timer",
 
744	},
745};
746
747static int __init omap_dm_timer_driver_init(void)
748{
749	return platform_driver_register(&omap_dm_timer_driver);
750}
751
752static void __exit omap_dm_timer_driver_exit(void)
753{
754	platform_driver_unregister(&omap_dm_timer_driver);
755}
756
757early_platform_init("earlytimer", &omap_dm_timer_driver);
758module_init(omap_dm_timer_driver_init);
759module_exit(omap_dm_timer_driver_exit);
760
761MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
762MODULE_LICENSE("GPL");
763MODULE_ALIAS("platform:" DRIVER_NAME);
764MODULE_AUTHOR("Texas Instruments Inc");
v4.6
   1/*
   2 * linux/arch/arm/plat-omap/dmtimer.c
   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 * dmtimer adaptation to platform_driver.
  11 *
  12 * Copyright (C) 2005 Nokia Corporation
  13 * OMAP2 support by Juha Yrjola
  14 * API improvements and OMAP2 clock framework support by Timo Teras
  15 *
  16 * Copyright (C) 2009 Texas Instruments
  17 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  18 *
  19 * This program is free software; you can redistribute it and/or modify it
  20 * under the terms of the GNU General Public License as published by the
  21 * Free Software Foundation; either version 2 of the License, or (at your
  22 * option) any later version.
  23 *
  24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  27 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32 *
  33 * You should have received a copy of the  GNU General Public License along
  34 * with this program; if not, write  to the Free Software Foundation, Inc.,
  35 * 675 Mass Ave, Cambridge, MA 02139, USA.
  36 */
  37
  38#include <linux/clk.h>
  39#include <linux/clk-provider.h>
  40#include <linux/module.h>
  41#include <linux/io.h>
  42#include <linux/device.h>
  43#include <linux/err.h>
  44#include <linux/pm_runtime.h>
  45#include <linux/of.h>
  46#include <linux/of_device.h>
  47#include <linux/platform_device.h>
  48#include <linux/platform_data/dmtimer-omap.h>
  49
  50#include <plat/dmtimer.h>
  51
  52static u32 omap_reserved_systimers;
 
  53static LIST_HEAD(omap_timer_list);
  54static DEFINE_SPINLOCK(dm_timer_lock);
  55
  56enum {
  57	REQUEST_ANY = 0,
  58	REQUEST_BY_ID,
  59	REQUEST_BY_CAP,
  60	REQUEST_BY_NODE,
  61};
  62
  63/**
  64 * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode
  65 * @timer:      timer pointer over which read operation to perform
  66 * @reg:        lowest byte holds the register offset
  67 *
  68 * The posted mode bit is encoded in reg. Note that in posted mode write
  69 * pending bit must be checked. Otherwise a read of a non completed write
  70 * will produce an error.
  71 */
  72static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
  73{
  74	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  75	return __omap_dm_timer_read(timer, reg, timer->posted);
  76}
  77
  78/**
  79 * omap_dm_timer_write_reg - write timer registers in posted and non-posted mode
  80 * @timer:      timer pointer over which write operation is to perform
  81 * @reg:        lowest byte holds the register offset
  82 * @value:      data to write into the register
  83 *
  84 * The posted mode bit is encoded in reg. Note that in posted mode the write
  85 * pending bit must be checked. Otherwise a write on a register which has a
  86 * pending write will be lost.
  87 */
  88static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
  89						u32 value)
  90{
  91	WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
  92	__omap_dm_timer_write(timer, reg, value, timer->posted);
  93}
  94
  95static void omap_timer_restore_context(struct omap_dm_timer *timer)
  96{
 
 
 
 
  97	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
  98				timer->context.twer);
  99	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
 100				timer->context.tcrr);
 101	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
 102				timer->context.tldr);
 103	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
 104				timer->context.tmar);
 105	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
 106				timer->context.tsicr);
 107	writel_relaxed(timer->context.tier, timer->irq_ena);
 108	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
 109				timer->context.tclr);
 110}
 111
 112static int omap_dm_timer_reset(struct omap_dm_timer *timer)
 113{
 114	u32 l, timeout = 100000;
 115
 116	if (timer->revision != 1)
 117		return -EINVAL;
 118
 119	omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
 120
 121	do {
 122		l = __omap_dm_timer_read(timer,
 123					 OMAP_TIMER_V1_SYS_STAT_OFFSET, 0);
 124	} while (!l && timeout--);
 125
 126	if (!timeout) {
 127		dev_err(&timer->pdev->dev, "Timer failed to reset\n");
 128		return -ETIMEDOUT;
 129	}
 130
 131	/* Configure timer for smart-idle mode */
 132	l = __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
 133	l |= 0x2 << 0x3;
 134	__omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, l, 0);
 135
 136	timer->posted = 0;
 137
 138	return 0;
 139}
 140
 141static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
 142{
 143	int ret;
 144	struct clk *parent;
 145
 146	/*
 147	 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
 148	 * do not call clk_get() for these devices.
 149	 */
 150	if (!timer->fclk)
 151		return -ENODEV;
 152
 153	parent = clk_get(&timer->pdev->dev, NULL);
 154	if (IS_ERR(parent))
 155		return -ENODEV;
 156
 157	ret = clk_set_parent(timer->fclk, parent);
 158	if (ret < 0)
 159		pr_err("%s: failed to set parent\n", __func__);
 160
 161	clk_put(parent);
 162
 163	return ret;
 164}
 165
 166static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 167{
 168	int rc;
 169
 170	/*
 171	 * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
 172	 * do not call clk_get() for these devices.
 173	 */
 174	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
 175		timer->fclk = clk_get(&timer->pdev->dev, "fck");
 176		if (WARN_ON_ONCE(IS_ERR(timer->fclk))) {
 177			dev_err(&timer->pdev->dev, ": No fclk handle.\n");
 178			return -EINVAL;
 179		}
 180	}
 181
 182	omap_dm_timer_enable(timer);
 183
 184	if (timer->capability & OMAP_TIMER_NEEDS_RESET) {
 185		rc = omap_dm_timer_reset(timer);
 186		if (rc) {
 187			omap_dm_timer_disable(timer);
 188			return rc;
 189		}
 190	}
 191
 192	__omap_dm_timer_enable_posted(timer);
 193	omap_dm_timer_disable(timer);
 194
 195	rc = omap_dm_timer_of_set_source(timer);
 196	if (rc == -ENODEV)
 197		return omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
 198
 199	return rc;
 200}
 201
 202static inline u32 omap_dm_timer_reserved_systimer(int id)
 203{
 204	return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
 205}
 
 
 
 
 
 
 
 206
 207int omap_dm_timer_reserve_systimer(int id)
 208{
 209	if (omap_dm_timer_reserved_systimer(id))
 210		return -ENODEV;
 211
 212	omap_reserved_systimers |= (1 << (id - 1));
 213
 214	return 0;
 
 215}
 216
 217static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data)
 218{
 219	struct omap_dm_timer *timer = NULL, *t;
 220	struct device_node *np = NULL;
 221	unsigned long flags;
 222	u32 cap = 0;
 223	int id = 0;
 224
 225	switch (req_type) {
 226	case REQUEST_BY_ID:
 227		id = *(int *)data;
 228		break;
 229	case REQUEST_BY_CAP:
 230		cap = *(u32 *)data;
 231		break;
 232	case REQUEST_BY_NODE:
 233		np = (struct device_node *)data;
 234		break;
 235	default:
 236		/* REQUEST_ANY */
 237		break;
 238	}
 239
 240	spin_lock_irqsave(&dm_timer_lock, flags);
 241	list_for_each_entry(t, &omap_timer_list, node) {
 242		if (t->reserved)
 243			continue;
 244
 245		switch (req_type) {
 246		case REQUEST_BY_ID:
 247			if (id == t->pdev->id) {
 248				timer = t;
 249				timer->reserved = 1;
 250				goto found;
 251			}
 252			break;
 253		case REQUEST_BY_CAP:
 254			if (cap == (t->capability & cap)) {
 255				/*
 256				 * If timer is not NULL, we have already found
 257				 * one timer but it was not an exact match
 258				 * because it had more capabilites that what
 259				 * was required. Therefore, unreserve the last
 260				 * timer found and see if this one is a better
 261				 * match.
 262				 */
 263				if (timer)
 264					timer->reserved = 0;
 265				timer = t;
 266				timer->reserved = 1;
 267
 268				/* Exit loop early if we find an exact match */
 269				if (t->capability == cap)
 270					goto found;
 271			}
 272			break;
 273		case REQUEST_BY_NODE:
 274			if (np == t->pdev->dev.of_node) {
 275				timer = t;
 276				timer->reserved = 1;
 277				goto found;
 278			}
 279			break;
 280		default:
 281			/* REQUEST_ANY */
 282			timer = t;
 283			timer->reserved = 1;
 284			goto found;
 285		}
 286	}
 287found:
 288	spin_unlock_irqrestore(&dm_timer_lock, flags);
 289
 290	if (timer && omap_dm_timer_prepare(timer)) {
 291		timer->reserved = 0;
 292		timer = NULL;
 293	}
 294
 295	if (!timer)
 296		pr_debug("%s: timer request failed!\n", __func__);
 297
 298	return timer;
 299}
 300
 301struct omap_dm_timer *omap_dm_timer_request(void)
 302{
 303	return _omap_dm_timer_request(REQUEST_ANY, NULL);
 304}
 305EXPORT_SYMBOL_GPL(omap_dm_timer_request);
 306
 307struct omap_dm_timer *omap_dm_timer_request_specific(int id)
 308{
 309	/* Requesting timer by ID is not supported when device tree is used */
 310	if (of_have_populated_dt()) {
 311		pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n",
 312			__func__);
 313		return NULL;
 
 
 
 
 
 
 314	}
 315
 316	return _omap_dm_timer_request(REQUEST_BY_ID, &id);
 317}
 318EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
 
 
 
 
 
 319
 320/**
 321 * omap_dm_timer_request_by_cap - Request a timer by capability
 322 * @cap:	Bit mask of capabilities to match
 323 *
 324 * Find a timer based upon capabilities bit mask. Callers of this function
 325 * should use the definitions found in the plat/dmtimer.h file under the
 326 * comment "timer capabilities used in hwmod database". Returns pointer to
 327 * timer handle on success and a NULL pointer on failure.
 328 */
 329struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
 330{
 331	return _omap_dm_timer_request(REQUEST_BY_CAP, &cap);
 332}
 333EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
 334
 335/**
 336 * omap_dm_timer_request_by_node - Request a timer by device-tree node
 337 * @np:		Pointer to device-tree timer node
 338 *
 339 * Request a timer based upon a device node pointer. Returns pointer to
 340 * timer handle on success and a NULL pointer on failure.
 341 */
 342struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np)
 343{
 344	if (!np)
 345		return NULL;
 346
 347	return _omap_dm_timer_request(REQUEST_BY_NODE, np);
 348}
 349EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node);
 350
 351int omap_dm_timer_free(struct omap_dm_timer *timer)
 352{
 353	if (unlikely(!timer))
 354		return -EINVAL;
 355
 356	clk_put(timer->fclk);
 357
 358	WARN_ON(!timer->reserved);
 359	timer->reserved = 0;
 360	return 0;
 361}
 362EXPORT_SYMBOL_GPL(omap_dm_timer_free);
 363
 364void omap_dm_timer_enable(struct omap_dm_timer *timer)
 365{
 366	int c;
 367
 368	pm_runtime_get_sync(&timer->pdev->dev);
 369
 370	if (!(timer->capability & OMAP_TIMER_ALWON)) {
 371		if (timer->get_context_loss_count) {
 372			c = timer->get_context_loss_count(&timer->pdev->dev);
 373			if (c != timer->ctx_loss_count) {
 374				omap_timer_restore_context(timer);
 375				timer->ctx_loss_count = c;
 376			}
 377		} else {
 378			omap_timer_restore_context(timer);
 379		}
 380	}
 381}
 382EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 383
 384void omap_dm_timer_disable(struct omap_dm_timer *timer)
 385{
 386	pm_runtime_put_sync(&timer->pdev->dev);
 387}
 388EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 389
 390int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
 391{
 392	if (timer)
 393		return timer->irq;
 394	return -EINVAL;
 395}
 396EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
 397
 398#if defined(CONFIG_ARCH_OMAP1)
 399#include <mach/hardware.h>
 400/**
 401 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
 402 * @inputmask: current value of idlect mask
 403 */
 404__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 405{
 406	int i = 0;
 407	struct omap_dm_timer *timer = NULL;
 408	unsigned long flags;
 409
 410	/* If ARMXOR cannot be idled this function call is unnecessary */
 411	if (!(inputmask & (1 << 1)))
 412		return inputmask;
 413
 414	/* If any active timer is using ARMXOR return modified mask */
 415	spin_lock_irqsave(&dm_timer_lock, flags);
 416	list_for_each_entry(timer, &omap_timer_list, node) {
 417		u32 l;
 418
 419		l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 420		if (l & OMAP_TIMER_CTRL_ST) {
 421			if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
 422				inputmask &= ~(1 << 1);
 423			else
 424				inputmask &= ~(1 << 2);
 425		}
 426		i++;
 427	}
 428	spin_unlock_irqrestore(&dm_timer_lock, flags);
 429
 430	return inputmask;
 431}
 432EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 433
 434#else
 435
 436struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 437{
 438	if (timer && !IS_ERR(timer->fclk))
 439		return timer->fclk;
 440	return NULL;
 441}
 442EXPORT_SYMBOL_GPL(omap_dm_timer_get_fclk);
 443
 444__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask)
 445{
 446	BUG();
 447
 448	return 0;
 449}
 450EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 451
 452#endif
 453
 454int omap_dm_timer_trigger(struct omap_dm_timer *timer)
 455{
 456	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
 457		pr_err("%s: timer not available or enabled.\n", __func__);
 458		return -EINVAL;
 459	}
 460
 461	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
 462	return 0;
 463}
 464EXPORT_SYMBOL_GPL(omap_dm_timer_trigger);
 465
 466int omap_dm_timer_start(struct omap_dm_timer *timer)
 467{
 468	u32 l;
 469
 470	if (unlikely(!timer))
 471		return -EINVAL;
 472
 473	omap_dm_timer_enable(timer);
 474
 
 
 
 
 
 
 
 475	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 476	if (!(l & OMAP_TIMER_CTRL_ST)) {
 477		l |= OMAP_TIMER_CTRL_ST;
 478		omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 479	}
 480
 481	/* Save the context */
 482	timer->context.tclr = l;
 483	return 0;
 484}
 485EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 486
 487int omap_dm_timer_stop(struct omap_dm_timer *timer)
 488{
 489	unsigned long rate = 0;
 
 490
 491	if (unlikely(!timer))
 492		return -EINVAL;
 493
 494	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
 
 495		rate = clk_get_rate(timer->fclk);
 496
 497	__omap_dm_timer_stop(timer, timer->posted, rate);
 498
 
 
 
 
 499	/*
 500	 * Since the register values are computed and written within
 501	 * __omap_dm_timer_stop, we need to use read to retrieve the
 502	 * context.
 503	 */
 504	timer->context.tclr =
 505			omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 
 506	omap_dm_timer_disable(timer);
 507	return 0;
 508}
 509EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 510
 511int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 512{
 513	int ret;
 514	char *parent_name = NULL;
 515	struct clk *parent;
 516	struct dmtimer_platform_data *pdata;
 517
 518	if (unlikely(!timer))
 519		return -EINVAL;
 520
 521	pdata = timer->pdev->dev.platform_data;
 522
 523	if (source < 0 || source >= 3)
 524		return -EINVAL;
 525
 526	/*
 527	 * FIXME: Used for OMAP1 devices only because they do not currently
 528	 * use the clock framework to set the parent clock. To be removed
 529	 * once OMAP1 migrated to using clock framework for dmtimers
 530	 */
 531	if (pdata && pdata->set_timer_src)
 532		return pdata->set_timer_src(timer->pdev, source);
 533
 534	if (IS_ERR(timer->fclk))
 535		return -EINVAL;
 536
 537#if defined(CONFIG_COMMON_CLK)
 538	/* Check if the clock has configurable parents */
 539	if (clk_hw_get_num_parents(__clk_get_hw(timer->fclk)) < 2)
 540		return 0;
 541#endif
 542
 543	switch (source) {
 544	case OMAP_TIMER_SRC_SYS_CLK:
 545		parent_name = "timer_sys_ck";
 546		break;
 547
 548	case OMAP_TIMER_SRC_32_KHZ:
 549		parent_name = "timer_32k_ck";
 550		break;
 551
 552	case OMAP_TIMER_SRC_EXT_CLK:
 553		parent_name = "timer_ext_ck";
 554		break;
 555	}
 556
 557	parent = clk_get(&timer->pdev->dev, parent_name);
 558	if (IS_ERR(parent)) {
 559		pr_err("%s: %s not found\n", __func__, parent_name);
 560		return -EINVAL;
 561	}
 562
 563	ret = clk_set_parent(timer->fclk, parent);
 564	if (ret < 0)
 565		pr_err("%s: failed to set %s as parent\n", __func__,
 566			parent_name);
 567
 568	clk_put(parent);
 569
 570	return ret;
 571}
 572EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
 573
 574int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
 575			    unsigned int load)
 576{
 577	u32 l;
 578
 579	if (unlikely(!timer))
 580		return -EINVAL;
 581
 582	omap_dm_timer_enable(timer);
 583	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 584	if (autoreload)
 585		l |= OMAP_TIMER_CTRL_AR;
 586	else
 587		l &= ~OMAP_TIMER_CTRL_AR;
 588	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 589	omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 590
 591	omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
 592	/* Save the context */
 593	timer->context.tclr = l;
 594	timer->context.tldr = load;
 595	omap_dm_timer_disable(timer);
 596	return 0;
 597}
 598EXPORT_SYMBOL_GPL(omap_dm_timer_set_load);
 599
 600/* Optimized set_load which removes costly spin wait in timer_start */
 601int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 602                            unsigned int load)
 603{
 604	u32 l;
 605
 606	if (unlikely(!timer))
 607		return -EINVAL;
 608
 609	omap_dm_timer_enable(timer);
 610
 
 
 
 
 
 
 
 611	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 612	if (autoreload) {
 613		l |= OMAP_TIMER_CTRL_AR;
 614		omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
 615	} else {
 616		l &= ~OMAP_TIMER_CTRL_AR;
 617	}
 618	l |= OMAP_TIMER_CTRL_ST;
 619
 620	__omap_dm_timer_load_start(timer, l, load, timer->posted);
 621
 622	/* Save the context */
 623	timer->context.tclr = l;
 624	timer->context.tldr = load;
 625	timer->context.tcrr = load;
 626	return 0;
 627}
 628EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
 629
 630int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
 631			     unsigned int match)
 632{
 633	u32 l;
 634
 635	if (unlikely(!timer))
 636		return -EINVAL;
 637
 638	omap_dm_timer_enable(timer);
 639	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 640	if (enable)
 641		l |= OMAP_TIMER_CTRL_CE;
 642	else
 643		l &= ~OMAP_TIMER_CTRL_CE;
 
 644	omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
 645	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 646
 647	/* Save the context */
 648	timer->context.tclr = l;
 649	timer->context.tmar = match;
 650	omap_dm_timer_disable(timer);
 651	return 0;
 652}
 653EXPORT_SYMBOL_GPL(omap_dm_timer_set_match);
 654
 655int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
 656			   int toggle, int trigger)
 657{
 658	u32 l;
 659
 660	if (unlikely(!timer))
 661		return -EINVAL;
 662
 663	omap_dm_timer_enable(timer);
 664	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 665	l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM |
 666	       OMAP_TIMER_CTRL_PT | (0x03 << 10));
 667	if (def_on)
 668		l |= OMAP_TIMER_CTRL_SCPWM;
 669	if (toggle)
 670		l |= OMAP_TIMER_CTRL_PT;
 671	l |= trigger << 10;
 672	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 673
 674	/* Save the context */
 675	timer->context.tclr = l;
 676	omap_dm_timer_disable(timer);
 677	return 0;
 678}
 679EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm);
 680
 681int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
 682{
 683	u32 l;
 684
 685	if (unlikely(!timer))
 686		return -EINVAL;
 687
 688	omap_dm_timer_enable(timer);
 689	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
 690	l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
 691	if (prescaler >= 0x00 && prescaler <= 0x07) {
 692		l |= OMAP_TIMER_CTRL_PRE;
 693		l |= prescaler << 2;
 694	}
 695	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
 696
 697	/* Save the context */
 698	timer->context.tclr = l;
 699	omap_dm_timer_disable(timer);
 700	return 0;
 701}
 702EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
 703
 704int omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
 705				  unsigned int value)
 706{
 707	if (unlikely(!timer))
 708		return -EINVAL;
 709
 710	omap_dm_timer_enable(timer);
 711	__omap_dm_timer_int_enable(timer, value);
 712
 713	/* Save the context */
 714	timer->context.tier = value;
 715	timer->context.twer = value;
 716	omap_dm_timer_disable(timer);
 717	return 0;
 718}
 719EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
 720
 721/**
 722 * omap_dm_timer_set_int_disable - disable timer interrupts
 723 * @timer:	pointer to timer handle
 724 * @mask:	bit mask of interrupts to be disabled
 725 *
 726 * Disables the specified timer interrupts for a timer.
 727 */
 728int omap_dm_timer_set_int_disable(struct omap_dm_timer *timer, u32 mask)
 729{
 730	u32 l = mask;
 731
 732	if (unlikely(!timer))
 733		return -EINVAL;
 734
 735	omap_dm_timer_enable(timer);
 736
 737	if (timer->revision == 1)
 738		l = readl_relaxed(timer->irq_ena) & ~mask;
 739
 740	writel_relaxed(l, timer->irq_dis);
 741	l = omap_dm_timer_read_reg(timer, OMAP_TIMER_WAKEUP_EN_REG) & ~mask;
 742	omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, l);
 743
 744	/* Save the context */
 745	timer->context.tier &= ~mask;
 746	timer->context.twer &= ~mask;
 747	omap_dm_timer_disable(timer);
 748	return 0;
 749}
 750EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_disable);
 751
 752unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
 753{
 754	unsigned int l;
 755
 756	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
 757		pr_err("%s: timer not available or enabled.\n", __func__);
 758		return 0;
 759	}
 760
 761	l = readl_relaxed(timer->irq_stat);
 762
 763	return l;
 764}
 765EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
 766
 767int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
 768{
 769	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
 770		return -EINVAL;
 771
 772	__omap_dm_timer_write_status(timer, value);
 773
 
 774	return 0;
 775}
 776EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
 777
 778unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
 779{
 780	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
 781		pr_err("%s: timer not iavailable or enabled.\n", __func__);
 782		return 0;
 783	}
 784
 785	return __omap_dm_timer_read_counter(timer, timer->posted);
 786}
 787EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
 788
 789int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
 790{
 791	if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
 792		pr_err("%s: timer not available or enabled.\n", __func__);
 793		return -EINVAL;
 794	}
 795
 796	omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
 797
 798	/* Save the context */
 799	timer->context.tcrr = value;
 800	return 0;
 801}
 802EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter);
 803
 804int omap_dm_timers_active(void)
 805{
 806	struct omap_dm_timer *timer;
 807
 808	list_for_each_entry(timer, &omap_timer_list, node) {
 809		if (!timer->reserved)
 810			continue;
 811
 812		if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
 813		    OMAP_TIMER_CTRL_ST) {
 814			return 1;
 815		}
 816	}
 817	return 0;
 818}
 819EXPORT_SYMBOL_GPL(omap_dm_timers_active);
 820
 821static const struct of_device_id omap_timer_match[];
 822
 823/**
 824 * omap_dm_timer_probe - probe function called for every registered device
 825 * @pdev:	pointer to current timer platform device
 826 *
 827 * Called by driver framework at the end of device registration for all
 828 * timer devices.
 829 */
 830static int omap_dm_timer_probe(struct platform_device *pdev)
 831{
 
 832	unsigned long flags;
 833	struct omap_dm_timer *timer;
 834	struct resource *mem, *irq;
 835	struct device *dev = &pdev->dev;
 836	const struct of_device_id *match;
 837	const struct dmtimer_platform_data *pdata;
 838	int ret;
 839
 840	match = of_match_device(of_match_ptr(omap_timer_match), dev);
 841	pdata = match ? match->data : dev->platform_data;
 842
 843	if (!pdata && !dev->of_node) {
 844		dev_err(dev, "%s: no platform data.\n", __func__);
 845		return -ENODEV;
 846	}
 847
 848	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 849	if (unlikely(!irq)) {
 850		dev_err(dev, "%s: no IRQ resource.\n", __func__);
 851		return -ENODEV;
 852	}
 853
 854	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 855	if (unlikely(!mem)) {
 856		dev_err(dev, "%s: no memory resource.\n", __func__);
 857		return -ENODEV;
 858	}
 859
 860	timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
 
 
 
 
 
 
 
 861	if (!timer) {
 862		dev_err(dev, "%s: memory alloc failed!\n", __func__);
 863		return  -ENOMEM;
 
 
 864	}
 865
 866	timer->fclk = ERR_PTR(-ENODEV);
 867	timer->io_base = devm_ioremap_resource(dev, mem);
 868	if (IS_ERR(timer->io_base))
 869		return PTR_ERR(timer->io_base);
 870
 871	if (dev->of_node) {
 872		if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
 873			timer->capability |= OMAP_TIMER_ALWON;
 874		if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
 875			timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
 876		if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
 877			timer->capability |= OMAP_TIMER_HAS_PWM;
 878		if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
 879			timer->capability |= OMAP_TIMER_SECURE;
 880	} else {
 881		timer->id = pdev->id;
 882		timer->capability = pdata->timer_capability;
 883		timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
 884		timer->get_context_loss_count = pdata->get_context_loss_count;
 885	}
 886
 887	if (pdata)
 888		timer->errata = pdata->timer_errata;
 889
 890	timer->irq = irq->start;
 
 891	timer->pdev = pdev;
 
 
 892
 893	/* Skip pm_runtime_enable for OMAP1 */
 894	if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
 895		pm_runtime_enable(dev);
 896		pm_runtime_irq_safe(dev);
 897	}
 898
 899	if (!timer->reserved) {
 900		ret = pm_runtime_get_sync(dev);
 901		if (ret < 0) {
 902			dev_err(dev, "%s: pm_runtime_get_sync failed!\n",
 903				__func__);
 904			goto err_get_sync;
 905		}
 906		__omap_dm_timer_init_regs(timer);
 907		pm_runtime_put(dev);
 908	}
 909
 910	/* add the timer element to the list */
 911	spin_lock_irqsave(&dm_timer_lock, flags);
 912	list_add_tail(&timer->node, &omap_timer_list);
 913	spin_unlock_irqrestore(&dm_timer_lock, flags);
 914
 915	dev_dbg(dev, "Device Probed.\n");
 916
 917	return 0;
 918
 919err_get_sync:
 920	pm_runtime_put_noidle(dev);
 921	pm_runtime_disable(dev);
 
 
 
 922	return ret;
 923}
 924
 925/**
 926 * omap_dm_timer_remove - cleanup a registered timer device
 927 * @pdev:	pointer to current timer platform device
 928 *
 929 * Called by driver framework whenever a timer device is unregistered.
 930 * In addition to freeing platform resources it also deletes the timer
 931 * entry from the local list.
 932 */
 933static int omap_dm_timer_remove(struct platform_device *pdev)
 934{
 935	struct omap_dm_timer *timer;
 936	unsigned long flags;
 937	int ret = -EINVAL;
 938
 939	spin_lock_irqsave(&dm_timer_lock, flags);
 940	list_for_each_entry(timer, &omap_timer_list, node)
 941		if (!strcmp(dev_name(&timer->pdev->dev),
 942			    dev_name(&pdev->dev))) {
 943			list_del(&timer->node);
 
 944			ret = 0;
 945			break;
 946		}
 947	spin_unlock_irqrestore(&dm_timer_lock, flags);
 948
 949	pm_runtime_disable(&pdev->dev);
 950
 951	return ret;
 952}
 953
 954static const struct dmtimer_platform_data omap3plus_pdata = {
 955	.timer_errata = OMAP_TIMER_ERRATA_I103_I767,
 956};
 957
 958static const struct of_device_id omap_timer_match[] = {
 959	{
 960		.compatible = "ti,omap2420-timer",
 961	},
 962	{
 963		.compatible = "ti,omap3430-timer",
 964		.data = &omap3plus_pdata,
 965	},
 966	{
 967		.compatible = "ti,omap4430-timer",
 968		.data = &omap3plus_pdata,
 969	},
 970	{
 971		.compatible = "ti,omap5430-timer",
 972		.data = &omap3plus_pdata,
 973	},
 974	{
 975		.compatible = "ti,am335x-timer",
 976		.data = &omap3plus_pdata,
 977	},
 978	{
 979		.compatible = "ti,am335x-timer-1ms",
 980		.data = &omap3plus_pdata,
 981	},
 982	{
 983		.compatible = "ti,dm816-timer",
 984		.data = &omap3plus_pdata,
 985	},
 986	{},
 987};
 988MODULE_DEVICE_TABLE(of, omap_timer_match);
 989
 990static struct platform_driver omap_dm_timer_driver = {
 991	.probe  = omap_dm_timer_probe,
 992	.remove = omap_dm_timer_remove,
 993	.driver = {
 994		.name   = "omap_timer",
 995		.of_match_table = of_match_ptr(omap_timer_match),
 996	},
 997};
 998
 
 
 
 
 
 
 
 
 
 
 999early_platform_init("earlytimer", &omap_dm_timer_driver);
1000module_platform_driver(omap_dm_timer_driver);
 
1001
1002MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
1003MODULE_LICENSE("GPL");
1004MODULE_ALIAS("platform:" DRIVER_NAME);
1005MODULE_AUTHOR("Texas Instruments Inc");