diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/clkdev.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 6db161f64ae0..a9a113782821 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c | |||
@@ -89,6 +89,51 @@ void clk_put(struct clk *clk) | |||
89 | } | 89 | } |
90 | EXPORT_SYMBOL(clk_put); | 90 | EXPORT_SYMBOL(clk_put); |
91 | 91 | ||
92 | static void devm_clk_release(struct device *dev, void *res) | ||
93 | { | ||
94 | clk_put(*(struct clk **)res); | ||
95 | } | ||
96 | |||
97 | struct clk *devm_clk_get(struct device *dev, const char *id) | ||
98 | { | ||
99 | struct clk **ptr, *clk; | ||
100 | |||
101 | ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); | ||
102 | if (!ptr) | ||
103 | return ERR_PTR(-ENOMEM); | ||
104 | |||
105 | clk = clk_get(dev, id); | ||
106 | if (!IS_ERR(clk)) { | ||
107 | *ptr = clk; | ||
108 | devres_add(dev, ptr); | ||
109 | } else { | ||
110 | devres_free(ptr); | ||
111 | } | ||
112 | |||
113 | return clk; | ||
114 | } | ||
115 | EXPORT_SYMBOL(devm_clk_get); | ||
116 | |||
117 | static int devm_clk_match(struct device *dev, void *res, void *data) | ||
118 | { | ||
119 | struct clk **c = res; | ||
120 | if (!c || !*c) { | ||
121 | WARN_ON(!c || !*c); | ||
122 | return 0; | ||
123 | } | ||
124 | return *c == data; | ||
125 | } | ||
126 | |||
127 | void devm_clk_put(struct device *dev, struct clk *clk) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk); | ||
132 | |||
133 | WARN_ON(ret); | ||
134 | } | ||
135 | EXPORT_SYMBOL(devm_clk_put); | ||
136 | |||
92 | void clkdev_add(struct clk_lookup *cl) | 137 | void clkdev_add(struct clk_lookup *cl) |
93 | { | 138 | { |
94 | mutex_lock(&clocks_mutex); | 139 | mutex_lock(&clocks_mutex); |