4a8e5c4c6e6b2c875919a6e883cff6041696b1ba
[openwrt/staging/xback.git] /
1 From 9934a1bd45b2b03f6d1204a6ae2780d3b009799f Mon Sep 17 00:00:00 2001
2 From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
3 Date: Mon, 5 Aug 2024 10:57:31 +0200
4 Subject: [PATCH] clk: provide devm_clk_get_optional_enabled_with_rate()
5
6 There are clock users in the kernel that can't use
7 devm_clk_get_optional_enabled() as they need to set rate after getting
8 the clock and before enabling it. Provide a managed helper that wraps
9 these operations in the correct order.
10
11 Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
12 Link: https://lore.kernel.org/r/20240805-clk-new-helper-v2-1-e5fdd1e1d729@linaro.org
13 Signed-off-by: Stephen Boyd <sboyd@kernel.org>
14 ---
15 drivers/clk/clk-devres.c | 28 ++++++++++++++++++++++++++++
16 include/linux/clk.h | 33 +++++++++++++++++++++++++++++++++
17 2 files changed, 61 insertions(+)
18
19 --- a/drivers/clk/clk-devres.c
20 +++ b/drivers/clk/clk-devres.c
21 @@ -99,6 +99,34 @@ struct clk *devm_clk_get_optional_enable
22 }
23 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
24
25 +struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
26 + const char *id,
27 + unsigned long rate)
28 +{
29 + struct clk *clk;
30 + int ret;
31 +
32 + clk = __devm_clk_get(dev, id, clk_get_optional, NULL,
33 + clk_disable_unprepare);
34 + if (IS_ERR(clk))
35 + return ERR_CAST(clk);
36 +
37 + ret = clk_set_rate(clk, rate);
38 + if (ret)
39 + goto out_put_clk;
40 +
41 + ret = clk_prepare_enable(clk);
42 + if (ret)
43 + goto out_put_clk;
44 +
45 + return clk;
46 +
47 +out_put_clk:
48 + devm_clk_put(dev, clk);
49 + return ERR_PTR(ret);
50 +}
51 +EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled_with_rate);
52 +
53 struct clk_bulk_devres {
54 struct clk_bulk_data *clks;
55 int num_clks;
56 --- a/include/linux/clk.h
57 +++ b/include/linux/clk.h
58 @@ -608,6 +608,32 @@ struct clk *devm_clk_get_optional_prepar
59 struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id);
60
61 /**
62 + * devm_clk_get_optional_enabled_with_rate - devm_clk_get_optional() +
63 + * clk_set_rate() +
64 + * clk_prepare_enable()
65 + * @dev: device for clock "consumer"
66 + * @id: clock consumer ID
67 + * @rate: new clock rate
68 + *
69 + * Context: May sleep.
70 + *
71 + * Return: a struct clk corresponding to the clock producer, or
72 + * valid IS_ERR() condition containing errno. The implementation
73 + * uses @dev and @id to determine the clock consumer, and thereby
74 + * the clock producer. If no such clk is found, it returns NULL
75 + * which serves as a dummy clk. That's the only difference compared
76 + * to devm_clk_get_enabled().
77 + *
78 + * The returned clk (if valid) is prepared and enabled and rate was set.
79 + *
80 + * The clock will automatically be disabled, unprepared and freed
81 + * when the device is unbound from the bus.
82 + */
83 +struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
84 + const char *id,
85 + unsigned long rate);
86 +
87 +/**
88 * devm_get_clk_from_child - lookup and obtain a managed reference to a
89 * clock producer from child node.
90 * @dev: device for clock "consumer"
91 @@ -948,6 +974,13 @@ static inline struct clk *devm_clk_get_o
92 {
93 return NULL;
94 }
95 +
96 +static inline struct clk *
97 +devm_clk_get_optional_enabled_with_rate(struct device *dev, const char *id,
98 + unsigned long rate)
99 +{
100 + return NULL;
101 +}
102
103 static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
104 struct clk_bulk_data *clks)