ccu_div.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (c) 2016 Maxime Ripard. All rights reserved.
  4. */
  5. #ifndef _CCU_DIV_H_
  6. #define _CCU_DIV_H_
  7. #include <linux/clk-provider.h>
  8. #include "ccu_common.h"
  9. #include "ccu_mux.h"
  10. /**
  11. * struct ccu_div_internal - Internal divider description
  12. * @shift: Bit offset of the divider in its register
  13. * @width: Width of the divider field in its register
  14. * @max: Maximum value allowed for that divider. This is the
  15. * arithmetic value, not the maximum value to be set in the
  16. * register.
  17. * @flags: clk_divider flags to apply on this divider
  18. * @table: Divider table pointer (if applicable)
  19. *
  20. * That structure represents a single divider, and is meant to be
  21. * embedded in other structures representing the various clock
  22. * classes.
  23. *
  24. * It is basically a wrapper around the clk_divider functions
  25. * arguments.
  26. */
  27. struct ccu_div_internal {
  28. u8 shift;
  29. u8 width;
  30. u32 max;
  31. u32 offset;
  32. u32 flags;
  33. struct clk_div_table *table;
  34. };
  35. #define _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, _flags) \
  36. { \
  37. .shift = _shift, \
  38. .width = _width, \
  39. .flags = _flags, \
  40. .table = _table, \
  41. }
  42. #define _SUNXI_CCU_DIV_TABLE(_shift, _width, _table) \
  43. _SUNXI_CCU_DIV_TABLE_FLAGS(_shift, _width, _table, 0)
  44. #define _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _off, _max, _flags) \
  45. { \
  46. .shift = _shift, \
  47. .width = _width, \
  48. .flags = _flags, \
  49. .max = _max, \
  50. .offset = _off, \
  51. }
  52. #define _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, _flags) \
  53. _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, 1, _max, _flags)
  54. #define _SUNXI_CCU_DIV_FLAGS(_shift, _width, _flags) \
  55. _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, 0, _flags)
  56. #define _SUNXI_CCU_DIV_MAX(_shift, _width, _max) \
  57. _SUNXI_CCU_DIV_MAX_FLAGS(_shift, _width, _max, 0)
  58. #define _SUNXI_CCU_DIV_OFFSET(_shift, _width, _offset) \
  59. _SUNXI_CCU_DIV_OFFSET_MAX_FLAGS(_shift, _width, _offset, 0, 0)
  60. #define _SUNXI_CCU_DIV(_shift, _width) \
  61. _SUNXI_CCU_DIV_FLAGS(_shift, _width, 0)
  62. struct ccu_div {
  63. u32 enable;
  64. struct ccu_div_internal div;
  65. struct ccu_mux_internal mux;
  66. struct ccu_common common;
  67. unsigned int fixed_post_div;
  68. };
  69. #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \
  70. _shift, _width, \
  71. _table, _gate, _flags) \
  72. struct ccu_div _struct = { \
  73. .div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \
  74. _table), \
  75. .enable = _gate, \
  76. .common = { \
  77. .reg = _reg, \
  78. .hw.init = CLK_HW_INIT(_name, \
  79. _parent, \
  80. &ccu_div_ops, \
  81. _flags), \
  82. } \
  83. }
  84. #define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg, \
  85. _shift, _width, \
  86. _table, _flags) \
  87. SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \
  88. _shift, _width, _table, 0, \
  89. _flags)
  90. #define SUNXI_CCU_DIV_TABLE_HW(_struct, _name, _parent, _reg, \
  91. _shift, _width, \
  92. _table, _flags) \
  93. struct ccu_div _struct = { \
  94. .div = _SUNXI_CCU_DIV_TABLE(_shift, _width, \
  95. _table), \
  96. .common = { \
  97. .reg = _reg, \
  98. .hw.init = CLK_HW_INIT_HW(_name, \
  99. _parent, \
  100. &ccu_div_ops, \
  101. _flags), \
  102. } \
  103. }
  104. #define SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
  105. _parents, _table, \
  106. _reg, \
  107. _mshift, _mwidth, \
  108. _muxshift, _muxwidth, \
  109. _gate, _flags) \
  110. struct ccu_div _struct = { \
  111. .enable = _gate, \
  112. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  113. .mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
  114. .common = { \
  115. .reg = _reg, \
  116. .hw.init = CLK_HW_INIT_PARENTS(_name, \
  117. _parents, \
  118. &ccu_div_ops, \
  119. _flags), \
  120. }, \
  121. }
  122. #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  123. _mshift, _mwidth, _muxshift, _muxwidth, \
  124. _gate, _flags) \
  125. SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
  126. _parents, NULL, \
  127. _reg, _mshift, _mwidth, \
  128. _muxshift, _muxwidth, \
  129. _gate, _flags)
  130. #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \
  131. _mshift, _mwidth, _muxshift, _muxwidth, \
  132. _flags) \
  133. SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
  134. _parents, NULL, \
  135. _reg, _mshift, _mwidth, \
  136. _muxshift, _muxwidth, \
  137. 0, _flags)
  138. #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
  139. _mshift, _mwidth, _gate, \
  140. _flags) \
  141. struct ccu_div _struct = { \
  142. .enable = _gate, \
  143. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  144. .common = { \
  145. .reg = _reg, \
  146. .hw.init = CLK_HW_INIT(_name, \
  147. _parent, \
  148. &ccu_div_ops, \
  149. _flags), \
  150. }, \
  151. }
  152. #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth, \
  153. _flags) \
  154. SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
  155. _mshift, _mwidth, 0, _flags)
  156. #define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  157. _mshift, _mwidth, \
  158. _muxshift, _muxwidth, \
  159. _gate, _flags) \
  160. struct ccu_div _struct = { \
  161. .enable = _gate, \
  162. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  163. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  164. .common = { \
  165. .reg = _reg, \
  166. .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
  167. _parents, \
  168. &ccu_div_ops, \
  169. _flags), \
  170. }, \
  171. }
  172. #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
  173. _mshift, _mwidth, \
  174. _muxshift, _muxwidth, \
  175. _flags) \
  176. SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  177. _mshift, _mwidth, \
  178. _muxshift, _muxwidth, \
  179. 0, _flags)
  180. #define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  181. _mshift, _mwidth, _muxshift, _muxwidth, \
  182. _gate, _flags) \
  183. struct ccu_div _struct = { \
  184. .enable = _gate, \
  185. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  186. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  187. .common = { \
  188. .reg = _reg, \
  189. .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
  190. _parents, \
  191. &ccu_div_ops, \
  192. _flags), \
  193. }, \
  194. }
  195. #define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
  196. _mshift, _mwidth, _gate, \
  197. _flags) \
  198. struct ccu_div _struct = { \
  199. .enable = _gate, \
  200. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  201. .common = { \
  202. .reg = _reg, \
  203. .hw.init = CLK_HW_INIT_HWS(_name, \
  204. _parent, \
  205. &ccu_div_ops, \
  206. _flags), \
  207. }, \
  208. }
  209. #define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift, \
  210. _mwidth, _flags) \
  211. SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
  212. _mshift, _mwidth, 0, _flags)
  213. static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
  214. {
  215. struct ccu_common *common = hw_to_ccu_common(hw);
  216. return container_of(common, struct ccu_div, common);
  217. }
  218. extern const struct clk_ops ccu_div_ops;
  219. #endif /* _CCU_DIV_H_ */