aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/timer.c
diff options
context:
space:
mode:
authorTarun Kanti DebBarma <tarun.kanti@ti.com>2011-09-20 07:30:18 -0400
committerTony Lindgren <tony@atomide.com>2011-09-21 18:50:31 -0400
commitc345c8b09d7a131f3571af55341038054a79efbd (patch)
tree8bd6653ef7da1276365258a2b11a54d5c0626a4e /arch/arm/mach-omap2/timer.c
parent97933d6ced601de013f17ad3f589e72cf2266bba (diff)
ARM: OMAP2+: dmtimer: convert to platform devices
Add routines to converts dmtimers to platform devices. The device data is obtained from hwmod database of respective platform and is registered to device model after successful binding to driver. In addition, capability attribute of each of the timers is added in hwmod database. 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/mach-omap2/timer.c')
-rw-r--r--arch/arm/mach-omap2/timer.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 69466f388417..b2829ee0c4e4 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -35,6 +35,7 @@
35#include <linux/irq.h> 35#include <linux/irq.h>
36#include <linux/clocksource.h> 36#include <linux/clocksource.h>
37#include <linux/clockchips.h> 37#include <linux/clockchips.h>
38#include <linux/slab.h>
38 39
39#include <asm/mach/time.h> 40#include <asm/mach/time.h>
40#include <plat/dmtimer.h> 41#include <plat/dmtimer.h>
@@ -42,6 +43,7 @@
42#include <asm/sched_clock.h> 43#include <asm/sched_clock.h>
43#include <plat/common.h> 44#include <plat/common.h>
44#include <plat/omap_hwmod.h> 45#include <plat/omap_hwmod.h>
46#include <plat/omap_device.h>
45 47
46/* Parent clocks, eventually these will come from the clock framework */ 48/* Parent clocks, eventually these will come from the clock framework */
47 49
@@ -342,3 +344,137 @@ static void __init omap4_timer_init(void)
342} 344}
343OMAP_SYS_TIMER(4) 345OMAP_SYS_TIMER(4)
344#endif 346#endif
347
348/**
349 * omap2_dm_timer_set_src - change the timer input clock source
350 * @pdev: timer platform device pointer
351 * @source: array index of parent clock source
352 */
353static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
354{
355 int ret;
356 struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
357 struct clk *fclk, *parent;
358 char *parent_name = NULL;
359
360 fclk = clk_get(&pdev->dev, "fck");
361 if (IS_ERR_OR_NULL(fclk)) {
362 dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
363 __func__, __LINE__);
364 return -EINVAL;
365 }
366
367 switch (source) {
368 case OMAP_TIMER_SRC_SYS_CLK:
369 parent_name = "sys_ck";
370 break;
371
372 case OMAP_TIMER_SRC_32_KHZ:
373 parent_name = "32k_ck";
374 break;
375
376 case OMAP_TIMER_SRC_EXT_CLK:
377 if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
378 parent_name = "alt_ck";
379 break;
380 }
381 dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
382 __func__, __LINE__);
383 clk_put(fclk);
384 return -EINVAL;
385 }
386
387 parent = clk_get(&pdev->dev, parent_name);
388 if (IS_ERR_OR_NULL(parent)) {
389 dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
390 __func__, __LINE__, parent_name);
391 clk_put(fclk);
392 return -EINVAL;
393 }
394
395 ret = clk_set_parent(fclk, parent);
396 if (IS_ERR_VALUE(ret)) {
397 dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
398 __func__, parent_name);
399 ret = -EINVAL;
400 }
401
402 clk_put(parent);
403 clk_put(fclk);
404
405 return ret;
406}
407
408struct omap_device_pm_latency omap2_dmtimer_latency[] = {
409 {
410 .deactivate_func = omap_device_idle_hwmods,
411 .activate_func = omap_device_enable_hwmods,
412 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
413 },
414};
415
416/**
417 * omap_timer_init - build and register timer device with an
418 * associated timer hwmod
419 * @oh: timer hwmod pointer to be used to build timer device
420 * @user: parameter that can be passed from calling hwmod API
421 *
422 * Called by omap_hwmod_for_each_by_class to register each of the timer
423 * devices present in the system. The number of timer devices is known
424 * by parsing through the hwmod database for a given class name. At the
425 * end of function call memory is allocated for timer device and it is
426 * registered to the framework ready to be proved by the driver.
427 */
428static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
429{
430 int id;
431 int ret = 0;
432 char *name = "omap_timer";
433 struct dmtimer_platform_data *pdata;
434 struct omap_device *od;
435 struct omap_timer_capability_dev_attr *timer_dev_attr;
436
437 pr_debug("%s: %s\n", __func__, oh->name);
438
439 /* on secure device, do not register secure timer */
440 timer_dev_attr = oh->dev_attr;
441 if (omap_type() != OMAP2_DEVICE_TYPE_GP && timer_dev_attr)
442 if (timer_dev_attr->timer_capability == OMAP_TIMER_SECURE)
443 return ret;
444
445 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
446 if (!pdata) {
447 pr_err("%s: No memory for [%s]\n", __func__, oh->name);
448 return -ENOMEM;
449 }
450
451 /*
452 * Extract the IDs from name field in hwmod database
453 * and use the same for constructing ids' for the
454 * timer devices. In a way, we are avoiding usage of
455 * static variable witin the function to do the same.
456 * CAUTION: We have to be careful and make sure the
457 * name in hwmod database does not change in which case
458 * we might either make corresponding change here or
459 * switch back static variable mechanism.
460 */
461 sscanf(oh->name, "timer%2d", &id);
462
463 pdata->set_timer_src = omap2_dm_timer_set_src;
464 pdata->timer_ip_version = oh->class->rev;
465
466 od = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
467 omap2_dmtimer_latency,
468 ARRAY_SIZE(omap2_dmtimer_latency),
469 0);
470
471 if (IS_ERR(od)) {
472 pr_err("%s: Can't build omap_device for %s: %s.\n",
473 __func__, name, oh->name);
474 ret = -EINVAL;
475 }
476
477 kfree(pdata);
478
479 return ret;
480}