diff options
author | Tarun Kanti DebBarma <tarun.kanti@ti.com> | 2011-09-20 07:30:19 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2011-09-21 18:50:31 -0400 |
commit | df28472a1b28f5d2a6e5cf66265aa328995fde6b (patch) | |
tree | f9598f2f82717d3a92a06369842fe85fe91b4bee /arch/arm/plat-omap | |
parent | c345c8b09d7a131f3571af55341038054a79efbd (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.c | 139 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/dmtimer.h | 2 |
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; | |||
149 | static struct clk **dm_source_clocks; | 144 | static struct clk **dm_source_clocks; |
150 | 145 | ||
151 | static spinlock_t dm_timer_lock; | 146 | static spinlock_t dm_timer_lock; |
147 | static 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 | } |
550 | EXPORT_SYMBOL_GPL(omap_dm_timers_active); | 546 | EXPORT_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 | */ | ||
555 | static 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 | |||
616 | err_free_mem: | ||
617 | kfree(timer); | ||
618 | |||
619 | err_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 | */ | ||
633 | static 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 | |||
652 | static 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 | |||
660 | static int __init omap_dm_timer_driver_init(void) | ||
661 | { | ||
662 | return platform_driver_register(&omap_dm_timer_driver); | ||
663 | } | ||
664 | |||
665 | static void __exit omap_dm_timer_driver_exit(void) | ||
666 | { | ||
667 | platform_driver_unregister(&omap_dm_timer_driver); | ||
668 | } | ||
669 | |||
670 | early_platform_init("earlytimer", &omap_dm_timer_driver); | ||
671 | module_init(omap_dm_timer_driver_init); | ||
672 | module_exit(omap_dm_timer_driver_exit); | ||
673 | |||
674 | MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver"); | ||
675 | MODULE_LICENSE("GPL"); | ||
676 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
677 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
678 | |||
552 | static int __init omap_dm_timer_init(void) | 679 | static 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 | ||
230 | struct omap_dm_timer { | 230 | struct 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 | ||
251 | extern u32 sys_timer_reserved; | 253 | extern u32 sys_timer_reserved; |