1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/clk.h> 3 #include <linux/device.h> 4 #include <linux/export.h> 5 #include <linux/gfp.h> 6 7 struct devm_clk_state { 8 struct clk *clk; 9 void (*exit)(struct clk *clk); 10 }; 11 12 static void devm_clk_release(struct device *dev, void *res) 13 { 14 struct devm_clk_state *state = res; 15 16 if (state->exit) 17 state->exit(state->clk); 18 19 clk_put(state->clk); 20 } 21 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)) 26 { 27 struct devm_clk_state *state; 28 struct clk *clk; 29 int ret; 30 31 state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL); 32 if (!state) 33 return ERR_PTR(-ENOMEM); 34 35 clk = get(dev, id); 36 if (IS_ERR(clk)) { 37 ret = PTR_ERR(clk); 38 goto err_clk_get; 39 } 40 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 52 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); 66 } 67 EXPORT_SYMBOL(devm_clk_get); 68 69 struct clk *devm_clk_get_prepared(struct device *dev, const char *id) 70 { 71 return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare); 72 } 73 EXPORT_SYMBOL_GPL(devm_clk_get_prepared); 74 75 struct clk *devm_clk_get_enabled(struct device *dev, const char *id) 76 { 77 return __devm_clk_get(dev, id, clk_get, 78 clk_prepare_enable, clk_disable_unprepare); 79 } 80 EXPORT_SYMBOL_GPL(devm_clk_get_enabled); 81 82 struct clk *devm_clk_get_optional(struct device *dev, const char *id) 83 { 84 return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL); 85 } 86 EXPORT_SYMBOL(devm_clk_get_optional); 87 88 struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id) 89 { 90 return __devm_clk_get(dev, id, clk_get_optional, 91 clk_prepare, clk_unprepare); 92 } 93 EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared); 94 95 struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id) 96 { 97 return __devm_clk_get(dev, id, clk_get_optional, 98 clk_prepare_enable, clk_disable_unprepare); 99 } 100 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled); 101 102 static void devm_clk_disable_unprepare(void *data) 103 { 104 clk_disable_unprepare(data); 105 } 106 107 struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev, 108 const char *id, 109 unsigned long rate) 110 { 111 struct clk *clk; 112 int ret; 113 114 clk = devm_clk_get_optional(dev, id); 115 if (IS_ERR(clk)) 116 return ERR_CAST(clk); 117 118 ret = clk_set_rate(clk, rate); 119 if (ret) 120 goto out_put_clk; 121 122 ret = clk_prepare_enable(clk); 123 if (ret) 124 goto out_put_clk; 125 126 ret = devm_add_action_or_reset(dev, devm_clk_disable_unprepare, clk); 127 if (ret) 128 goto out_put_clk; 129 130 return clk; 131 132 out_put_clk: 133 devm_clk_put(dev, clk); 134 return ERR_PTR(ret); 135 } 136 EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled_with_rate); 137 138 struct clk_bulk_devres { 139 struct clk_bulk_data *clks; 140 int num_clks; 141 }; 142 143 static void devm_clk_bulk_release(struct device *dev, void *res) 144 { 145 struct clk_bulk_devres *devres = res; 146 147 clk_bulk_put(devres->num_clks, devres->clks); 148 } 149 150 static int __devm_clk_bulk_get(struct device *dev, int num_clks, 151 struct clk_bulk_data *clks, bool optional) 152 { 153 struct clk_bulk_devres *devres; 154 int ret; 155 156 devres = devres_alloc(devm_clk_bulk_release, 157 sizeof(*devres), GFP_KERNEL); 158 if (!devres) 159 return -ENOMEM; 160 161 if (optional) 162 ret = clk_bulk_get_optional(dev, num_clks, clks); 163 else 164 ret = clk_bulk_get(dev, num_clks, clks); 165 if (!ret) { 166 devres->clks = clks; 167 devres->num_clks = num_clks; 168 devres_add(dev, devres); 169 } else { 170 devres_free(devres); 171 } 172 173 return ret; 174 } 175 176 int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, 177 struct clk_bulk_data *clks) 178 { 179 return __devm_clk_bulk_get(dev, num_clks, clks, false); 180 } 181 EXPORT_SYMBOL_GPL(devm_clk_bulk_get); 182 183 int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks, 184 struct clk_bulk_data *clks) 185 { 186 return __devm_clk_bulk_get(dev, num_clks, clks, true); 187 } 188 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional); 189 190 static void devm_clk_bulk_release_enable(struct device *dev, void *res) 191 { 192 struct clk_bulk_devres *devres = res; 193 194 clk_bulk_disable_unprepare(devres->num_clks, devres->clks); 195 clk_bulk_put(devres->num_clks, devres->clks); 196 } 197 198 static int __devm_clk_bulk_get_enable(struct device *dev, int num_clks, 199 struct clk_bulk_data *clks, bool optional) 200 { 201 struct clk_bulk_devres *devres; 202 int ret; 203 204 devres = devres_alloc(devm_clk_bulk_release_enable, 205 sizeof(*devres), GFP_KERNEL); 206 if (!devres) 207 return -ENOMEM; 208 209 if (optional) 210 ret = clk_bulk_get_optional(dev, num_clks, clks); 211 else 212 ret = clk_bulk_get(dev, num_clks, clks); 213 if (ret) 214 goto err_clk_get; 215 216 ret = clk_bulk_prepare_enable(num_clks, clks); 217 if (ret) 218 goto err_clk_prepare; 219 220 devres->clks = clks; 221 devres->num_clks = num_clks; 222 devres_add(dev, devres); 223 224 return 0; 225 226 err_clk_prepare: 227 clk_bulk_put(num_clks, clks); 228 err_clk_get: 229 devres_free(devres); 230 return ret; 231 } 232 233 int __must_check devm_clk_bulk_get_enable(struct device *dev, int num_clks, 234 struct clk_bulk_data *clks) 235 { 236 return __devm_clk_bulk_get_enable(dev, num_clks, clks, false); 237 } 238 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_enable); 239 240 int __must_check devm_clk_bulk_get_optional_enable(struct device *dev, int num_clks, 241 struct clk_bulk_data *clks) 242 { 243 return __devm_clk_bulk_get_enable(dev, num_clks, clks, true); 244 } 245 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional_enable); 246 247 static void devm_clk_bulk_release_all(struct device *dev, void *res) 248 { 249 struct clk_bulk_devres *devres = res; 250 251 clk_bulk_put_all(devres->num_clks, devres->clks); 252 } 253 254 int __must_check devm_clk_bulk_get_all(struct device *dev, 255 struct clk_bulk_data **clks) 256 { 257 struct clk_bulk_devres *devres; 258 int ret; 259 260 devres = devres_alloc(devm_clk_bulk_release_all, 261 sizeof(*devres), GFP_KERNEL); 262 if (!devres) 263 return -ENOMEM; 264 265 ret = clk_bulk_get_all(dev, &devres->clks); 266 if (ret > 0) { 267 *clks = devres->clks; 268 devres->num_clks = ret; 269 devres_add(dev, devres); 270 } else { 271 devres_free(devres); 272 } 273 274 return ret; 275 } 276 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all); 277 278 static void devm_clk_bulk_release_all_enable(struct device *dev, void *res) 279 { 280 struct clk_bulk_devres *devres = res; 281 282 clk_bulk_disable_unprepare(devres->num_clks, devres->clks); 283 clk_bulk_put_all(devres->num_clks, devres->clks); 284 } 285 286 int __must_check devm_clk_bulk_get_all_enabled(struct device *dev, 287 struct clk_bulk_data **clks) 288 { 289 struct clk_bulk_devres *devres; 290 int ret; 291 292 devres = devres_alloc(devm_clk_bulk_release_all_enable, 293 sizeof(*devres), GFP_KERNEL); 294 if (!devres) 295 return -ENOMEM; 296 297 ret = clk_bulk_get_all(dev, &devres->clks); 298 if (ret > 0) { 299 *clks = devres->clks; 300 devres->num_clks = ret; 301 } else { 302 devres_free(devres); 303 return ret; 304 } 305 306 ret = clk_bulk_prepare_enable(devres->num_clks, *clks); 307 if (!ret) { 308 devres_add(dev, devres); 309 } else { 310 clk_bulk_put_all(devres->num_clks, devres->clks); 311 devres_free(devres); 312 return ret; 313 } 314 315 return devres->num_clks; 316 } 317 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enabled); 318 319 static int devm_clk_match(struct device *dev, void *res, void *data) 320 { 321 struct clk **c = res; 322 if (!c || !*c) { 323 WARN_ON(!c || !*c); 324 return 0; 325 } 326 return *c == data; 327 } 328 329 void devm_clk_put(struct device *dev, struct clk *clk) 330 { 331 int ret; 332 333 ret = devres_release(dev, devm_clk_release, devm_clk_match, clk); 334 335 WARN_ON(ret); 336 } 337 EXPORT_SYMBOL(devm_clk_put); 338 339 struct clk *devm_get_clk_from_child(struct device *dev, 340 struct device_node *np, const char *con_id) 341 { 342 struct devm_clk_state *state; 343 struct clk *clk; 344 345 state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL); 346 if (!state) 347 return ERR_PTR(-ENOMEM); 348 349 clk = of_clk_get_by_name(np, con_id); 350 if (!IS_ERR(clk)) { 351 state->clk = clk; 352 devres_add(dev, state); 353 } else { 354 devres_free(state); 355 } 356 357 return clk; 358 } 359 EXPORT_SYMBOL(devm_get_clk_from_child); 360