From b7b4ff764f7bf903e47eebdab661b1c38e791c6d Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:51 -0500 Subject: ARM: OMAP2+: Add dmtimer platform function to reserve systimers During early boot, one or two dmtimers are reserved by the kernel as system timers (for clocksource and clockevents). These timers are marked as reserved and the dmtimer driver is notified which timers have been reserved via the platform data information. For OMAP2+ devices the timers reserved may vary depending on device and compile flags. Therefore, it is not easy to assume which timers we be reserved for the system timers. In order to migrate the dmtimer driver to support device-tree we need a way to pass the timers reserved for system timers to the dmtimer driver. Using the platform data structure will not work in the same way as it is currently used because the platform data structure will be stored statically in the dmtimer itself and the platform data will be selected via the device-tree match device function (of_match_device). There are a couple ways to workaround this. One option is to store the system timers reserved for the kernel in the device-tree and query them on boot. The downside of this approach is that it adds some delay to parse the DT blob to search for the system timers. Secondly, for OMAP3 devices we have a dependency on compile time flags and the device-tree would not be aware of that kernel compile flags and so we would need to address that. The second option is to add a function to the dmtimer code to reserved the system timers during boot and so the dmtimer knows exactly which timers are being used for system timers. This also allows us to remove the "reserved" member from the timer platform data. This seemed like the simpler approach and so was implemented here. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 3b0cfeb33d05..f5b5c89ac7c2 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -45,6 +45,7 @@ #include +static u32 omap_reserved_systimers; static LIST_HEAD(omap_timer_list); static DEFINE_SPINLOCK(dm_timer_lock); @@ -152,6 +153,21 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) return ret; } +static inline u32 omap_dm_timer_reserved_systimer(int id) +{ + return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0; +} + +int omap_dm_timer_reserve_systimer(int id) +{ + if (omap_dm_timer_reserved_systimer(id)) + return -ENODEV; + + omap_reserved_systimers |= (1 << (id - 1)); + + return 0; +} + struct omap_dm_timer *omap_dm_timer_request(void) { struct omap_dm_timer *timer = NULL, *t; @@ -674,7 +690,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->id = pdev->id; timer->irq = irq->start; - timer->reserved = pdata->reserved; + timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; timer->loses_context = pdata->loses_context; timer->get_context_loss_count = pdata->get_context_loss_count; -- cgit v1.2.3 From d1c1691be5290bf7e5b11b63b6fda0d63a9f4937 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:52 -0500 Subject: ARM: OMAP: Add DMTIMER capability variable to represent timer features Although the OMAP timers share a common hardware design, there are some differences between the timer instances in a given device. For example, a timer maybe in a power domain that can be powered-of, so can lose its logic state and need restoring where as another may be in power domain that is always be on. Another example, is a timer may support different clock sources to drive the timer. This information is passed to the dmtimer via the following platform data structure. struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); int timer_ip_version; u32 needs_manual_reset:1; bool loses_context; int (*get_context_loss_count)(struct device *dev); }; The above structure uses multiple variables to represent the timer features. HWMOD also stores the timer capabilities using a bit-mask that represents the features supported. By using the same format for representing the timer features in the platform data as used by HWMOD, we can ... 1. Use the flags defined in the plat/dmtimer.h to represent the features supported. 2. For devices using HWMOD, we can retrieve the features supported from HWMOD. 3. Eventually, simplify the platform data structure to be ... struct dmtimer_platform_data { int (*set_timer_src)(struct platform_device *pdev, int source); u32 timer_capability; } Another benefit from doing this, is that it will simplify the migration of the dmtimer driver to device-tree. For example, in the current OMAP2+ timer code the "loses_context" variable is configured at runtime by calling an architecture specific function. For device tree this creates a problem, because we would need to call the architecture specific function from within the dmtimer driver. However, such attributes do not need to be queried at runtime and we can look up the attributes via HWMOD or device-tree. This changes a new "capability" variable to the platform data and timer structure so we can start removing and simplifying the platform data structure. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index f5b5c89ac7c2..30742d8e6819 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -694,6 +694,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->pdev = pdev; timer->loses_context = pdata->loses_context; timer->get_context_loss_count = pdata->get_context_loss_count; + timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ if (!pdata->needs_manual_reset) { -- cgit v1.2.3 From 1c2d076b589225e51e022d85bb9f25dca26530f3 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:55 -0500 Subject: ARM: OMAP: Remove loses_context variable from timer platform data The platform data variable loses_context is used to determine if the timer may lose its logic state during power transitions and so needs to be restored. This information is also provided in the HWMOD device attributes for OMAP2+ devices via the OMAP_TIMER_ALWON flag. When this flag is set the timer will not lose context. So use the HWMOD device attributes to determine this. For OMAP1 devices, loses_context is never set and so set the OMAP_TIMER_ALWON flag for OMAP1 timers to ensure that code is equivalent. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 30742d8e6819..7aa12785e238 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -341,7 +341,7 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_enable(timer); - if (timer->loses_context) { + if (!(timer->capability & OMAP_TIMER_ALWON)) { u32 ctx_loss_cnt_after = timer->get_context_loss_count(&timer->pdev->dev); if (ctx_loss_cnt_after != timer->ctx_loss_count) @@ -374,7 +374,8 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); - if (timer->loses_context && timer->get_context_loss_count) + if (!(timer->capability & OMAP_TIMER_ALWON) && + timer->get_context_loss_count) timer->ctx_loss_count = timer->get_context_loss_count(&timer->pdev->dev); @@ -447,7 +448,7 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_enable(timer); - if (timer->loses_context) { + if (!(timer->capability & OMAP_TIMER_ALWON)) { u32 ctx_loss_cnt_after = timer->get_context_loss_count(&timer->pdev->dev); if (ctx_loss_cnt_after != timer->ctx_loss_count) @@ -692,7 +693,6 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->irq = irq->start; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; - timer->loses_context = pdata->loses_context; timer->get_context_loss_count = pdata->get_context_loss_count; timer->capability = pdata->timer_capability; -- cgit v1.2.3 From 0b30ec1cb7f1b0134b16670f886baaf3521b083c Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:56 -0500 Subject: ARM: OMAP: Remove timer function pointer for context loss counter For OMAP2+ devices, a function pointer that returns the number of times a timer power domain has lost context is passed to the dmtimer driver. This function pointer is only populated for OMAP2+ devices and it is pointing to a platform function. Given that this is a platform function, we can simplify the code by removing the function pointer and referencing the function directly. We can use the OMAP_TIMER_ALWON flag to determine if we need to call this function for OMAP1 and OMAP2+ devices. The benefit of this change is the we can remove the function pointer from the platform data and simplifies the dmtimer migration to device-tree. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 7aa12785e238..7875eefd0474 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -42,6 +42,7 @@ #include #include +#include #include @@ -342,9 +343,8 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_enable(timer); if (!(timer->capability & OMAP_TIMER_ALWON)) { - u32 ctx_loss_cnt_after = - timer->get_context_loss_count(&timer->pdev->dev); - if (ctx_loss_cnt_after != timer->ctx_loss_count) + if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != + timer->ctx_loss_count) omap_timer_restore_context(timer); } @@ -374,10 +374,9 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); - if (!(timer->capability & OMAP_TIMER_ALWON) && - timer->get_context_loss_count) + if (!(timer->capability & OMAP_TIMER_ALWON)) timer->ctx_loss_count = - timer->get_context_loss_count(&timer->pdev->dev); + omap_pm_get_dev_context_loss_count(&timer->pdev->dev); /* * Since the register values are computed and written within @@ -449,9 +448,8 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_enable(timer); if (!(timer->capability & OMAP_TIMER_ALWON)) { - u32 ctx_loss_cnt_after = - timer->get_context_loss_count(&timer->pdev->dev); - if (ctx_loss_cnt_after != timer->ctx_loss_count) + if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) != + timer->ctx_loss_count) omap_timer_restore_context(timer); } @@ -693,7 +691,6 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->irq = irq->start; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->pdev = pdev; - timer->get_context_loss_count = pdata->get_context_loss_count; timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ -- cgit v1.2.3 From 6615975bc58a1234bd401a7ff231dae85631fd58 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:57 -0500 Subject: ARM: OMAP: Add flag to indicate if a timer needs a manual reset For OMAP1 devices, it is necessary to perform a manual reset of the timer. Currently, this is indicating by setting the "needs_manual_reset" variable in the platform data. Instead of using an extra variable to indicate this add a new timer capabilities flag to indicate this and remove the "needs_manual_reset" member from the platform data. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 7875eefd0474..e3e22b3dc5c2 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -135,7 +135,6 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) int omap_dm_timer_prepare(struct omap_dm_timer *timer) { - struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data; int ret; timer->fclk = clk_get(&timer->pdev->dev, "fck"); @@ -145,7 +144,7 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) return -EINVAL; } - if (pdata->needs_manual_reset) + if (timer->capability & OMAP_TIMER_NEEDS_RESET) omap_dm_timer_reset(timer); ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); @@ -363,13 +362,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start); int omap_dm_timer_stop(struct omap_dm_timer *timer) { unsigned long rate = 0; - struct dmtimer_platform_data *pdata; if (unlikely(!timer)) return -EINVAL; - pdata = timer->pdev->dev.platform_data; - if (!pdata->needs_manual_reset) + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) rate = clk_get_rate(timer->fclk); __omap_dm_timer_stop(timer, timer->posted, rate); @@ -694,7 +691,7 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) timer->capability = pdata->timer_capability; /* Skip pm_runtime_enable for OMAP1 */ - if (!pdata->needs_manual_reset) { + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { pm_runtime_enable(&pdev->dev); pm_runtime_irq_safe(&pdev->dev); } -- cgit v1.2.3 From bca4580845cbffb455d77783fc7e58a94b3904e0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:58 -0500 Subject: ARM: OMAP1: Fix dmtimer support OMAP1 dmtimer support is currently broken. When a dmtimer is requested by the omap_dm_timer_request() function fails to allocate a dmtimer because the call to clk_get() inside omap_dm_timer_prepare fails. The clk_get() fails simply because the clock data for the OMAP1 dmtimers is not present. Ideally this should be fixed by moving OMAP1 dmtimers to use the clock framework. For now simply fix this by using the "TIMER_NEEDS_RESET" flag to identify an OMAP1 device and avoid calling clk_get(). Although this is not the ideal fix and should be corrected, this flag has already been use for the same purpose in omap_dm_timer_stop(). Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index e3e22b3dc5c2..6510e5e7b7e3 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -137,11 +137,17 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) { int ret; - timer->fclk = clk_get(&timer->pdev->dev, "fck"); - if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) { - timer->fclk = NULL; - dev_err(&timer->pdev->dev, ": No fclk handle.\n"); - return -EINVAL; + /* + * FIXME: OMAP1 devices do not use the clock framework for dmtimers so + * do not call clk_get() for these devices. + */ + if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { + timer->fclk = clk_get(&timer->pdev->dev, "fck"); + if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) { + timer->fclk = NULL; + dev_err(&timer->pdev->dev, ": No fclk handle.\n"); + return -EINVAL; + } } if (timer->capability & OMAP_TIMER_NEEDS_RESET) -- cgit v1.2.3 From 2b2d35230099613365ad6000f4d71086130b9e71 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:34:59 -0500 Subject: ARM: OMAP2+: Move dmtimer clock set function to dmtimer driver OMAP1 uses an architecture specific function for setting the dmtimer clock source, where as the OMAP2+ devices use the clock framework. Eventually OMAP1 device should also use the clock framework and hence we should not any architecture specific functions. For now move the OMAP2+ function for configuring the clock source into the dmtimer driver. Therefore, we do no longer need to specify an architecture specific function for setting the clock source for OMAP2+ devices. This will simplify device tree migration of the dmtimers for OMAP2+ devices. From now on, only OMAP1 devices should specify an architecture specific function for setting the clock source via the platform data set_dmtimer_src() function pointer. Signed-off-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 6510e5e7b7e3..6a7088972c55 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -397,6 +397,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop); int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) { int ret; + char *parent_name = NULL; + struct clk *fclk, *parent; struct dmtimer_platform_data *pdata; if (unlikely(!timer)) @@ -407,7 +409,49 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) if (source < 0 || source >= 3) return -EINVAL; - ret = pdata->set_timer_src(timer->pdev, source); + /* + * FIXME: Used for OMAP1 devices only because they do not currently + * use the clock framework to set the parent clock. To be removed + * once OMAP1 migrated to using clock framework for dmtimers + */ + if (pdata->set_timer_src) + return pdata->set_timer_src(timer->pdev, source); + + fclk = clk_get(&timer->pdev->dev, "fck"); + if (IS_ERR_OR_NULL(fclk)) { + pr_err("%s: fck not found\n", __func__); + return -EINVAL; + } + + switch (source) { + case OMAP_TIMER_SRC_SYS_CLK: + parent_name = "sys_ck"; + break; + + case OMAP_TIMER_SRC_32_KHZ: + parent_name = "32k_ck"; + break; + + case OMAP_TIMER_SRC_EXT_CLK: + parent_name = "alt_ck"; + break; + } + + parent = clk_get(&timer->pdev->dev, parent_name); + if (IS_ERR_OR_NULL(parent)) { + pr_err("%s: %s not found\n", __func__, parent_name); + ret = -EINVAL; + goto out; + } + + ret = clk_set_parent(fclk, parent); + if (IS_ERR_VALUE(ret)) + pr_err("%s: failed to set %s as parent\n", __func__, + parent_name); + + clk_put(parent); +out: + clk_put(fclk); return ret; } -- cgit v1.2.3 From c59b537d87068be8c357a0150f6172a2dc8cdf82 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 5 Jun 2012 12:35:00 -0500 Subject: ARM: OMAP2+: Simplify dmtimer clock aliases The OMAP dmtimer driver allows you to dynamically configure the functional clock that drives the timer logic. The dmtimer driver uses the device name and a "con-id" string to search for the appropriate functional clock. Currently, we define a clock alias for each functional clock source each timer supports. Some functional clock sources are common to all of the timers on a device and so for these clock sources we can use a single alias with a unique con-id string. The possible functional clock sources for an OMAP device are a 32kHz clock, a system (MHz range) clock and (for OMAP2 only) an external clock. By defining a unique con-id name for each of these (timer_32k_ck, timer_sys_ck and timer_ext_ck) we can eliminate a lot of the clock aliases for timers. This reduces code, speeds-up searches and clock initialisation time. Signed-off-by: Jon Hunter Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 6a7088972c55..54ed4e6e429e 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -425,15 +425,15 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) switch (source) { case OMAP_TIMER_SRC_SYS_CLK: - parent_name = "sys_ck"; + parent_name = "timer_sys_ck"; break; case OMAP_TIMER_SRC_32_KHZ: - parent_name = "32k_ck"; + parent_name = "timer_32k_ck"; break; case OMAP_TIMER_SRC_EXT_CLK: - parent_name = "alt_ck"; + parent_name = "timer_ext_ck"; break; } -- cgit v1.2.3 From 74dd9ec627582bfd4477f01ceeaaa3f54e3748b8 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Fri, 20 Apr 2012 18:09:20 +0530 Subject: ARM: OMAP: dmtimer: use devm_ API and do some cleanup in probe() Replace the regular kzalloc and ioremap with the devm_ equivalent to simplify error handling. We don't need kree() any more in omap_dm_timer_remove(). Also added *dev* pointer to reference pdev->dev which makes the usage shorter in code. Cc: Cousson, Benoit Cc: Paul Walmsley Cc: Kevin Hilman Cc: Rajendra Nayak Cc: Santosh Shilimkar Signed-off-by: Tarun Kanti DebBarma Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 53 ++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 36 deletions(-) (limited to 'arch/arm/plat-omap/dmtimer.c') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 54ed4e6e429e..626ad8cad7a9 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include @@ -689,49 +689,39 @@ EXPORT_SYMBOL_GPL(omap_dm_timers_active); */ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) { - int ret; unsigned long flags; struct omap_dm_timer *timer; - struct resource *mem, *irq, *ioarea; + struct resource *mem, *irq; + struct device *dev = &pdev->dev; struct dmtimer_platform_data *pdata = pdev->dev.platform_data; if (!pdata) { - dev_err(&pdev->dev, "%s: no platform data.\n", __func__); + dev_err(dev, "%s: no platform data.\n", __func__); return -ENODEV; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (unlikely(!irq)) { - dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__); + dev_err(dev, "%s: no IRQ resource.\n", __func__); return -ENODEV; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(!mem)) { - dev_err(&pdev->dev, "%s: no memory resource.\n", __func__); + dev_err(dev, "%s: no memory resource.\n", __func__); return -ENODEV; } - ioarea = request_mem_region(mem->start, resource_size(mem), - pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "%s: region already claimed.\n", __func__); - return -EBUSY; - } - - timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL); + timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL); if (!timer) { - dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n", - __func__); - ret = -ENOMEM; - goto err_free_ioregion; + dev_err(dev, "%s: memory alloc failed!\n", __func__); + return -ENOMEM; } - timer->io_base = ioremap(mem->start, resource_size(mem)); + timer->io_base = devm_request_and_ioremap(dev, mem); if (!timer->io_base) { - dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__); - ret = -ENOMEM; - goto err_free_mem; + dev_err(dev, "%s: region already claimed.\n", __func__); + return -ENOMEM; } timer->id = pdev->id; @@ -742,14 +732,14 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) /* Skip pm_runtime_enable for OMAP1 */ if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) { - pm_runtime_enable(&pdev->dev); - pm_runtime_irq_safe(&pdev->dev); + pm_runtime_enable(dev); + pm_runtime_irq_safe(dev); } if (!timer->reserved) { - pm_runtime_get_sync(&pdev->dev); + pm_runtime_get_sync(dev); __omap_dm_timer_init_regs(timer); - pm_runtime_put(&pdev->dev); + pm_runtime_put(dev); } /* add the timer element to the list */ @@ -757,17 +747,9 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) list_add_tail(&timer->node, &omap_timer_list); spin_unlock_irqrestore(&dm_timer_lock, flags); - dev_dbg(&pdev->dev, "Device Probed.\n"); + dev_dbg(dev, "Device Probed.\n"); return 0; - -err_free_mem: - kfree(timer); - -err_free_ioregion: - release_mem_region(mem->start, resource_size(mem)); - - return ret; } /** @@ -788,7 +770,6 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev) list_for_each_entry(timer, &omap_timer_list, node) if (timer->pdev->id == pdev->id) { list_del(&timer->node); - kfree(timer); ret = 0; break; } -- cgit v1.2.3