Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dmtimer.c
Go to the documentation of this file.
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 <[email protected]>
8  * Thara Gopinath <[email protected]>
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 <[email protected]>
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/device.h>
41 #include <linux/err.h>
42 #include <linux/pm_runtime.h>
43 
44 #include <plat/dmtimer.h>
45 #include <plat/omap-pm.h>
46 
47 #include <mach/hardware.h>
48 
49 static u32 omap_reserved_systimers;
50 static LIST_HEAD(omap_timer_list);
51 static DEFINE_SPINLOCK(dm_timer_lock);
52 
62 static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
63 {
64  WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
65  return __omap_dm_timer_read(timer, reg, timer->posted);
66 }
67 
78 static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
79  u32 value)
80 {
81  WARN_ON((reg & 0xff) < _OMAP_TIMER_WAKEUP_EN_OFFSET);
82  __omap_dm_timer_write(timer, reg, value, timer->posted);
83 }
84 
85 static void omap_timer_restore_context(struct omap_dm_timer *timer)
86 {
87  if (timer->revision == 1)
88  __raw_writel(timer->context.tistat, timer->sys_stat);
89 
90  __raw_writel(timer->context.tisr, timer->irq_stat);
91  omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
92  timer->context.twer);
93  omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
94  timer->context.tcrr);
95  omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG,
96  timer->context.tldr);
97  omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG,
98  timer->context.tmar);
99  omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
100  timer->context.tsicr);
101  __raw_writel(timer->context.tier, timer->irq_ena);
102  omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG,
103  timer->context.tclr);
104 }
105 
106 static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
107 {
108  int c;
109 
110  if (!timer->sys_stat)
111  return;
112 
113  c = 0;
114  while (!(__raw_readl(timer->sys_stat) & 1)) {
115  c++;
116  if (c > 100000) {
117  printk(KERN_ERR "Timer failed to reset\n");
118  return;
119  }
120  }
121 }
122 
123 static void omap_dm_timer_reset(struct omap_dm_timer *timer)
124 {
125  omap_dm_timer_enable(timer);
126  if (timer->pdev->id != 1) {
127  omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
128  omap_dm_timer_wait_for_reset(timer);
129  }
130 
131  __omap_dm_timer_reset(timer, 0, 0);
132  omap_dm_timer_disable(timer);
133  timer->posted = 1;
134 }
135 
137 {
138  int ret;
139 
140  /*
141  * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
142  * do not call clk_get() for these devices.
143  */
144  if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
145  timer->fclk = clk_get(&timer->pdev->dev, "fck");
146  if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
147  timer->fclk = NULL;
148  dev_err(&timer->pdev->dev, ": No fclk handle.\n");
149  return -EINVAL;
150  }
151  }
152 
153  if (timer->capability & OMAP_TIMER_NEEDS_RESET)
154  omap_dm_timer_reset(timer);
155 
157 
158  timer->posted = 1;
159  return ret;
160 }
161 
162 static inline u32 omap_dm_timer_reserved_systimer(int id)
163 {
164  return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
165 }
166 
168 {
169  if (omap_dm_timer_reserved_systimer(id))
170  return -ENODEV;
171 
172  omap_reserved_systimers |= (1 << (id - 1));
173 
174  return 0;
175 }
176 
178 {
179  struct omap_dm_timer *timer = NULL, *t;
180  unsigned long flags;
181  int ret = 0;
182 
183  spin_lock_irqsave(&dm_timer_lock, flags);
184  list_for_each_entry(t, &omap_timer_list, node) {
185  if (t->reserved)
186  continue;
187 
188  timer = t;
189  timer->reserved = 1;
190  break;
191  }
192  spin_unlock_irqrestore(&dm_timer_lock, flags);
193 
194  if (timer) {
195  ret = omap_dm_timer_prepare(timer);
196  if (ret) {
197  timer->reserved = 0;
198  timer = NULL;
199  }
200  }
201 
202  if (!timer)
203  pr_debug("%s: timer request failed!\n", __func__);
204 
205  return timer;
206 }
208 
210 {
211  struct omap_dm_timer *timer = NULL, *t;
212  unsigned long flags;
213  int ret = 0;
214 
215  spin_lock_irqsave(&dm_timer_lock, flags);
216  list_for_each_entry(t, &omap_timer_list, node) {
217  if (t->pdev->id == id && !t->reserved) {
218  timer = t;
219  timer->reserved = 1;
220  break;
221  }
222  }
223  spin_unlock_irqrestore(&dm_timer_lock, flags);
224 
225  if (timer) {
226  ret = omap_dm_timer_prepare(timer);
227  if (ret) {
228  timer->reserved = 0;
229  timer = NULL;
230  }
231  }
232 
233  if (!timer)
234  pr_debug("%s: timer%d request failed!\n", __func__, id);
235 
236  return timer;
237 }
239 
241 {
242  if (unlikely(!timer))
243  return -EINVAL;
244 
245  clk_put(timer->fclk);
246 
247  WARN_ON(!timer->reserved);
248  timer->reserved = 0;
249  return 0;
250 }
252 
254 {
255  pm_runtime_get_sync(&timer->pdev->dev);
256 }
258 
260 {
261  pm_runtime_put_sync(&timer->pdev->dev);
262 }
264 
266 {
267  if (timer)
268  return timer->irq;
269  return -EINVAL;
270 }
272 
273 #if defined(CONFIG_ARCH_OMAP1)
274 
280 {
281  int i = 0;
282  struct omap_dm_timer *timer = NULL;
283  unsigned long flags;
284 
285  /* If ARMXOR cannot be idled this function call is unnecessary */
286  if (!(inputmask & (1 << 1)))
287  return inputmask;
288 
289  /* If any active timer is using ARMXOR return modified mask */
290  spin_lock_irqsave(&dm_timer_lock, flags);
291  list_for_each_entry(timer, &omap_timer_list, node) {
292  u32 l;
293 
294  l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
295  if (l & OMAP_TIMER_CTRL_ST) {
296  if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0)
297  inputmask &= ~(1 << 1);
298  else
299  inputmask &= ~(1 << 2);
300  }
301  i++;
302  }
303  spin_unlock_irqrestore(&dm_timer_lock, flags);
304 
305  return inputmask;
306 }
308 
309 #else
310 
312 {
313  if (timer)
314  return timer->fclk;
315  return NULL;
316 }
318 
320 {
321  BUG();
322 
323  return 0;
324 }
326 
327 #endif
328 
330 {
331  if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
332  pr_err("%s: timer not available or enabled.\n", __func__);
333  return -EINVAL;
334  }
335 
336  omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
337  return 0;
338 }
340 
342 {
343  u32 l;
344 
345  if (unlikely(!timer))
346  return -EINVAL;
347 
348  omap_dm_timer_enable(timer);
349 
350  if (!(timer->capability & OMAP_TIMER_ALWON)) {
351  if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
352  timer->ctx_loss_count)
353  omap_timer_restore_context(timer);
354  }
355 
356  l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
357  if (!(l & OMAP_TIMER_CTRL_ST)) {
358  l |= OMAP_TIMER_CTRL_ST;
359  omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
360  }
361 
362  /* Save the context */
363  timer->context.tclr = l;
364  return 0;
365 }
367 
369 {
370  unsigned long rate = 0;
371 
372  if (unlikely(!timer))
373  return -EINVAL;
374 
375  if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
376  rate = clk_get_rate(timer->fclk);
377 
378  __omap_dm_timer_stop(timer, timer->posted, rate);
379 
380  if (!(timer->capability & OMAP_TIMER_ALWON))
381  timer->ctx_loss_count =
383 
384  /*
385  * Since the register values are computed and written within
386  * __omap_dm_timer_stop, we need to use read to retrieve the
387  * context.
388  */
389  timer->context.tclr =
390  omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
391  timer->context.tisr = __raw_readl(timer->irq_stat);
392  omap_dm_timer_disable(timer);
393  return 0;
394 }
396 
398 {
399  int ret;
400  char *parent_name = NULL;
401  struct clk *fclk, *parent;
403 
404  if (unlikely(!timer))
405  return -EINVAL;
406 
407  pdata = timer->pdev->dev.platform_data;
408 
409  if (source < 0 || source >= 3)
410  return -EINVAL;
411 
412  /*
413  * FIXME: Used for OMAP1 devices only because they do not currently
414  * use the clock framework to set the parent clock. To be removed
415  * once OMAP1 migrated to using clock framework for dmtimers
416  */
417  if (pdata->set_timer_src)
418  return pdata->set_timer_src(timer->pdev, source);
419 
420  fclk = clk_get(&timer->pdev->dev, "fck");
421  if (IS_ERR_OR_NULL(fclk)) {
422  pr_err("%s: fck not found\n", __func__);
423  return -EINVAL;
424  }
425 
426  switch (source) {
428  parent_name = "timer_sys_ck";
429  break;
430 
432  parent_name = "timer_32k_ck";
433  break;
434 
436  parent_name = "timer_ext_ck";
437  break;
438  }
439 
440  parent = clk_get(&timer->pdev->dev, parent_name);
441  if (IS_ERR_OR_NULL(parent)) {
442  pr_err("%s: %s not found\n", __func__, parent_name);
443  ret = -EINVAL;
444  goto out;
445  }
446 
447  ret = clk_set_parent(fclk, parent);
448  if (IS_ERR_VALUE(ret))
449  pr_err("%s: failed to set %s as parent\n", __func__,
450  parent_name);
451 
452  clk_put(parent);
453 out:
454  clk_put(fclk);
455 
456  return ret;
457 }
459 
460 int omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload,
461  unsigned int load)
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 (autoreload)
471  l |= OMAP_TIMER_CTRL_AR;
472  else
473  l &= ~OMAP_TIMER_CTRL_AR;
474  omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
475  omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
476 
477  omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0);
478  /* Save the context */
479  timer->context.tclr = l;
480  timer->context.tldr = load;
481  omap_dm_timer_disable(timer);
482  return 0;
483 }
485 
486 /* Optimized set_load which removes costly spin wait in timer_start */
487 int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
488  unsigned int load)
489 {
490  u32 l;
491 
492  if (unlikely(!timer))
493  return -EINVAL;
494 
495  omap_dm_timer_enable(timer);
496 
497  if (!(timer->capability & OMAP_TIMER_ALWON)) {
498  if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
499  timer->ctx_loss_count)
500  omap_timer_restore_context(timer);
501  }
502 
503  l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
504  if (autoreload) {
505  l |= OMAP_TIMER_CTRL_AR;
506  omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
507  } else {
508  l &= ~OMAP_TIMER_CTRL_AR;
509  }
510  l |= OMAP_TIMER_CTRL_ST;
511 
512  __omap_dm_timer_load_start(timer, l, load, timer->posted);
513 
514  /* Save the context */
515  timer->context.tclr = l;
516  timer->context.tldr = load;
517  timer->context.tcrr = load;
518  return 0;
519 }
521 
523  unsigned int match)
524 {
525  u32 l;
526 
527  if (unlikely(!timer))
528  return -EINVAL;
529 
530  omap_dm_timer_enable(timer);
531  l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
532  if (enable)
533  l |= OMAP_TIMER_CTRL_CE;
534  else
535  l &= ~OMAP_TIMER_CTRL_CE;
536  omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
537  omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match);
538 
539  /* Save the context */
540  timer->context.tclr = l;
541  timer->context.tmar = match;
542  omap_dm_timer_disable(timer);
543  return 0;
544 }
546 
547 int omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on,
548  int toggle, int trigger)
549 {
550  u32 l;
551 
552  if (unlikely(!timer))
553  return -EINVAL;
554 
555  omap_dm_timer_enable(timer);
556  l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
558  OMAP_TIMER_CTRL_PT | (0x03 << 10));
559  if (def_on)
561  if (toggle)
562  l |= OMAP_TIMER_CTRL_PT;
563  l |= trigger << 10;
564  omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
565 
566  /* Save the context */
567  timer->context.tclr = l;
568  omap_dm_timer_disable(timer);
569  return 0;
570 }
572 
573 int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
574 {
575  u32 l;
576 
577  if (unlikely(!timer))
578  return -EINVAL;
579 
580  omap_dm_timer_enable(timer);
581  l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
582  l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2));
583  if (prescaler >= 0x00 && prescaler <= 0x07) {
584  l |= OMAP_TIMER_CTRL_PRE;
585  l |= prescaler << 2;
586  }
587  omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
588 
589  /* Save the context */
590  timer->context.tclr = l;
591  omap_dm_timer_disable(timer);
592  return 0;
593 }
595 
597  unsigned int value)
598 {
599  if (unlikely(!timer))
600  return -EINVAL;
601 
602  omap_dm_timer_enable(timer);
603  __omap_dm_timer_int_enable(timer, value);
604 
605  /* Save the context */
606  timer->context.tier = value;
607  timer->context.twer = value;
608  omap_dm_timer_disable(timer);
609  return 0;
610 }
612 
613 unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer)
614 {
615  unsigned int l;
616 
617  if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
618  pr_err("%s: timer not available or enabled.\n", __func__);
619  return 0;
620  }
621 
622  l = __raw_readl(timer->irq_stat);
623 
624  return l;
625 }
627 
628 int omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
629 {
630  if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev)))
631  return -EINVAL;
632 
633  __omap_dm_timer_write_status(timer, value);
634  /* Save the context */
635  timer->context.tisr = value;
636  return 0;
637 }
639 
640 unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
641 {
642  if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
643  pr_err("%s: timer not iavailable or enabled.\n", __func__);
644  return 0;
645  }
646 
647  return __omap_dm_timer_read_counter(timer, timer->posted);
648 }
650 
651 int omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value)
652 {
653  if (unlikely(!timer || pm_runtime_suspended(&timer->pdev->dev))) {
654  pr_err("%s: timer not available or enabled.\n", __func__);
655  return -EINVAL;
656  }
657 
658  omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value);
659 
660  /* Save the context */
661  timer->context.tcrr = value;
662  return 0;
663 }
665 
667 {
668  struct omap_dm_timer *timer;
669 
670  list_for_each_entry(timer, &omap_timer_list, node) {
671  if (!timer->reserved)
672  continue;
673 
674  if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) &
675  OMAP_TIMER_CTRL_ST) {
676  return 1;
677  }
678  }
679  return 0;
680 }
682 
690 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
691 {
692  unsigned long flags;
693  struct omap_dm_timer *timer;
694  struct resource *mem, *irq;
695  struct device *dev = &pdev->dev;
696  struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
697 
698  if (!pdata) {
699  dev_err(dev, "%s: no platform data.\n", __func__);
700  return -ENODEV;
701  }
702 
703  irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
704  if (unlikely(!irq)) {
705  dev_err(dev, "%s: no IRQ resource.\n", __func__);
706  return -ENODEV;
707  }
708 
709  mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
710  if (unlikely(!mem)) {
711  dev_err(dev, "%s: no memory resource.\n", __func__);
712  return -ENODEV;
713  }
714 
715  timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
716  if (!timer) {
717  dev_err(dev, "%s: memory alloc failed!\n", __func__);
718  return -ENOMEM;
719  }
720 
721  timer->io_base = devm_request_and_ioremap(dev, mem);
722  if (!timer->io_base) {
723  dev_err(dev, "%s: region already claimed.\n", __func__);
724  return -ENOMEM;
725  }
726 
727  timer->id = pdev->id;
728  timer->irq = irq->start;
729  timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
730  timer->pdev = pdev;
731  timer->capability = pdata->timer_capability;
732 
733  /* Skip pm_runtime_enable for OMAP1 */
734  if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
735  pm_runtime_enable(dev);
736  pm_runtime_irq_safe(dev);
737  }
738 
739  if (!timer->reserved) {
740  pm_runtime_get_sync(dev);
741  __omap_dm_timer_init_regs(timer);
742  pm_runtime_put(dev);
743  }
744 
745  /* add the timer element to the list */
746  spin_lock_irqsave(&dm_timer_lock, flags);
747  list_add_tail(&timer->node, &omap_timer_list);
748  spin_unlock_irqrestore(&dm_timer_lock, flags);
749 
750  dev_dbg(dev, "Device Probed.\n");
751 
752  return 0;
753 }
754 
763 static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
764 {
765  struct omap_dm_timer *timer;
766  unsigned long flags;
767  int ret = -EINVAL;
768 
769  spin_lock_irqsave(&dm_timer_lock, flags);
770  list_for_each_entry(timer, &omap_timer_list, node)
771  if (timer->pdev->id == pdev->id) {
772  list_del(&timer->node);
773  ret = 0;
774  break;
775  }
776  spin_unlock_irqrestore(&dm_timer_lock, flags);
777 
778  return ret;
779 }
780 
781 static struct platform_driver omap_dm_timer_driver = {
782  .probe = omap_dm_timer_probe,
783  .remove = __devexit_p(omap_dm_timer_remove),
784  .driver = {
785  .name = "omap_timer",
786  },
787 };
788 
789 static int __init omap_dm_timer_driver_init(void)
790 {
791  return platform_driver_register(&omap_dm_timer_driver);
792 }
793 
794 static void __exit omap_dm_timer_driver_exit(void)
795 {
796  platform_driver_unregister(&omap_dm_timer_driver);
797 }
798 
799 early_platform_init("earlytimer", &omap_dm_timer_driver);
800 module_init(omap_dm_timer_driver_init);
801 module_exit(omap_dm_timer_driver_exit);
802 
803 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
804 MODULE_LICENSE("GPL");
805 MODULE_ALIAS("platform:" DRIVER_NAME);
806 MODULE_AUTHOR("Texas Instruments Inc");