clk-composite.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved.
  4. * Copyright 2019 NXP
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <malloc.h>
  9. #include <clk-uclass.h>
  10. #include <dm/device.h>
  11. #include <dm/devres.h>
  12. #include <linux/clk-provider.h>
  13. #include <clk.h>
  14. #include <linux/err.h>
  15. #include "clk.h"
  16. #define UBOOT_DM_CLK_COMPOSITE "clk_composite"
  17. static u8 clk_composite_get_parent(struct clk *clk)
  18. {
  19. struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
  20. (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
  21. struct clk *mux = composite->mux;
  22. if (mux)
  23. return clk_mux_get_parent(mux);
  24. else
  25. return 0;
  26. }
  27. static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
  28. {
  29. struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
  30. (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
  31. const struct clk_ops *mux_ops = composite->mux_ops;
  32. struct clk *mux = composite->mux;
  33. if (mux && mux_ops)
  34. return mux_ops->set_parent(mux, parent);
  35. else
  36. return -ENOTSUPP;
  37. }
  38. static unsigned long clk_composite_recalc_rate(struct clk *clk)
  39. {
  40. struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
  41. (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
  42. const struct clk_ops *rate_ops = composite->rate_ops;
  43. struct clk *rate = composite->rate;
  44. if (rate && rate_ops)
  45. return rate_ops->get_rate(rate);
  46. else
  47. return clk_get_parent_rate(clk);
  48. }
  49. static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
  50. {
  51. struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
  52. (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
  53. const struct clk_ops *rate_ops = composite->rate_ops;
  54. struct clk *clk_rate = composite->rate;
  55. if (rate && rate_ops)
  56. return rate_ops->set_rate(clk_rate, rate);
  57. else
  58. return clk_get_rate(clk);
  59. }
  60. static int clk_composite_enable(struct clk *clk)
  61. {
  62. struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
  63. (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
  64. const struct clk_ops *gate_ops = composite->gate_ops;
  65. struct clk *gate = composite->gate;
  66. if (gate && gate_ops)
  67. return gate_ops->enable(gate);
  68. else
  69. return 0;
  70. }
  71. static int clk_composite_disable(struct clk *clk)
  72. {
  73. struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
  74. (struct clk *)dev_get_clk_ptr(clk->dev) : clk);
  75. const struct clk_ops *gate_ops = composite->gate_ops;
  76. struct clk *gate = composite->gate;
  77. if (gate && gate_ops)
  78. return gate_ops->disable(gate);
  79. else
  80. return 0;
  81. }
  82. struct clk *clk_register_composite(struct device *dev, const char *name,
  83. const char * const *parent_names,
  84. int num_parents, struct clk *mux,
  85. const struct clk_ops *mux_ops,
  86. struct clk *rate,
  87. const struct clk_ops *rate_ops,
  88. struct clk *gate,
  89. const struct clk_ops *gate_ops,
  90. unsigned long flags)
  91. {
  92. struct clk *clk;
  93. struct clk_composite *composite;
  94. int ret;
  95. if (!num_parents || (num_parents != 1 && !mux))
  96. return ERR_PTR(-EINVAL);
  97. composite = kzalloc(sizeof(*composite), GFP_KERNEL);
  98. if (!composite)
  99. return ERR_PTR(-ENOMEM);
  100. if (mux && mux_ops) {
  101. composite->mux = mux;
  102. composite->mux_ops = mux_ops;
  103. mux->data = (ulong)composite;
  104. }
  105. if (rate && rate_ops) {
  106. if (!rate_ops->get_rate) {
  107. clk = ERR_PTR(-EINVAL);
  108. goto err;
  109. }
  110. composite->rate = rate;
  111. composite->rate_ops = rate_ops;
  112. rate->data = (ulong)composite;
  113. }
  114. if (gate && gate_ops) {
  115. if (!gate_ops->enable || !gate_ops->disable) {
  116. clk = ERR_PTR(-EINVAL);
  117. goto err;
  118. }
  119. composite->gate = gate;
  120. composite->gate_ops = gate_ops;
  121. gate->data = (ulong)composite;
  122. }
  123. clk = &composite->clk;
  124. clk->flags = flags;
  125. ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
  126. parent_names[clk_composite_get_parent(clk)]);
  127. if (ret) {
  128. clk = ERR_PTR(ret);
  129. goto err;
  130. }
  131. if (composite->mux)
  132. composite->mux->dev = clk->dev;
  133. if (composite->rate)
  134. composite->rate->dev = clk->dev;
  135. if (composite->gate)
  136. composite->gate->dev = clk->dev;
  137. return clk;
  138. err:
  139. kfree(composite);
  140. return clk;
  141. }
  142. static const struct clk_ops clk_composite_ops = {
  143. .set_parent = clk_composite_set_parent,
  144. .get_rate = clk_composite_recalc_rate,
  145. .set_rate = clk_composite_set_rate,
  146. .enable = clk_composite_enable,
  147. .disable = clk_composite_disable,
  148. };
  149. U_BOOT_DRIVER(clk_composite) = {
  150. .name = UBOOT_DM_CLK_COMPOSITE,
  151. .id = UCLASS_CLK,
  152. .ops = &clk_composite_ops,
  153. .flags = DM_FLAG_PRE_RELOC,
  154. };