c7857119256f8295cc99f3d677f1db5993d97524
[openwrt/staging/wigyori.git] /
1 From 7599e32a45d303268886ba6b4a08c37e877e42a2 Mon Sep 17 00:00:00 2001
2 From: Samuel Holland <samuel@sholland.org>
3 Date: Wed, 1 Sep 2021 00:05:19 -0500
4 Subject: [PATCH 001/124] clk: sunxi-ng: Unregister clocks/resets when
5 unbinding
6
7 Currently, unbinding a CCU driver unmaps the device's MMIO region, while
8 leaving its clocks/resets and their providers registered. This can cause
9 a page fault later when some clock operation tries to perform MMIO. Fix
10 this by separating the CCU initialization from the memory allocation,
11 and then using a devres callback to unregister the clocks and resets.
12
13 This also fixes a memory leak of the `struct ccu_reset`, and uses the
14 correct owner (the specific platform driver) for the clocks and resets.
15
16 Early OF clock providers are never unregistered, and limited error
17 handling is possible, so they are mostly unchanged. The error reporting
18 is made more consistent by moving the message inside of_sunxi_ccu_probe.
19
20 Signed-off-by: Samuel Holland <samuel@sholland.org>
21 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
22 Link: https://lore.kernel.org/r/20210901050526.45673-2-samuel@sholland.org
23 ---
24 drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 2 +-
25 drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c | 2 +-
26 drivers/clk/sunxi-ng/ccu-sun50i-a100.c | 2 +-
27 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 +-
28 drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 2 +-
29 drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 2 +-
30 drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 4 +-
31 drivers/clk/sunxi-ng/ccu-sun5i.c | 2 +-
32 drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 2 +-
33 drivers/clk/sunxi-ng/ccu-sun8i-a23.c | 2 +-
34 drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 2 +-
35 drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 2 +-
36 drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 2 +-
37 drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
38 drivers/clk/sunxi-ng/ccu-sun8i-r.c | 2 +-
39 drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 2 +-
40 drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | 2 +-
41 drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c | 3 +-
42 drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c | 3 +-
43 drivers/clk/sunxi-ng/ccu-sun9i-a80.c | 2 +-
44 drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c | 2 +-
45 drivers/clk/sunxi-ng/ccu_common.c | 89 ++++++++++++++++++++----
46 drivers/clk/sunxi-ng/ccu_common.h | 6 +-
47 23 files changed, 100 insertions(+), 41 deletions(-)
48
49 diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
50 index f32366d9336e..bd9a8782fec3 100644
51 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
52 +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
53 @@ -1464,7 +1464,7 @@ static void __init sun4i_ccu_init(struct device_node *node,
54 val &= ~GENMASK(7, 6);
55 writel(val | (2 << 6), reg + SUN4I_AHB_REG);
56
57 - sunxi_ccu_probe(node, reg, desc);
58 + of_sunxi_ccu_probe(node, reg, desc);
59 }
60
61 static void __init sun4i_a10_ccu_setup(struct device_node *node)
62 diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
63 index a56142b90993..6f2a58970556 100644
64 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
65 +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
66 @@ -196,7 +196,7 @@ static int sun50i_a100_r_ccu_probe(struct platform_device *pdev)
67 if (IS_ERR(reg))
68 return PTR_ERR(reg);
69
70 - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc);
71 + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_r_ccu_desc);
72 }
73
74 static const struct of_device_id sun50i_a100_r_ccu_ids[] = {
75 diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
76 index 81b48c73d389..913bb08e6dee 100644
77 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
78 +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
79 @@ -1247,7 +1247,7 @@ static int sun50i_a100_ccu_probe(struct platform_device *pdev)
80 writel(val, reg + sun50i_a100_usb2_clk_regs[i]);
81 }
82
83 - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc);
84 + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc);
85 if (ret)
86 return ret;
87
88 diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
89 index 149cfde817cb..54f25c624f02 100644
90 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
91 +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
92 @@ -955,7 +955,7 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
93
94 writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
95
96 - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
97 + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc);
98 if (ret)
99 return ret;
100
101 diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
102 index f8909a7ed553..f30d7eb5424d 100644
103 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
104 +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
105 @@ -232,7 +232,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node,
106 return;
107 }
108
109 - sunxi_ccu_probe(node, reg, desc);
110 + of_sunxi_ccu_probe(node, reg, desc);
111 }
112
113 static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
114 diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
115 index bff446b78290..c0800da2fa3d 100644
116 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
117 +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
118 @@ -1240,7 +1240,7 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
119 val |= BIT(24);
120 writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
121
122 - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
123 + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
124 }
125
126 static const struct of_device_id sun50i_h6_ccu_ids[] = {
127 diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
128 index 225307305880..22eb18079a15 100644
129 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
130 +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
131 @@ -1141,9 +1141,7 @@ static void __init sun50i_h616_ccu_setup(struct device_node *node)
132 val |= BIT(24);
133 writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
134
135 - i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
136 - if (i)
137 - pr_err("%pOF: probing clocks fails: %d\n", node, i);
138 + of_sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
139 }
140
141 CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu",
142 diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c
143 index b78e9b507c1c..1f4bc0e773a7 100644
144 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c
145 +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c
146 @@ -1012,7 +1012,7 @@ static void __init sun5i_ccu_init(struct device_node *node,
147 val &= ~GENMASK(7, 6);
148 writel(val | (2 << 6), reg + SUN5I_AHB_REG);
149
150 - sunxi_ccu_probe(node, reg, desc);
151 + of_sunxi_ccu_probe(node, reg, desc);
152 }
153
154 static void __init sun5i_a10s_ccu_setup(struct device_node *node)
155 diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
156 index 9b40d53266a3..3df5c0b41580 100644
157 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
158 +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
159 @@ -1257,7 +1257,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node)
160 val |= 0x3 << 12;
161 writel(val, reg + SUN6I_A31_AHB1_REG);
162
163 - sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc);
164 + of_sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc);
165
166 ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
167 &sun6i_a31_cpu_nb);
168 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
169 index 103aa504f6c8..577bb235d658 100644
170 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
171 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
172 @@ -745,7 +745,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node)
173 val &= ~BIT(16);
174 writel(val, reg + SUN8I_A23_PLL_MIPI_REG);
175
176 - sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc);
177 + of_sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc);
178 }
179 CLK_OF_DECLARE(sun8i_a23_ccu, "allwinner,sun8i-a23-ccu",
180 sun8i_a23_ccu_setup);
181 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
182 index 91838cd11037..8f65cd03f5ac 100644
183 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
184 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
185 @@ -805,7 +805,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node)
186 val &= ~BIT(16);
187 writel(val, reg + SUN8I_A33_PLL_MIPI_REG);
188
189 - sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc);
190 + of_sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc);
191
192 /* Gate then ungate PLL CPU after any rate changes */
193 ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb);
194 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
195 index 2b434521c5cc..c2ddcd2ddab4 100644
196 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
197 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
198 @@ -906,7 +906,7 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev)
199 sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG);
200 sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG);
201
202 - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_a83t_ccu_desc);
203 + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc);
204 }
205
206 static const struct of_device_id sun8i_a83t_ccu_ids[] = {
207 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
208 index 524f33275bc7..4b94b6041b27 100644
209 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
210 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
211 @@ -342,7 +342,7 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev)
212 goto err_disable_mod_clk;
213 }
214
215 - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
216 + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc);
217 if (ret)
218 goto err_assert_reset;
219
220 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
221 index 7e629a4493af..d2fc2903787d 100644
222 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
223 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
224 @@ -1154,7 +1154,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node,
225 val &= ~GENMASK(19, 16);
226 writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
227
228 - sunxi_ccu_probe(node, reg, desc);
229 + of_sunxi_ccu_probe(node, reg, desc);
230
231 /* Gate then ungate PLL CPU after any rate changes */
232 ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb);
233 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
234 index 4c8c491b87c2..9e754d1f754a 100644
235 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c
236 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
237 @@ -265,7 +265,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node,
238 return;
239 }
240
241 - sunxi_ccu_probe(node, reg, desc);
242 + of_sunxi_ccu_probe(node, reg, desc);
243 }
244
245 static void __init sun8i_a83t_r_ccu_setup(struct device_node *node)
246 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
247 index 84153418453f..002e0c3a04db 100644
248 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
249 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
250 @@ -1346,7 +1346,7 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev)
251 if (IS_ERR(regmap))
252 return PTR_ERR(regmap);
253
254 - ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc);
255 + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_r40_ccu_desc);
256 if (ret)
257 return ret;
258
259 diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
260 index f49724a22540..ce150f83ab54 100644
261 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
262 +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
263 @@ -822,7 +822,7 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node,
264 val &= ~GENMASK(19, 16);
265 writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG);
266
267 - sunxi_ccu_probe(node, reg, ccu_desc);
268 + of_sunxi_ccu_probe(node, reg, ccu_desc);
269 }
270
271 static void __init sun8i_v3s_ccu_setup(struct device_node *node)
272 diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
273 index 6616e8114f62..261e64416f26 100644
274 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
275 +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
276 @@ -246,8 +246,7 @@ static int sun9i_a80_de_clk_probe(struct platform_device *pdev)
277 goto err_disable_clk;
278 }
279
280 - ret = sunxi_ccu_probe(pdev->dev.of_node, reg,
281 - &sun9i_a80_de_clk_desc);
282 + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc);
283 if (ret)
284 goto err_assert_reset;
285
286 diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
287 index 4b4a507d04ed..596243b3e0fa 100644
288 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
289 +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
290 @@ -117,8 +117,7 @@ static int sun9i_a80_usb_clk_probe(struct platform_device *pdev)
291 return ret;
292 }
293
294 - ret = sunxi_ccu_probe(pdev->dev.of_node, reg,
295 - &sun9i_a80_usb_clk_desc);
296 + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_usb_clk_desc);
297 if (ret)
298 goto err_disable_clk;
299
300 diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
301 index ef29582676f6..97aaed0e6850 100644
302 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
303 +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
304 @@ -1231,7 +1231,7 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev)
305 sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
306 sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
307
308 - return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc);
309 + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc);
310 }
311
312 static const struct of_device_id sun9i_a80_ccu_ids[] = {
313 diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
314 index 7ecc3a5a5b5e..61ad7ee91c11 100644
315 --- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
316 +++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
317 @@ -538,7 +538,7 @@ static void __init suniv_f1c100s_ccu_setup(struct device_node *node)
318 val &= ~GENMASK(19, 16);
319 writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG);
320
321 - sunxi_ccu_probe(node, reg, &suniv_ccu_desc);
322 + of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc);
323
324 /* Gate then ungate PLL CPU after any rate changes */
325 ccu_pll_notifier_register(&suniv_pll_cpu_nb);
326 diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
327 index 2e20e650b6c0..88cb569e5835 100644
328 --- a/drivers/clk/sunxi-ng/ccu_common.c
329 +++ b/drivers/clk/sunxi-ng/ccu_common.c
330 @@ -7,6 +7,7 @@
331
332 #include <linux/clk.h>
333 #include <linux/clk-provider.h>
334 +#include <linux/device.h>
335 #include <linux/iopoll.h>
336 #include <linux/slab.h>
337
338 @@ -14,6 +15,11 @@
339 #include "ccu_gate.h"
340 #include "ccu_reset.h"
341
342 +struct sunxi_ccu {
343 + const struct sunxi_ccu_desc *desc;
344 + struct ccu_reset reset;
345 +};
346 +
347 static DEFINE_SPINLOCK(ccu_lock);
348
349 void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
350 @@ -79,12 +85,15 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb)
351 &pll_nb->clk_nb);
352 }
353
354 -int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
355 - const struct sunxi_ccu_desc *desc)
356 +static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
357 + struct device_node *node, void __iomem *reg,
358 + const struct sunxi_ccu_desc *desc)
359 {
360 struct ccu_reset *reset;
361 int i, ret;
362
363 + ccu->desc = desc;
364 +
365 for (i = 0; i < desc->num_ccu_clks; i++) {
366 struct ccu_common *cclk = desc->ccu_clks[i];
367
368 @@ -103,7 +112,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
369 continue;
370
371 name = hw->init->name;
372 - ret = of_clk_hw_register(node, hw);
373 + if (dev)
374 + ret = clk_hw_register(dev, hw);
375 + else
376 + ret = of_clk_hw_register(node, hw);
377 if (ret) {
378 pr_err("Couldn't register clock %d - %s\n", i, name);
379 goto err_clk_unreg;
380 @@ -115,15 +127,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
381 if (ret)
382 goto err_clk_unreg;
383
384 - reset = kzalloc(sizeof(*reset), GFP_KERNEL);
385 - if (!reset) {
386 - ret = -ENOMEM;
387 - goto err_alloc_reset;
388 - }
389 -
390 + reset = &ccu->reset;
391 reset->rcdev.of_node = node;
392 reset->rcdev.ops = &ccu_reset_ops;
393 - reset->rcdev.owner = THIS_MODULE;
394 + reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE;
395 reset->rcdev.nr_resets = desc->num_resets;
396 reset->base = reg;
397 reset->lock = &ccu_lock;
398 @@ -131,13 +138,11 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
399
400 ret = reset_controller_register(&reset->rcdev);
401 if (ret)
402 - goto err_of_clk_unreg;
403 + goto err_del_provider;
404
405 return 0;
406
407 -err_of_clk_unreg:
408 - kfree(reset);
409 -err_alloc_reset:
410 +err_del_provider:
411 of_clk_del_provider(node);
412 err_clk_unreg:
413 while (--i >= 0) {
414 @@ -149,3 +154,59 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
415 }
416 return ret;
417 }
418 +
419 +static void devm_sunxi_ccu_release(struct device *dev, void *res)
420 +{
421 + struct sunxi_ccu *ccu = res;
422 + const struct sunxi_ccu_desc *desc = ccu->desc;
423 + int i;
424 +
425 + reset_controller_unregister(&ccu->reset.rcdev);
426 + of_clk_del_provider(dev->of_node);
427 +
428 + for (i = 0; i < desc->hw_clks->num; i++) {
429 + struct clk_hw *hw = desc->hw_clks->hws[i];
430 +
431 + if (!hw)
432 + continue;
433 + clk_hw_unregister(hw);
434 + }
435 +}
436 +
437 +int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg,
438 + const struct sunxi_ccu_desc *desc)
439 +{
440 + struct sunxi_ccu *ccu;
441 + int ret;
442 +
443 + ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL);
444 + if (!ccu)
445 + return -ENOMEM;
446 +
447 + ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc);
448 + if (ret) {
449 + devres_free(ccu);
450 + return ret;
451 + }
452 +
453 + devres_add(dev, ccu);
454 +
455 + return 0;
456 +}
457 +
458 +void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
459 + const struct sunxi_ccu_desc *desc)
460 +{
461 + struct sunxi_ccu *ccu;
462 + int ret;
463 +
464 + ccu = kzalloc(sizeof(*ccu), GFP_KERNEL);
465 + if (!ccu)
466 + return;
467 +
468 + ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc);
469 + if (ret) {
470 + pr_err("%pOF: probing clocks failed: %d\n", node, ret);
471 + kfree(ccu);
472 + }
473 +}
474 diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
475 index 04e7a12200a2..98a1834b58bb 100644
476 --- a/drivers/clk/sunxi-ng/ccu_common.h
477 +++ b/drivers/clk/sunxi-ng/ccu_common.h
478 @@ -63,7 +63,9 @@ struct ccu_pll_nb {
479
480 int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb);
481
482 -int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
483 - const struct sunxi_ccu_desc *desc);
484 +int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg,
485 + const struct sunxi_ccu_desc *desc);
486 +void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
487 + const struct sunxi_ccu_desc *desc);
488
489 #endif /* _COMMON_H_ */
490 --
491 2.20.1
492