aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/clock_ops.c47
-rw-r--r--include/linux/pm_clock.h8
2 files changed, 45 insertions, 10 deletions
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index 78369305e069..f061eaa48bb5 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
@@ -53,7 +54,8 @@ static inline int __pm_clk_enable(struct device *dev, struct clk *clk)
53 */ 54 */
54static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) 55static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
55{ 56{
56 ce->clk = clk_get(dev, ce->con_id); 57 if (!ce->clk)
58 ce->clk = clk_get(dev, ce->con_id);
57 if (IS_ERR(ce->clk)) { 59 if (IS_ERR(ce->clk)) {
58 ce->status = PCE_STATUS_ERROR; 60 ce->status = PCE_STATUS_ERROR;
59 } else { 61 } else {
@@ -63,15 +65,8 @@ static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce)
63 } 65 }
64} 66}
65 67
66/** 68static int __pm_clk_add(struct device *dev, const char *con_id,
67 * pm_clk_add - Start using a device clock for power management. 69 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{ 70{
76 struct pm_subsys_data *psd = dev_to_psd(dev); 71 struct pm_subsys_data *psd = dev_to_psd(dev);
77 struct pm_clock_entry *ce; 72 struct pm_clock_entry *ce;
@@ -93,6 +88,12 @@ int pm_clk_add(struct device *dev, const char *con_id)
93 kfree(ce); 88 kfree(ce);
94 return -ENOMEM; 89 return -ENOMEM;
95 } 90 }
91 } else {
92 if (IS_ERR(ce->clk) || !__clk_get(clk)) {
93 kfree(ce);
94 return -ENOENT;
95 }
96 ce->clk = clk;
96 } 97 }
97 98
98 pm_clk_acquire(dev, ce); 99 pm_clk_acquire(dev, ce);
@@ -104,6 +105,32 @@ int pm_clk_add(struct device *dev, const char *con_id)
104} 105}
105 106
106/** 107/**
108 * pm_clk_add - Start using a device clock for power management.
109 * @dev: Device whose clock is going to be used for power management.
110 * @con_id: Connection ID of the clock.
111 *
112 * Add the clock represented by @con_id to the list of clocks used for
113 * the power management of @dev.
114 */
115int pm_clk_add(struct device *dev, const char *con_id)
116{
117 return __pm_clk_add(dev, con_id, NULL);
118}
119
120/**
121 * pm_clk_add_clk - Start using a device clock for power management.
122 * @dev: Device whose clock is going to be used for power management.
123 * @clk: Clock pointer
124 *
125 * Add the clock to the list of clocks used for the power management of @dev.
126 * It will increment refcount on clock pointer, use clk_put() on it when done.
127 */
128int pm_clk_add_clk(struct device *dev, struct clk *clk)
129{
130 return __pm_clk_add(dev, NULL, clk);
131}
132
133/**
107 * __pm_clk_remove - Destroy PM clock entry. 134 * __pm_clk_remove - Destroy PM clock entry.
108 * @ce: PM clock entry to destroy. 135 * @ce: PM clock entry to destroy.
109 */ 136 */
diff --git a/include/linux/pm_clock.h b/include/linux/pm_clock.h
index 8348866e7b05..0b0039634410 100644
--- a/include/linux/pm_clock.h
+++ b/include/linux/pm_clock.h
@@ -18,6 +18,8 @@ struct pm_clk_notifier_block {
18 char *con_ids[]; 18 char *con_ids[];
19}; 19};
20 20
21struct clk;
22
21#ifdef CONFIG_PM_CLK 23#ifdef CONFIG_PM_CLK
22static inline bool pm_clk_no_clocks(struct device *dev) 24static inline bool pm_clk_no_clocks(struct device *dev)
23{ 25{
@@ -29,6 +31,7 @@ extern void pm_clk_init(struct device *dev);
29extern int pm_clk_create(struct device *dev); 31extern int pm_clk_create(struct device *dev);
30extern void pm_clk_destroy(struct device *dev); 32extern void pm_clk_destroy(struct device *dev);
31extern int pm_clk_add(struct device *dev, const char *con_id); 33extern int pm_clk_add(struct device *dev, const char *con_id);
34extern int pm_clk_add_clk(struct device *dev, struct clk *clk);
32extern void pm_clk_remove(struct device *dev, const char *con_id); 35extern void pm_clk_remove(struct device *dev, const char *con_id);
33extern int pm_clk_suspend(struct device *dev); 36extern int pm_clk_suspend(struct device *dev);
34extern int pm_clk_resume(struct device *dev); 37extern int pm_clk_resume(struct device *dev);
@@ -51,6 +54,11 @@ static inline int pm_clk_add(struct device *dev, const char *con_id)
51{ 54{
52 return -EINVAL; 55 return -EINVAL;
53} 56}
57
58static inline int pm_clk_add_clk(struct device *dev, struct clk *clk)
59{
60 return -EINVAL;
61}
54static inline void pm_clk_remove(struct device *dev, const char *con_id) 62static inline void pm_clk_remove(struct device *dev, const char *con_id)
55{ 63{
56} 64}