clk-devres.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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. static void devm_clk_release(struct device *dev, void *res)
  7. {
  8. clk_put(*(struct clk **)res);
  9. }
  10. struct clk *devm_clk_get(struct device *dev, const char *id)
  11. {
  12. struct clk **ptr, *clk;
  13. ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
  14. if (!ptr)
  15. return ERR_PTR(-ENOMEM);
  16. clk = clk_get(dev, id);
  17. if (!IS_ERR(clk)) {
  18. *ptr = clk;
  19. devres_add(dev, ptr);
  20. } else {
  21. devres_free(ptr);
  22. }
  23. return clk;
  24. }
  25. EXPORT_SYMBOL(devm_clk_get);
  26. struct clk *devm_clk_get_optional(struct device *dev, const char *id)
  27. {
  28. struct clk *clk = devm_clk_get(dev, id);
  29. if (clk == ERR_PTR(-ENOENT))
  30. return NULL;
  31. return clk;
  32. }
  33. EXPORT_SYMBOL(devm_clk_get_optional);
  34. struct clk_bulk_devres {
  35. struct clk_bulk_data *clks;
  36. int num_clks;
  37. };
  38. static void devm_clk_bulk_release(struct device *dev, void *res)
  39. {
  40. struct clk_bulk_devres *devres = res;
  41. clk_bulk_put(devres->num_clks, devres->clks);
  42. }
  43. static int __devm_clk_bulk_get(struct device *dev, int num_clks,
  44. struct clk_bulk_data *clks, bool optional)
  45. {
  46. struct clk_bulk_devres *devres;
  47. int ret;
  48. devres = devres_alloc(devm_clk_bulk_release,
  49. sizeof(*devres), GFP_KERNEL);
  50. if (!devres)
  51. return -ENOMEM;
  52. if (optional)
  53. ret = clk_bulk_get_optional(dev, num_clks, clks);
  54. else
  55. ret = clk_bulk_get(dev, num_clks, clks);
  56. if (!ret) {
  57. devres->clks = clks;
  58. devres->num_clks = num_clks;
  59. devres_add(dev, devres);
  60. } else {
  61. devres_free(devres);
  62. }
  63. return ret;
  64. }
  65. int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
  66. struct clk_bulk_data *clks)
  67. {
  68. return __devm_clk_bulk_get(dev, num_clks, clks, false);
  69. }
  70. EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
  71. int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
  72. struct clk_bulk_data *clks)
  73. {
  74. return __devm_clk_bulk_get(dev, num_clks, clks, true);
  75. }
  76. EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
  77. static void devm_clk_bulk_release_all(struct device *dev, void *res)
  78. {
  79. struct clk_bulk_devres *devres = res;
  80. clk_bulk_put_all(devres->num_clks, devres->clks);
  81. }
  82. int __must_check devm_clk_bulk_get_all(struct device *dev,
  83. struct clk_bulk_data **clks)
  84. {
  85. struct clk_bulk_devres *devres;
  86. int ret;
  87. devres = devres_alloc(devm_clk_bulk_release_all,
  88. sizeof(*devres), GFP_KERNEL);
  89. if (!devres)
  90. return -ENOMEM;
  91. ret = clk_bulk_get_all(dev, &devres->clks);
  92. if (ret > 0) {
  93. *clks = devres->clks;
  94. devres->num_clks = ret;
  95. devres_add(dev, devres);
  96. } else {
  97. devres_free(devres);
  98. }
  99. return ret;
  100. }
  101. EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
  102. static int devm_clk_match(struct device *dev, void *res, void *data)
  103. {
  104. struct clk **c = res;
  105. if (!c || !*c) {
  106. WARN_ON(!c || !*c);
  107. return 0;
  108. }
  109. return *c == data;
  110. }
  111. void devm_clk_put(struct device *dev, struct clk *clk)
  112. {
  113. int ret;
  114. ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
  115. WARN_ON(ret);
  116. }
  117. EXPORT_SYMBOL(devm_clk_put);
  118. struct clk *devm_get_clk_from_child(struct device *dev,
  119. struct device_node *np, const char *con_id)
  120. {
  121. struct clk **ptr, *clk;
  122. ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
  123. if (!ptr)
  124. return ERR_PTR(-ENOMEM);
  125. clk = of_clk_get_by_name(np, con_id);
  126. if (!IS_ERR(clk)) {
  127. *ptr = clk;
  128. devres_add(dev, ptr);
  129. } else {
  130. devres_free(ptr);
  131. }
  132. return clk;
  133. }
  134. EXPORT_SYMBOL(devm_get_clk_from_child);