aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/dmtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/dmtimer.c')
-rw-r--r--arch/arm/plat-omap/dmtimer.c113
1 files changed, 98 insertions, 15 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 938b50a33439..9dca23e4d6b0 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -40,11 +40,10 @@
40#include <linux/device.h> 40#include <linux/device.h>
41#include <linux/err.h> 41#include <linux/err.h>
42#include <linux/pm_runtime.h> 42#include <linux/pm_runtime.h>
43#include <linux/of.h>
44#include <linux/of_device.h>
43 45
44#include <plat/dmtimer.h> 46#include <plat/dmtimer.h>
45#include <plat/omap-pm.h>
46
47#include <mach/hardware.h>
48 47
49static u32 omap_reserved_systimers; 48static u32 omap_reserved_systimers;
50static LIST_HEAD(omap_timer_list); 49static LIST_HEAD(omap_timer_list);
@@ -212,6 +211,13 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
212 unsigned long flags; 211 unsigned long flags;
213 int ret = 0; 212 int ret = 0;
214 213
214 /* Requesting timer by ID is not supported when device tree is used */
215 if (of_have_populated_dt()) {
216 pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n",
217 __func__);
218 return NULL;
219 }
220
215 spin_lock_irqsave(&dm_timer_lock, flags); 221 spin_lock_irqsave(&dm_timer_lock, flags);
216 list_for_each_entry(t, &omap_timer_list, node) { 222 list_for_each_entry(t, &omap_timer_list, node) {
217 if (t->pdev->id == id && !t->reserved) { 223 if (t->pdev->id == id && !t->reserved) {
@@ -237,6 +243,58 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
237} 243}
238EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); 244EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific);
239 245
246/**
247 * omap_dm_timer_request_by_cap - Request a timer by capability
248 * @cap: Bit mask of capabilities to match
249 *
250 * Find a timer based upon capabilities bit mask. Callers of this function
251 * should use the definitions found in the plat/dmtimer.h file under the
252 * comment "timer capabilities used in hwmod database". Returns pointer to
253 * timer handle on success and a NULL pointer on failure.
254 */
255struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap)
256{
257 struct omap_dm_timer *timer = NULL, *t;
258 unsigned long flags;
259
260 if (!cap)
261 return NULL;
262
263 spin_lock_irqsave(&dm_timer_lock, flags);
264 list_for_each_entry(t, &omap_timer_list, node) {
265 if ((!t->reserved) && ((t->capability & cap) == cap)) {
266 /*
267 * If timer is not NULL, we have already found one timer
268 * but it was not an exact match because it had more
269 * capabilites that what was required. Therefore,
270 * unreserve the last timer found and see if this one
271 * is a better match.
272 */
273 if (timer)
274 timer->reserved = 0;
275
276 timer = t;
277 timer->reserved = 1;
278
279 /* Exit loop early if we find an exact match */
280 if (t->capability == cap)
281 break;
282 }
283 }
284 spin_unlock_irqrestore(&dm_timer_lock, flags);
285
286 if (timer && omap_dm_timer_prepare(timer)) {
287 timer->reserved = 0;
288 timer = NULL;
289 }
290
291 if (!timer)
292 pr_debug("%s: timer request failed!\n", __func__);
293
294 return timer;
295}
296EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap);
297
240int omap_dm_timer_free(struct omap_dm_timer *timer) 298int omap_dm_timer_free(struct omap_dm_timer *timer)
241{ 299{
242 if (unlikely(!timer)) 300 if (unlikely(!timer))
@@ -271,7 +329,7 @@ int omap_dm_timer_get_irq(struct omap_dm_timer *timer)
271EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq); 329EXPORT_SYMBOL_GPL(omap_dm_timer_get_irq);
272 330
273#if defined(CONFIG_ARCH_OMAP1) 331#if defined(CONFIG_ARCH_OMAP1)
274 332#include <mach/hardware.h>
275/** 333/**
276 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR 334 * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR
277 * @inputmask: current value of idlect mask 335 * @inputmask: current value of idlect mask
@@ -348,7 +406,8 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
348 omap_dm_timer_enable(timer); 406 omap_dm_timer_enable(timer);
349 407
350 if (!(timer->capability & OMAP_TIMER_ALWON)) { 408 if (!(timer->capability & OMAP_TIMER_ALWON)) {
351 if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != 409 if (timer->get_context_loss_count &&
410 timer->get_context_loss_count(&timer->pdev->dev) !=
352 timer->ctx_loss_count) 411 timer->ctx_loss_count)
353 omap_timer_restore_context(timer); 412 omap_timer_restore_context(timer);
354 } 413 }
@@ -377,9 +436,11 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer)
377 436
378 __omap_dm_timer_stop(timer, timer->posted, rate); 437 __omap_dm_timer_stop(timer, timer->posted, rate);
379 438
380 if (!(timer->capability & OMAP_TIMER_ALWON)) 439 if (!(timer->capability & OMAP_TIMER_ALWON)) {
381 timer->ctx_loss_count = 440 if (timer->get_context_loss_count)
382 omap_pm_get_dev_context_loss_count(&timer->pdev->dev); 441 timer->ctx_loss_count =
442 timer->get_context_loss_count(&timer->pdev->dev);
443 }
383 444
384 /* 445 /*
385 * Since the register values are computed and written within 446 * Since the register values are computed and written within
@@ -414,7 +475,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
414 * use the clock framework to set the parent clock. To be removed 475 * use the clock framework to set the parent clock. To be removed
415 * once OMAP1 migrated to using clock framework for dmtimers 476 * once OMAP1 migrated to using clock framework for dmtimers
416 */ 477 */
417 if (pdata->set_timer_src) 478 if (pdata && pdata->set_timer_src)
418 return pdata->set_timer_src(timer->pdev, source); 479 return pdata->set_timer_src(timer->pdev, source);
419 480
420 fclk = clk_get(&timer->pdev->dev, "fck"); 481 fclk = clk_get(&timer->pdev->dev, "fck");
@@ -495,7 +556,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
495 omap_dm_timer_enable(timer); 556 omap_dm_timer_enable(timer);
496 557
497 if (!(timer->capability & OMAP_TIMER_ALWON)) { 558 if (!(timer->capability & OMAP_TIMER_ALWON)) {
498 if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != 559 if (timer->get_context_loss_count &&
560 timer->get_context_loss_count(&timer->pdev->dev) !=
499 timer->ctx_loss_count) 561 timer->ctx_loss_count)
500 omap_timer_restore_context(timer); 562 omap_timer_restore_context(timer);
501 } 563 }
@@ -695,7 +757,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
695 struct device *dev = &pdev->dev; 757 struct device *dev = &pdev->dev;
696 struct dmtimer_platform_data *pdata = pdev->dev.platform_data; 758 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
697 759
698 if (!pdata) { 760 if (!pdata && !dev->of_node) {
699 dev_err(dev, "%s: no platform data.\n", __func__); 761 dev_err(dev, "%s: no platform data.\n", __func__);
700 return -ENODEV; 762 return -ENODEV;
701 } 763 }
@@ -724,11 +786,24 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
724 return -ENOMEM; 786 return -ENOMEM;
725 } 787 }
726 788
727 timer->id = pdev->id; 789 if (dev->of_node) {
790 if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))
791 timer->capability |= OMAP_TIMER_ALWON;
792 if (of_find_property(dev->of_node, "ti,timer-dsp", NULL))
793 timer->capability |= OMAP_TIMER_HAS_DSP_IRQ;
794 if (of_find_property(dev->of_node, "ti,timer-pwm", NULL))
795 timer->capability |= OMAP_TIMER_HAS_PWM;
796 if (of_find_property(dev->of_node, "ti,timer-secure", NULL))
797 timer->capability |= OMAP_TIMER_SECURE;
798 } else {
799 timer->id = pdev->id;
800 timer->capability = pdata->timer_capability;
801 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
802 timer->get_context_loss_count = pdata->get_context_loss_count;
803 }
804
728 timer->irq = irq->start; 805 timer->irq = irq->start;
729 timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
730 timer->pdev = pdev; 806 timer->pdev = pdev;
731 timer->capability = pdata->timer_capability;
732 807
733 /* Skip pm_runtime_enable for OMAP1 */ 808 /* Skip pm_runtime_enable for OMAP1 */
734 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { 809 if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
@@ -768,7 +843,8 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
768 843
769 spin_lock_irqsave(&dm_timer_lock, flags); 844 spin_lock_irqsave(&dm_timer_lock, flags);
770 list_for_each_entry(timer, &omap_timer_list, node) 845 list_for_each_entry(timer, &omap_timer_list, node)
771 if (timer->pdev->id == pdev->id) { 846 if (!strcmp(dev_name(&timer->pdev->dev),
847 dev_name(&pdev->dev))) {
772 list_del(&timer->node); 848 list_del(&timer->node);
773 ret = 0; 849 ret = 0;
774 break; 850 break;
@@ -778,11 +854,18 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
778 return ret; 854 return ret;
779} 855}
780 856
857static const struct of_device_id omap_timer_match[] = {
858 { .compatible = "ti,omap2-timer", },
859 {},
860};
861MODULE_DEVICE_TABLE(of, omap_timer_match);
862
781static struct platform_driver omap_dm_timer_driver = { 863static struct platform_driver omap_dm_timer_driver = {
782 .probe = omap_dm_timer_probe, 864 .probe = omap_dm_timer_probe,
783 .remove = __devexit_p(omap_dm_timer_remove), 865 .remove = __devexit_p(omap_dm_timer_remove),
784 .driver = { 866 .driver = {
785 .name = "omap_timer", 867 .name = "omap_timer",
868 .of_match_table = of_match_ptr(omap_timer_match),
786 }, 869 },
787}; 870};
788 871