aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-11-28 19:18:27 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-11-28 19:18:27 -0500
commitef9cc993cd2e3524d86e86e9ad510e8f34b9c078 (patch)
tree4596a532436b30268c493377a4cd0bde658ce159 /drivers/base
parentaf261127e94c286c08bba162711307863fd4e68c (diff)
parent471f7707b6f0b18b6aa81119ed01525d9e712427 (diff)
Merge branch 'pm-clk' into pm-runtime
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/clock_ops.c85
1 files changed, 53 insertions, 32 deletions
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 78369305e069..b32b5d47b3c5 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -12,6 +12,7 @@
12#include <linux/pm.h> 12#include <linux/pm.h>
13#include <linux/pm_clock.h> 13#include <linux/pm_clock.h>
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/clkdev.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
16#include <linux/err.h> 17#include <linux/err.h>
17 18
@@ -34,14 +35,20 @@ struct pm_clock_entry {
34/** 35/**
35 * pm_clk_enable - Enable a clock, reporting any errors 36 * pm_clk_enable - Enable a clock, reporting any errors
36 * @dev: The device for the given clock 37 * @dev: The device for the given clock
37 * @clk: The clock being enabled. 38 * @ce: PM clock entry corresponding to the clock.
38 */ 39 */
39static inline int __pm_clk_enable(struct device *dev, struct clk *clk) 40static inline int __pm_clk_enable(struct device *dev, struct pm_clock_entry *ce)
40{ 41{
41 int ret = clk_enable(clk); 42 int ret;
42 if (ret) 43
43 dev_err(dev, "%s: failed to enable clk %p, error %d\n", 44 if (ce->status < PCE_STATUS_ERROR) {
44 __func__, clk, ret); 45 ret = clk_enable(ce->clk);
46 if (!ret)
47 ce->status = PCE_STATUS_ENABLED;
48 else
49 dev_err(dev, "%s: failed to enable clk %p, error %d\n",
50 __func__, ce->clk, ret);
51 }
45 52
46 return ret; 53 return ret;
47} 54}
@@ -53,7 +60,8 @@ static inline int __pm_clk_enable(struct device *dev, struct clk *clk)
53 */ 60 */
54static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) 61static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
55{ 62{
56 ce->clk = clk_get(dev, ce->con_id); 63 if (!ce->clk)
64 ce->clk = clk_get(dev, ce->con_id);
57 if (IS_ERR(ce->clk)) { 65 if (IS_ERR(ce->clk)) {
58 ce->status = PCE_STATUS_ERROR; 66 ce->status = PCE_STATUS_ERROR;
59 } else { 67 } else {
@@ -63,15 +71,8 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
63 } 71 }
64} 72}
65 73
66/** 74static int __pm_clk_add(struct device *dev, const char *con_id,
67 * pm_clk_add - Start using a device clock for power management. 75 struct clk *clk)
68 * @dev: Device whose clock is going to be used for power management.
69 * @con_id: Connection ID of the clock.
70 *
71 * Add the clock represented by @con_id to the list of clocks used for
72 * the power management of @dev.
73 */
74int pm_clk_add(struct device *dev, const char *con_id)
75{ 76{
76 struct pm_subsys_data *psd = dev_to_psd(dev); 77 struct pm_subsys_data *psd = dev_to_psd(dev);
77 struct pm_clock_entry *ce; 78 struct pm_clock_entry *ce;
@@ -93,6 +94,12 @@ int pm_clk_add(struct device *dev, const char *con_id)
93 kfree(ce); 94 kfree(ce);
94 return -ENOMEM; 95 return -ENOMEM;
95 } 96 }
97 } else {
98 if (IS_ERR(ce->clk) || !__clk_get(clk)) {
99 kfree(ce);
100 return -ENOENT;
101 }
102 ce->clk = clk;
96 } 103 }
97 104
98 pm_clk_acquire(dev, ce); 105 pm_clk_acquire(dev, ce);
@@ -104,6 +111,32 @@ int pm_clk_add(struct device *dev, const char *con_id)
104} 111}
105 112
106/** 113/**
114 * pm_clk_add - Start using a device clock for power management.
115 * @dev: Device whose clock is going to be used for power management.
116 * @con_id: Connection ID of the clock.
117 *
118 * Add the clock represented by @con_id to the list of clocks used for
119 * the power management of @dev.
120 */
121int pm_clk_add(struct device *dev, const char *con_id)
122{
123 return __pm_clk_add(dev, con_id, NULL);
124}
125
126/**
127 * pm_clk_add_clk - Start using a device clock for power management.
128 * @dev: Device whose clock is going to be used for power management.
129 * @clk: Clock pointer
130 *
131 * Add the clock to the list of clocks used for the power management of @dev.
132 * It will increment refcount on clock pointer, use clk_put() on it when done.
133 */
134int pm_clk_add_clk(struct device *dev, struct clk *clk)
135{
136 return __pm_clk_add(dev, NULL, clk);
137}
138
139/**
107 * __pm_clk_remove - Destroy PM clock entry. 140 * __pm_clk_remove - Destroy PM clock entry.
108 * @ce: PM clock entry to destroy. 141 * @ce: PM clock entry to destroy.
109 */ 142 */
@@ -266,7 +299,6 @@ int pm_clk_resume(struct device *dev)
266 struct pm_subsys_data *psd = dev_to_psd(dev); 299 struct pm_subsys_data *psd = dev_to_psd(dev);
267 struct pm_clock_entry *ce; 300 struct pm_clock_entry *ce;
268 unsigned long flags; 301 unsigned long flags;
269 int ret;
270 302
271 dev_dbg(dev, "%s()\n", __func__); 303 dev_dbg(dev, "%s()\n", __func__);
272 304
@@ -275,13 +307,8 @@ int pm_clk_resume(struct device *dev)
275 307
276 spin_lock_irqsave(&psd->lock, flags); 308 spin_lock_irqsave(&psd->lock, flags);
277 309
278 list_for_each_entry(ce, &psd->clock_list, node) { 310 list_for_each_entry(ce, &psd->clock_list, node)
279 if (ce->status < PCE_STATUS_ERROR) { 311 __pm_clk_enable(dev, ce);
280 ret = __pm_clk_enable(dev, ce->clk);
281 if (!ret)
282 ce->status = PCE_STATUS_ENABLED;
283 }
284 }
285 312
286 spin_unlock_irqrestore(&psd->lock, flags); 313 spin_unlock_irqrestore(&psd->lock, flags);
287 314
@@ -390,7 +417,6 @@ int pm_clk_resume(struct device *dev)
390 struct pm_subsys_data *psd = dev_to_psd(dev); 417 struct pm_subsys_data *psd = dev_to_psd(dev);
391 struct pm_clock_entry *ce; 418 struct pm_clock_entry *ce;
392 unsigned long flags; 419 unsigned long flags;
393 int ret;
394 420
395 dev_dbg(dev, "%s()\n", __func__); 421 dev_dbg(dev, "%s()\n", __func__);
396 422
@@ -400,13 +426,8 @@ int pm_clk_resume(struct device *dev)
400 426
401 spin_lock_irqsave(&psd->lock, flags); 427 spin_lock_irqsave(&psd->lock, flags);
402 428
403 list_for_each_entry(ce, &psd->clock_list, node) { 429 list_for_each_entry(ce, &psd->clock_list, node)
404 if (ce->status < PCE_STATUS_ERROR) { 430 __pm_clk_enable(dev, ce);
405 ret = __pm_clk_enable(dev, ce->clk);
406 if (!ret)
407 ce->status = PCE_STATUS_ENABLED;
408 }
409 }
410 431
411 spin_unlock_irqrestore(&psd->lock, flags); 432 spin_unlock_irqrestore(&psd->lock, flags);
412 433