summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Makefile2
-rw-r--r--drivers/clocksource/bcm2835_timer.c161
-rw-r--r--drivers/clocksource/sh_cmt.c71
-rw-r--r--drivers/clocksource/sh_mtu2.c41
-rw-r--r--drivers/clocksource/sh_tmu.c112
5 files changed, 367 insertions, 20 deletions
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 65919901a30..603be366f76 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -13,4 +13,6 @@ obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o
+obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
+
obj-$(CONFIG_CLKSRC_ARM_GENERIC) += arm_generic.o
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
new file mode 100644
index 00000000000..bc19f12c20c
--- /dev/null
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bcm2835_timer.h>
+#include <linux/bitops.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/sched_clock.h>
+#include <asm/irq.h>
+
+#define REG_CONTROL 0x00
+#define REG_COUNTER_LO 0x04
+#define REG_COUNTER_HI 0x08
+#define REG_COMPARE(n) (0x0c + (n) * 4)
+#define MAX_TIMER 3
+#define DEFAULT_TIMER 3
+
+struct bcm2835_timer {
+ void __iomem *control;
+ void __iomem *compare;
+ int match_mask;
+ struct clock_event_device evt;
+ struct irqaction act;
+};
+
+static void __iomem *system_clock __read_mostly;
+
+static u32 notrace bcm2835_sched_read(void)
+{
+ return readl_relaxed(system_clock);
+}
+
+static void bcm2835_time_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt_dev)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+ default:
+ WARN(1, "%s: unhandled event mode %d\n", __func__, mode);
+ break;
+ }
+}
+
+static int bcm2835_time_set_next_event(unsigned long event,
+ struct clock_event_device *evt_dev)
+{
+ struct bcm2835_timer *timer = container_of(evt_dev,
+ struct bcm2835_timer, evt);
+ writel_relaxed(readl_relaxed(system_clock) + event,
+ timer->compare);
+ return 0;
+}
+
+static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id)
+{
+ struct bcm2835_timer *timer = dev_id;
+ void (*event_handler)(struct clock_event_device *);
+ if (readl_relaxed(timer->control) & timer->match_mask) {
+ writel_relaxed(timer->match_mask, timer->control);
+
+ event_handler = ACCESS_ONCE(timer->evt.event_handler);
+ if (event_handler)
+ event_handler(&timer->evt);
+ return IRQ_HANDLED;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static struct of_device_id bcm2835_time_match[] __initconst = {
+ { .compatible = "brcm,bcm2835-system-timer" },
+ {}
+};
+
+static void __init bcm2835_time_init(void)
+{
+ struct device_node *node;
+ void __iomem *base;
+ u32 freq;
+ int irq;
+ struct bcm2835_timer *timer;
+
+ node = of_find_matching_node(NULL, bcm2835_time_match);
+ if (!node)
+ panic("No bcm2835 timer node");
+
+ base = of_iomap(node, 0);
+ if (!base)
+ panic("Can't remap registers");
+
+ if (of_property_read_u32(node, "clock-frequency", &freq))
+ panic("Can't read clock-frequency");
+
+ system_clock = base + REG_COUNTER_LO;
+ setup_sched_clock(bcm2835_sched_read, 32, freq);
+
+ clocksource_mmio_init(base + REG_COUNTER_LO, node->name,
+ freq, 300, 32, clocksource_mmio_readl_up);
+
+ irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
+ if (irq <= 0)
+ panic("Can't parse IRQ");
+
+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+ if (!timer)
+ panic("Can't allocate timer struct\n");
+
+ timer->control = base + REG_CONTROL;
+ timer->compare = base + REG_COMPARE(DEFAULT_TIMER);
+ timer->match_mask = BIT(DEFAULT_TIMER);
+ timer->evt.name = node->name;
+ timer->evt.rating = 300;
+ timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
+ timer->evt.set_mode = bcm2835_time_set_mode;
+ timer->evt.set_next_event = bcm2835_time_set_next_event;
+ timer->evt.cpumask = cpumask_of(0);
+ timer->act.name = node->name;
+ timer->act.flags = IRQF_TIMER | IRQF_SHARED;
+ timer->act.dev_id = timer;
+ timer->act.handler = bcm2835_time_interrupt;
+
+ if (setup_irq(irq, &timer->act))
+ panic("Can't set up timer IRQ\n");
+
+ clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
+
+ pr_info("bcm2835: system timer (irq = %d)\n", irq);
+}
+
+struct sys_timer bcm2835_timer = {
+ .init = bcm2835_time_init,
+};
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 98b06baafcc..a5f7829f279 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
struct sh_cmt_priv {
void __iomem *mapbase;
@@ -52,6 +53,7 @@ struct sh_cmt_priv {
struct clock_event_device ced;
struct clocksource cs;
unsigned long total_cycles;
+ bool cs_enabled;
};
static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
@@ -155,6 +157,9 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
{
int k, ret;
+ pm_runtime_get_sync(&p->pdev->dev);
+ dev_pm_syscore_device(&p->pdev->dev, true);
+
/* enable clock */
ret = clk_enable(p->clk);
if (ret) {
@@ -221,6 +226,9 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
/* stop clock */
clk_disable(p->clk);
+
+ dev_pm_syscore_device(&p->pdev->dev, false);
+ pm_runtime_put(&p->pdev->dev);
}
/* private flags */
@@ -451,22 +459,42 @@ static int sh_cmt_clocksource_enable(struct clocksource *cs)
int ret;
struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+ WARN_ON(p->cs_enabled);
+
p->total_cycles = 0;
ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
- if (!ret)
+ if (!ret) {
__clocksource_updatefreq_hz(cs, p->rate);
+ p->cs_enabled = true;
+ }
return ret;
}
static void sh_cmt_clocksource_disable(struct clocksource *cs)
{
- sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+ struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+
+ WARN_ON(!p->cs_enabled);
+
+ sh_cmt_stop(p, FLAG_CLOCKSOURCE);
+ p->cs_enabled = false;
+}
+
+static void sh_cmt_clocksource_suspend(struct clocksource *cs)
+{
+ struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+
+ sh_cmt_stop(p, FLAG_CLOCKSOURCE);
+ pm_genpd_syscore_poweroff(&p->pdev->dev);
}
static void sh_cmt_clocksource_resume(struct clocksource *cs)
{
- sh_cmt_start(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+ struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+
+ pm_genpd_syscore_poweron(&p->pdev->dev);
+ sh_cmt_start(p, FLAG_CLOCKSOURCE);
}
static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
@@ -479,7 +507,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
cs->read = sh_cmt_clocksource_read;
cs->enable = sh_cmt_clocksource_enable;
cs->disable = sh_cmt_clocksource_disable;
- cs->suspend = sh_cmt_clocksource_disable;
+ cs->suspend = sh_cmt_clocksource_suspend;
cs->resume = sh_cmt_clocksource_resume;
cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
@@ -562,6 +590,16 @@ static int sh_cmt_clock_event_next(unsigned long delta,
return 0;
}
+static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
+{
+ pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev);
+}
+
+static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
+{
+ pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev);
+}
+
static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
char *name, unsigned long rating)
{
@@ -576,6 +614,8 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
ced->cpumask = cpumask_of(0);
ced->set_next_event = sh_cmt_clock_event_next;
ced->set_mode = sh_cmt_clock_event_mode;
+ ced->suspend = sh_cmt_clock_event_suspend;
+ ced->resume = sh_cmt_clock_event_resume;
dev_info(&p->pdev->dev, "used for clock events\n");
clockevents_register_device(ced);
@@ -670,6 +710,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
dev_err(&p->pdev->dev, "registration failed\n");
goto err1;
}
+ p->cs_enabled = false;
ret = setup_irq(irq, &p->irqaction);
if (ret) {
@@ -688,14 +729,17 @@ err0:
static int __devinit sh_cmt_probe(struct platform_device *pdev)
{
struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
int ret;
- if (!is_early_platform_device(pdev))
- pm_genpd_dev_always_on(&pdev->dev, true);
+ if (!is_early_platform_device(pdev)) {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
if (p) {
dev_info(&pdev->dev, "kept as earlytimer\n");
- return 0;
+ goto out;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -708,8 +752,19 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
if (ret) {
kfree(p);
platform_set_drvdata(pdev, NULL);
+ pm_runtime_idle(&pdev->dev);
+ return ret;
}
- return ret;
+ if (is_early_platform_device(pdev))
+ return 0;
+
+ out:
+ if (cfg->clockevent_rating || cfg->clocksource_rating)
+ pm_runtime_irq_safe(&pdev->dev);
+ else
+ pm_runtime_idle(&pdev->dev);
+
+ return 0;
}
static int __devexit sh_cmt_remove(struct platform_device *pdev)
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index d9b76ca64a6..c5eea858054 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -32,6 +32,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
struct sh_mtu2_priv {
void __iomem *mapbase;
@@ -123,6 +124,9 @@ static int sh_mtu2_enable(struct sh_mtu2_priv *p)
{
int ret;
+ pm_runtime_get_sync(&p->pdev->dev);
+ dev_pm_syscore_device(&p->pdev->dev, true);
+
/* enable clock */
ret = clk_enable(p->clk);
if (ret) {
@@ -157,6 +161,9 @@ static void sh_mtu2_disable(struct sh_mtu2_priv *p)
/* stop clock */
clk_disable(p->clk);
+
+ dev_pm_syscore_device(&p->pdev->dev, false);
+ pm_runtime_put(&p->pdev->dev);
}
static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id)
@@ -208,6 +215,16 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
}
}
+static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced)
+{
+ pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->pdev->dev);
+}
+
+static void sh_mtu2_clock_event_resume(struct clock_event_device *ced)
+{
+ pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->pdev->dev);
+}
+
static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
char *name, unsigned long rating)
{
@@ -221,6 +238,8 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
ced->rating = rating;
ced->cpumask = cpumask_of(0);
ced->set_mode = sh_mtu2_clock_event_mode;
+ ced->suspend = sh_mtu2_clock_event_suspend;
+ ced->resume = sh_mtu2_clock_event_resume;
dev_info(&p->pdev->dev, "used for clock events\n");
clockevents_register_device(ced);
@@ -305,14 +324,17 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
static int __devinit sh_mtu2_probe(struct platform_device *pdev)
{
struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
int ret;
- if (!is_early_platform_device(pdev))
- pm_genpd_dev_always_on(&pdev->dev, true);
+ if (!is_early_platform_device(pdev)) {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
if (p) {
dev_info(&pdev->dev, "kept as earlytimer\n");
- return 0;
+ goto out;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -325,8 +347,19 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev)
if (ret) {
kfree(p);
platform_set_drvdata(pdev, NULL);
+ pm_runtime_idle(&pdev->dev);
+ return ret;
}
- return ret;
+ if (is_early_platform_device(pdev))
+ return 0;
+
+ out:
+ if (cfg->clockevent_rating)
+ pm_runtime_irq_safe(&pdev->dev);
+ else
+ pm_runtime_idle(&pdev->dev);
+
+ return 0;
}
static int __devexit sh_mtu2_remove(struct platform_device *pdev)
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index c1b51d49d10..0cc4add8827 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -33,6 +33,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
struct sh_tmu_priv {
void __iomem *mapbase;
@@ -43,6 +44,8 @@ struct sh_tmu_priv {
unsigned long periodic;
struct clock_event_device ced;
struct clocksource cs;
+ bool cs_enabled;
+ unsigned int enable_count;
};
static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
@@ -107,7 +110,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
}
-static int sh_tmu_enable(struct sh_tmu_priv *p)
+static int __sh_tmu_enable(struct sh_tmu_priv *p)
{
int ret;
@@ -135,7 +138,18 @@ static int sh_tmu_enable(struct sh_tmu_priv *p)
return 0;
}
-static void sh_tmu_disable(struct sh_tmu_priv *p)
+static int sh_tmu_enable(struct sh_tmu_priv *p)
+{
+ if (p->enable_count++ > 0)
+ return 0;
+
+ pm_runtime_get_sync(&p->pdev->dev);
+ dev_pm_syscore_device(&p->pdev->dev, true);
+
+ return __sh_tmu_enable(p);
+}
+
+static void __sh_tmu_disable(struct sh_tmu_priv *p)
{
/* disable channel */
sh_tmu_start_stop_ch(p, 0);
@@ -147,6 +161,20 @@ static void sh_tmu_disable(struct sh_tmu_priv *p)
clk_disable(p->clk);
}
+static void sh_tmu_disable(struct sh_tmu_priv *p)
+{
+ if (WARN_ON(p->enable_count == 0))
+ return;
+
+ if (--p->enable_count > 0)
+ return;
+
+ __sh_tmu_disable(p);
+
+ dev_pm_syscore_device(&p->pdev->dev, false);
+ pm_runtime_put(&p->pdev->dev);
+}
+
static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
int periodic)
{
@@ -203,15 +231,53 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs)
struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
int ret;
+ if (WARN_ON(p->cs_enabled))
+ return 0;
+
ret = sh_tmu_enable(p);
- if (!ret)
+ if (!ret) {
__clocksource_updatefreq_hz(cs, p->rate);
+ p->cs_enabled = true;
+ }
+
return ret;
}
static void sh_tmu_clocksource_disable(struct clocksource *cs)
{
- sh_tmu_disable(cs_to_sh_tmu(cs));
+ struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+ if (WARN_ON(!p->cs_enabled))
+ return;
+
+ sh_tmu_disable(p);
+ p->cs_enabled = false;
+}
+
+static void sh_tmu_clocksource_suspend(struct clocksource *cs)
+{
+ struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+ if (!p->cs_enabled)
+ return;
+
+ if (--p->enable_count == 0) {
+ __sh_tmu_disable(p);
+ pm_genpd_syscore_poweroff(&p->pdev->dev);
+ }
+}
+
+static void sh_tmu_clocksource_resume(struct clocksource *cs)
+{
+ struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+ if (!p->cs_enabled)
+ return;
+
+ if (p->enable_count++ == 0) {
+ pm_genpd_syscore_poweron(&p->pdev->dev);
+ __sh_tmu_enable(p);
+ }
}
static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
@@ -224,6 +290,8 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
cs->read = sh_tmu_clocksource_read;
cs->enable = sh_tmu_clocksource_enable;
cs->disable = sh_tmu_clocksource_disable;
+ cs->suspend = sh_tmu_clocksource_suspend;
+ cs->resume = sh_tmu_clocksource_resume;
cs->mask = CLOCKSOURCE_MASK(32);
cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
@@ -301,6 +369,16 @@ static int sh_tmu_clock_event_next(unsigned long delta,
return 0;
}
+static void sh_tmu_clock_event_suspend(struct clock_event_device *ced)
+{
+ pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->pdev->dev);
+}
+
+static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
+{
+ pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->pdev->dev);
+}
+
static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
char *name, unsigned long rating)
{
@@ -316,6 +394,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
ced->cpumask = cpumask_of(0);
ced->set_next_event = sh_tmu_clock_event_next;
ced->set_mode = sh_tmu_clock_event_mode;
+ ced->suspend = sh_tmu_clock_event_suspend;
+ ced->resume = sh_tmu_clock_event_resume;
dev_info(&p->pdev->dev, "used for clock events\n");
@@ -392,6 +472,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
ret = PTR_ERR(p->clk);
goto err1;
}
+ p->cs_enabled = false;
+ p->enable_count = 0;
return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
cfg->clockevent_rating,
@@ -405,14 +487,17 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
static int __devinit sh_tmu_probe(struct platform_device *pdev)
{
struct sh_tmu_priv *p = platform_get_drvdata(pdev);
+ struct sh_timer_config *cfg = pdev->dev.platform_data;
int ret;
- if (!is_early_platform_device(pdev))
- pm_genpd_dev_always_on(&pdev->dev, true);
+ if (!is_early_platform_device(pdev)) {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
if (p) {
dev_info(&pdev->dev, "kept as earlytimer\n");
- return 0;
+ goto out;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -425,8 +510,19 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
if (ret) {
kfree(p);
platform_set_drvdata(pdev, NULL);
+ pm_runtime_idle(&pdev->dev);
+ return ret;
}
- return ret;
+ if (is_early_platform_device(pdev))
+ return 0;
+
+ out:
+ if (cfg->clockevent_rating || cfg->clocksource_rating)
+ pm_runtime_irq_safe(&pdev->dev);
+ else
+ pm_runtime_idle(&pdev->dev);
+
+ return 0;
}
static int __devexit sh_tmu_remove(struct platform_device *pdev)