PM / devfreq: devbw: Add suspend/resume APIs

Absence of traffic is guaranteed when the device sitting behind a devbw
device is suspended. In such cases, it is a waste of power to make non-zero
bandwidth votes or to scale the devbw device. So, provide APIs to
suspend/resume the devbw device as needed.

Change-Id: Id58072aec7a9710eb917f248d9b9bd08d3a1ec6a
Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
This commit is contained in:
Saravana Kannan 2014-08-07 20:04:45 -07:00 • committed by Stephen Boyd
commit 217b9b113c
3 changed files with 40 additions and 9 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -237,7 +237,6 @@ static void stop_bw_hwmon(struct bw_hwmon *hw)
{
struct bwmon *m = to_bwmon(hw);
disable_irq(m->irq);
free_irq(m->irq, m);
mon_disable(m);
mon_irq_disable(m);
@ -249,7 +248,7 @@ static int suspend_bw_hwmon(struct bw_hwmon *hw)
{
struct bwmon *m = to_bwmon(hw);
disable_irq(m->irq);
free_irq(m->irq, m);
mon_disable(m);
mon_irq_disable(m);
mon_irq_clear(m);
@ -260,11 +259,19 @@ static int suspend_bw_hwmon(struct bw_hwmon *hw)
static int resume_bw_hwmon(struct bw_hwmon *hw)
{
struct bwmon *m = to_bwmon(hw);
int ret;
mon_clear(m);
mon_irq_enable(m);
mon_enable(m);
enable_irq(m->irq);
ret = request_threaded_irq(m->irq, NULL, bwmon_intr_handler,
IRQF_ONESHOT | IRQF_SHARED,
dev_name(m->dev), m);
if (ret) {
dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
ret);
return ret;
}
return 0;
}

View file

@ -214,11 +214,6 @@ int devfreq_add_devbw(struct device *dev)
return 0;
}
static int devfreq_devbw_probe(struct platform_device *pdev)
{
return devfreq_add_devbw(&pdev->dev);
}
int devfreq_remove_devbw(struct device *dev)
{
struct dev_data *d = dev_get_drvdata(dev);
@ -228,6 +223,25 @@ int devfreq_remove_devbw(struct device *dev)
return 0;
}
int devfreq_suspend_devbw(struct device *dev)
{
struct dev_data *d = dev_get_drvdata(dev);
return devfreq_suspend_device(d->df);
}
int devfreq_resume_devbw(struct device *dev)
{
struct dev_data *d = dev_get_drvdata(dev);
return devfreq_resume_device(d->df);
}
static int devfreq_devbw_probe(struct platform_device *pdev)
{
return devfreq_add_devbw(&pdev->dev);
}
static int devfreq_devbw_remove(struct platform_device *pdev)
{
return devfreq_remove_devbw(&pdev->dev);

View file

@ -19,6 +19,8 @@
#ifdef CONFIG_MSM_DEVFREQ_DEVBW
int devfreq_add_devbw(struct device *dev);
int devfreq_remove_devbw(struct device *dev);
int devfreq_suspend_devbw(struct device *dev);
int devfreq_resume_devbw(struct device *dev);
#else
static inline int devfreq_add_devbw(struct device *dev)
{
@ -28,6 +30,14 @@ static inline int devfreq_remove_devbw(struct device *dev)
{
return 0;
}
static inline int devfreq_suspend_devbw(struct device *dev)
{
return 0;
}
static inline int devfreq_resume_devbw(struct device *dev)
{
return 0;
}
#endif
#endif /* _DEVFREQ_DEVBW_H */