1
0

083-0002-clk-Add-clk_hw-OF-clk-providers.patch 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. From 0861e5b8cf80038e91942f1005c8dfce79d18c38 Mon Sep 17 00:00:00 2001
  2. From: Stephen Boyd <sboyd@codeaurora.org>
  3. Date: Fri, 5 Feb 2016 17:38:26 -0800
  4. Subject: [PATCH] clk: Add clk_hw OF clk providers
  5. Now that we have a clk registration API that doesn't return
  6. struct clks, we need to have some way to hand out struct clks via
  7. the clk_get() APIs that doesn't involve associating struct clk
  8. pointers with an OF node. Currently we ask the OF provider to
  9. give us a struct clk pointer for some clkspec, turn that struct
  10. clk into a struct clk_hw and then allocate a new struct clk to
  11. return to the caller.
  12. Let's add a clk_hw based OF provider hook that returns a struct
  13. clk_hw directly, so that we skip the intermediate step of
  14. converting from struct clk to struct clk_hw. Eventually when
  15. we've converted all OF clk providers to struct clk_hw based APIs
  16. we can remove the struct clk based ones.
  17. It should also be noted that we change the onecell provider to
  18. have a flex array instead of a pointer for the array of clk_hw
  19. pointers. This allows providers to allocate one structure of the
  20. correct length in one step instead of two.
  21. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
  22. ---
  23. drivers/clk/clk.c | 85 +++++++++++++++++++++++++++++++++++++++++---
  24. include/linux/clk-provider.h | 30 ++++++++++++++++
  25. 2 files changed, 111 insertions(+), 4 deletions(-)
  26. --- a/drivers/clk/clk.c
  27. +++ b/drivers/clk/clk.c
  28. @@ -3001,6 +3001,7 @@ struct of_clk_provider {
  29. struct device_node *node;
  30. struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
  31. + struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
  32. void *data;
  33. };
  34. @@ -3017,6 +3018,12 @@ struct clk *of_clk_src_simple_get(struct
  35. }
  36. EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
  37. +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
  38. +{
  39. + return data;
  40. +}
  41. +EXPORT_SYMBOL_GPL(of_clk_hw_simple_get);
  42. +
  43. struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
  44. {
  45. struct clk_onecell_data *clk_data = data;
  46. @@ -3031,6 +3038,21 @@ struct clk *of_clk_src_onecell_get(struc
  47. }
  48. EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
  49. +struct clk_hw *
  50. +of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
  51. +{
  52. + struct clk_hw_onecell_data *hw_data = data;
  53. + unsigned int idx = clkspec->args[0];
  54. +
  55. + if (idx >= hw_data->num) {
  56. + pr_err("%s: invalid index %u\n", __func__, idx);
  57. + return ERR_PTR(-EINVAL);
  58. + }
  59. +
  60. + return hw_data->hws[idx];
  61. +}
  62. +EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get);
  63. +
  64. /**
  65. * of_clk_add_provider() - Register a clock provider for a node
  66. * @np: Device node pointer associated with clock provider
  67. @@ -3067,6 +3089,41 @@ int of_clk_add_provider(struct device_no
  68. EXPORT_SYMBOL_GPL(of_clk_add_provider);
  69. /**
  70. + * of_clk_add_hw_provider() - Register a clock provider for a node
  71. + * @np: Device node pointer associated with clock provider
  72. + * @get: callback for decoding clk_hw
  73. + * @data: context pointer for @get callback.
  74. + */
  75. +int of_clk_add_hw_provider(struct device_node *np,
  76. + struct clk_hw *(*get)(struct of_phandle_args *clkspec,
  77. + void *data),
  78. + void *data)
  79. +{
  80. + struct of_clk_provider *cp;
  81. + int ret;
  82. +
  83. + cp = kzalloc(sizeof(*cp), GFP_KERNEL);
  84. + if (!cp)
  85. + return -ENOMEM;
  86. +
  87. + cp->node = of_node_get(np);
  88. + cp->data = data;
  89. + cp->get_hw = get;
  90. +
  91. + mutex_lock(&of_clk_mutex);
  92. + list_add(&cp->link, &of_clk_providers);
  93. + mutex_unlock(&of_clk_mutex);
  94. + pr_debug("Added clk_hw provider from %s\n", np->full_name);
  95. +
  96. + ret = of_clk_set_defaults(np, true);
  97. + if (ret < 0)
  98. + of_clk_del_provider(np);
  99. +
  100. + return ret;
  101. +}
  102. +EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
  103. +
  104. +/**
  105. * of_clk_del_provider() - Remove a previously registered clock provider
  106. * @np: Device node pointer associated with clock provider
  107. */
  108. @@ -3087,11 +3144,32 @@ void of_clk_del_provider(struct device_n
  109. }
  110. EXPORT_SYMBOL_GPL(of_clk_del_provider);
  111. +static struct clk_hw *
  112. +__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
  113. + struct of_phandle_args *clkspec)
  114. +{
  115. + struct clk *clk;
  116. + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
  117. +
  118. + if (provider->get_hw) {
  119. + hw = provider->get_hw(clkspec, provider->data);
  120. + } else if (provider->get) {
  121. + clk = provider->get(clkspec, provider->data);
  122. + if (!IS_ERR(clk))
  123. + hw = __clk_get_hw(clk);
  124. + else
  125. + hw = ERR_CAST(clk);
  126. + }
  127. +
  128. + return hw;
  129. +}
  130. +
  131. struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
  132. const char *dev_id, const char *con_id)
  133. {
  134. struct of_clk_provider *provider;
  135. struct clk *clk = ERR_PTR(-EPROBE_DEFER);
  136. + struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
  137. if (!clkspec)
  138. return ERR_PTR(-EINVAL);
  139. @@ -3100,10 +3178,9 @@ struct clk *__of_clk_get_from_provider(s
  140. mutex_lock(&of_clk_mutex);
  141. list_for_each_entry(provider, &of_clk_providers, link) {
  142. if (provider->node == clkspec->np)
  143. - clk = provider->get(clkspec, provider->data);
  144. - if (!IS_ERR(clk)) {
  145. - clk = __clk_create_clk(__clk_get_hw(clk), dev_id,
  146. - con_id);
  147. + hw = __of_clk_get_hw_from_provider(provider, clkspec);
  148. + if (!IS_ERR(hw)) {
  149. + clk = __clk_create_clk(hw, dev_id, con_id);
  150. if (!IS_ERR(clk) && !__clk_get(clk)) {
  151. __clk_free_clk(clk);
  152. --- a/include/linux/clk-provider.h
  153. +++ b/include/linux/clk-provider.h
  154. @@ -693,6 +693,11 @@ struct clk_onecell_data {
  155. unsigned int clk_num;
  156. };
  157. +struct clk_hw_onecell_data {
  158. + size_t num;
  159. + struct clk_hw *hws[];
  160. +};
  161. +
  162. extern struct of_device_id __clk_of_table;
  163. #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
  164. @@ -702,10 +707,19 @@ int of_clk_add_provider(struct device_no
  165. struct clk *(*clk_src_get)(struct of_phandle_args *args,
  166. void *data),
  167. void *data);
  168. +int of_clk_add_hw_provider(struct device_node *np,
  169. + struct clk_hw *(*get)(struct of_phandle_args *clkspec,
  170. + void *data),
  171. + void *data);
  172. void of_clk_del_provider(struct device_node *np);
  173. struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
  174. void *data);
  175. +
  176. +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec,
  177. + void *data);
  178. struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
  179. +struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec,
  180. + void *data);
  181. int of_clk_get_parent_count(struct device_node *np);
  182. int of_clk_parent_fill(struct device_node *np, const char **parents,
  183. unsigned int size);
  184. @@ -722,6 +736,13 @@ static inline int of_clk_add_provider(st
  185. {
  186. return 0;
  187. }
  188. +static inline int of_clk_add_hw_provider(struct device_node *np,
  189. + struct clk_hw *(*get)(struct of_phandle_args *clkspec,
  190. + void *data),
  191. + void *data)
  192. +{
  193. + return 0;
  194. +}
  195. #define of_clk_del_provider(np) \
  196. { while (0); }
  197. static inline struct clk *of_clk_src_simple_get(
  198. @@ -729,11 +750,21 @@ static inline struct clk *of_clk_src_sim
  199. {
  200. return ERR_PTR(-ENOENT);
  201. }
  202. +static inline struct clk_hw *
  203. +of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
  204. +{
  205. + return ERR_PTR(-ENOENT);
  206. +}
  207. static inline struct clk *of_clk_src_onecell_get(
  208. struct of_phandle_args *clkspec, void *data)
  209. {
  210. return ERR_PTR(-ENOENT);
  211. }
  212. +static inline struct clk_hw *
  213. +of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
  214. +{
  215. + return ERR_PTR(-ENOENT);
  216. +}
  217. static inline int of_clk_get_parent_count(struct device_node *np)
  218. {
  219. return 0;