aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorTarun Kanti DebBarma <tarun.kanti@ti.com>2011-09-20 07:30:19 -0400
committerTony Lindgren <tony@atomide.com>2011-09-21 18:50:31 -0400
commitdf28472a1b28f5d2a6e5cf66265aa328995fde6b (patch)
treef9598f2f82717d3a92a06369842fe85fe91b4bee /arch/arm/plat-omap
parentc345c8b09d7a131f3571af55341038054a79efbd (diff)
ARM: OMAP: dmtimer: platform driver
Add dmtimer platform driver functions which include: (1) platform driver initialization (2) driver probe function (3) driver remove function Signed-off-by: Tarun Kanti DebBarma <tarun.kanti@ti.com> Signed-off-by: Thara Gopinath <thara@ti.com> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Cousson, Benoit <b-cousson@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/dmtimer.c139
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h2
2 files changed, 135 insertions, 6 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 571c14b36497..92d5aff9b2e9 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -35,14 +35,9 @@
35 * 675 Mass Ave, Cambridge, MA 02139, USA. 35 * 675 Mass Ave, Cambridge, MA 02139, USA.
36 */ 36 */
37 37
38#include <linux/init.h>
39#include <linux/spinlock.h>
40#include <linux/errno.h>
41#include <linux/list.h>
42#include <linux/clk.h>
43#include <linux/delay.h>
44#include <linux/io.h> 38#include <linux/io.h>
45#include <linux/module.h> 39#include <linux/module.h>
40#include <linux/slab.h>
46#include <mach/hardware.h> 41#include <mach/hardware.h>
47#include <plat/dmtimer.h> 42#include <plat/dmtimer.h>
48#include <mach/irqs.h> 43#include <mach/irqs.h>
@@ -149,6 +144,7 @@ static const char **dm_source_names;
149static struct clk **dm_source_clocks; 144static struct clk **dm_source_clocks;
150 145
151static spinlock_t dm_timer_lock; 146static spinlock_t dm_timer_lock;
147static LIST_HEAD(omap_timer_list);
152 148
153/* 149/*
154 * Reads timer registers in posted and non-posted mode. The posted mode bit 150 * Reads timer registers in posted and non-posted mode. The posted mode bit
@@ -549,6 +545,137 @@ int omap_dm_timers_active(void)
549} 545}
550EXPORT_SYMBOL_GPL(omap_dm_timers_active); 546EXPORT_SYMBOL_GPL(omap_dm_timers_active);
551 547
548/**
549 * omap_dm_timer_probe - probe function called for every registered device
550 * @pdev: pointer to current timer platform device
551 *
552 * Called by driver framework at the end of device registration for all
553 * timer devices.
554 */
555static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
556{
557 int ret;
558 unsigned long flags;
559 struct omap_dm_timer *timer;
560 struct resource *mem, *irq, *ioarea;
561 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
562
563 if (!pdata) {
564 dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
565 return -ENODEV;
566 }
567
568 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
569 if (unlikely(!irq)) {
570 dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
571 return -ENODEV;
572 }
573
574 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
575 if (unlikely(!mem)) {
576 dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
577 return -ENODEV;
578 }
579
580 ioarea = request_mem_region(mem->start, resource_size(mem),
581 pdev->name);
582 if (!ioarea) {
583 dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
584 return -EBUSY;
585 }
586
587 timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
588 if (!timer) {
589 dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
590 __func__);
591 ret = -ENOMEM;
592 goto err_free_ioregion;
593 }
594
595 timer->io_base = ioremap(mem->start, resource_size(mem));
596 if (!timer->io_base) {
597 dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
598 ret = -ENOMEM;
599 goto err_free_mem;
600 }
601
602 timer->id = pdev->id;
603 timer->irq = irq->start;
604 timer->pdev = pdev;
605 __omap_dm_timer_init_regs(timer);
606
607 /* add the timer element to the list */
608 spin_lock_irqsave(&dm_timer_lock, flags);
609 list_add_tail(&timer->node, &omap_timer_list);
610 spin_unlock_irqrestore(&dm_timer_lock, flags);
611
612 dev_dbg(&pdev->dev, "Device Probed.\n");
613
614 return 0;
615
616err_free_mem:
617 kfree(timer);
618
619err_free_ioregion:
620 release_mem_region(mem->start, resource_size(mem));
621
622 return ret;
623}
624
625/**
626 * omap_dm_timer_remove - cleanup a registered timer device
627 * @pdev: pointer to current timer platform device
628 *
629 * Called by driver framework whenever a timer device is unregistered.
630 * In addition to freeing platform resources it also deletes the timer
631 * entry from the local list.
632 */
633static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
634{
635 struct omap_dm_timer *timer;
636 unsigned long flags;
637 int ret = -EINVAL;
638
639 spin_lock_irqsave(&dm_timer_lock, flags);
640 list_for_each_entry(timer, &omap_timer_list, node)
641 if (timer->pdev->id == pdev->id) {
642 list_del(&timer->node);
643 kfree(timer);
644 ret = 0;
645 break;
646 }
647 spin_unlock_irqrestore(&dm_timer_lock, flags);
648
649 return ret;
650}
651
652static struct platform_driver omap_dm_timer_driver = {
653 .probe = omap_dm_timer_probe,
654 .remove = omap_dm_timer_remove,
655 .driver = {
656 .name = "omap_timer",
657 },
658};
659
660static int __init omap_dm_timer_driver_init(void)
661{
662 return platform_driver_register(&omap_dm_timer_driver);
663}
664
665static void __exit omap_dm_timer_driver_exit(void)
666{
667 platform_driver_unregister(&omap_dm_timer_driver);
668}
669
670early_platform_init("earlytimer", &omap_dm_timer_driver);
671module_init(omap_dm_timer_driver_init);
672module_exit(omap_dm_timer_driver_exit);
673
674MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
675MODULE_LICENSE("GPL");
676MODULE_ALIAS("platform:" DRIVER_NAME);
677MODULE_AUTHOR("Texas Instruments Inc");
678
552static int __init omap_dm_timer_init(void) 679static int __init omap_dm_timer_init(void)
553{ 680{
554 struct omap_dm_timer *timer; 681 struct omap_dm_timer *timer;
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index 9ed08df9d026..98f186e178c5 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -229,6 +229,7 @@ int omap_dm_timers_active(void);
229 229
230struct omap_dm_timer { 230struct omap_dm_timer {
231 unsigned long phys_base; 231 unsigned long phys_base;
232 int id;
232 int irq; 233 int irq;
233#ifdef CONFIG_ARCH_OMAP2PLUS 234#ifdef CONFIG_ARCH_OMAP2PLUS
234 struct clk *iclk, *fclk; 235 struct clk *iclk, *fclk;
@@ -246,6 +247,7 @@ struct omap_dm_timer {
246 unsigned enabled:1; 247 unsigned enabled:1;
247 unsigned posted:1; 248 unsigned posted:1;
248 struct platform_device *pdev; 249 struct platform_device *pdev;
250 struct list_head node;
249}; 251};
250 252
251extern u32 sys_timer_reserved; 253extern u32 sys_timer_reserved;