Skip to content

Commit abae8e5

Browse files
Uwe Kleine-Königbebarino
authored andcommitted
clk: generalize devm_clk_get() a bit
Allow to add an exit hook to devm managed clocks. Also use clk_get_optional() in devm_clk_get_optional instead of open coding it. The generalisation will be used in the next commit to add some more devm_clk helpers. Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Alexandru Ardelean <aardelean@deviqon.com> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Link: https://lore.kernel.org/r/20220520075737.758761-3-u.kleine-koenig@pengutronix.de Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent af89cd4 commit abae8e5

1 file changed

Lines changed: 49 additions & 17 deletions

File tree

drivers/clk/clk-devres.c

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,71 @@
44
#include <linux/export.h>
55
#include <linux/gfp.h>
66

7+
struct devm_clk_state {
8+
struct clk *clk;
9+
void (*exit)(struct clk *clk);
10+
};
11+
712
static void devm_clk_release(struct device *dev, void *res)
813
{
9-
clk_put(*(struct clk **)res);
14+
struct devm_clk_state *state = *(struct devm_clk_state **)res;
15+
16+
if (state->exit)
17+
state->exit(state->clk);
18+
19+
clk_put(state->clk);
1020
}
1121

12-
struct clk *devm_clk_get(struct device *dev, const char *id)
22+
static struct clk *__devm_clk_get(struct device *dev, const char *id,
23+
struct clk *(*get)(struct device *dev, const char *id),
24+
int (*init)(struct clk *clk),
25+
void (*exit)(struct clk *clk))
1326
{
14-
struct clk **ptr, *clk;
27+
struct devm_clk_state *state;
28+
struct clk *clk;
29+
int ret;
1530

16-
ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
17-
if (!ptr)
31+
state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
32+
if (!state)
1833
return ERR_PTR(-ENOMEM);
1934

20-
clk = clk_get(dev, id);
21-
if (!IS_ERR(clk)) {
22-
*ptr = clk;
23-
devres_add(dev, ptr);
24-
} else {
25-
devres_free(ptr);
35+
clk = get(dev, id);
36+
if (IS_ERR(clk)) {
37+
ret = PTR_ERR(clk);
38+
goto err_clk_get;
2639
}
2740

41+
if (init) {
42+
ret = init(clk);
43+
if (ret)
44+
goto err_clk_init;
45+
}
46+
47+
state->clk = clk;
48+
state->exit = exit;
49+
50+
devres_add(dev, state);
51+
2852
return clk;
53+
54+
err_clk_init:
55+
56+
clk_put(clk);
57+
err_clk_get:
58+
59+
devres_free(state);
60+
return ERR_PTR(ret);
61+
}
62+
63+
struct clk *devm_clk_get(struct device *dev, const char *id)
64+
{
65+
return __devm_clk_get(dev, id, clk_get, NULL, NULL);
2966
}
3067
EXPORT_SYMBOL(devm_clk_get);
3168

3269
struct clk *devm_clk_get_optional(struct device *dev, const char *id)
3370
{
34-
struct clk *clk = devm_clk_get(dev, id);
35-
36-
if (clk == ERR_PTR(-ENOENT))
37-
return NULL;
38-
39-
return clk;
71+
return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
4072
}
4173
EXPORT_SYMBOL(devm_clk_get_optional);
4274

0 commit comments

Comments
 (0)