ccu_div.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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_TABLE_GATE_CLOSEST(_struct, _name, \
  123. _parents, _table, \
  124. _reg, \
  125. _mshift, _mwidth, \
  126. _muxshift, _muxwidth, \
  127. _gate, _flags) \
  128. struct ccu_div _struct = { \
  129. .enable = _gate, \
  130. .div = _SUNXI_CCU_DIV_FLAGS(_mshift, _mwidth, CLK_DIVIDER_ROUND_CLOSEST), \
  131. .mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
  132. .common = { \
  133. .reg = _reg, \
  134. .hw.init = CLK_HW_INIT_PARENTS(_name, \
  135. _parents, \
  136. &ccu_div_ops, \
  137. _flags), \
  138. .features = CCU_FEATURE_CLOSEST_RATE, \
  139. }, \
  140. }
  141. #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  142. _mshift, _mwidth, _muxshift, _muxwidth, \
  143. _gate, _flags) \
  144. SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
  145. _parents, NULL, \
  146. _reg, _mshift, _mwidth, \
  147. _muxshift, _muxwidth, \
  148. _gate, _flags)
  149. #define SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(_struct, _name, _parents, \
  150. _reg, _mshift, _mwidth, \
  151. _muxshift, _muxwidth, \
  152. _gate, _flags) \
  153. SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name, \
  154. _parents, NULL, \
  155. _reg, _mshift, _mwidth, \
  156. _muxshift, _muxwidth, \
  157. _gate, _flags)
  158. #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \
  159. _mshift, _mwidth, _muxshift, _muxwidth, \
  160. _flags) \
  161. SUNXI_CCU_M_WITH_MUX_TABLE_GATE(_struct, _name, \
  162. _parents, NULL, \
  163. _reg, _mshift, _mwidth, \
  164. _muxshift, _muxwidth, \
  165. 0, _flags)
  166. #define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
  167. _mshift, _mwidth, _gate, \
  168. _flags) \
  169. struct ccu_div _struct = { \
  170. .enable = _gate, \
  171. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  172. .common = { \
  173. .reg = _reg, \
  174. .hw.init = CLK_HW_INIT(_name, \
  175. _parent, \
  176. &ccu_div_ops, \
  177. _flags), \
  178. }, \
  179. }
  180. #define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth, \
  181. _flags) \
  182. SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \
  183. _mshift, _mwidth, 0, _flags)
  184. #define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  185. _mshift, _mwidth, \
  186. _muxshift, _muxwidth, \
  187. _gate, _flags) \
  188. struct ccu_div _struct = { \
  189. .enable = _gate, \
  190. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  191. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  192. .common = { \
  193. .reg = _reg, \
  194. .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
  195. _parents, \
  196. &ccu_div_ops, \
  197. _flags), \
  198. }, \
  199. }
  200. #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
  201. _mshift, _mwidth, \
  202. _muxshift, _muxwidth, \
  203. _flags) \
  204. SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  205. _mshift, _mwidth, \
  206. _muxshift, _muxwidth, \
  207. 0, _flags)
  208. #define SUNXI_CCU_M_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  209. _mshift, _mwidth, _muxshift, _muxwidth, \
  210. _gate, _flags) \
  211. struct ccu_div _struct = { \
  212. .enable = _gate, \
  213. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  214. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  215. .common = { \
  216. .reg = _reg, \
  217. .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
  218. _parents, \
  219. &ccu_div_ops, \
  220. _flags), \
  221. }, \
  222. }
  223. #define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
  224. _mshift, _mwidth, _gate, \
  225. _flags) \
  226. struct ccu_div _struct = { \
  227. .enable = _gate, \
  228. .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  229. .common = { \
  230. .reg = _reg, \
  231. .hw.init = CLK_HW_INIT_HWS(_name, \
  232. _parent, \
  233. &ccu_div_ops, \
  234. _flags), \
  235. }, \
  236. }
  237. #define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift, \
  238. _mwidth, _flags) \
  239. SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \
  240. _mshift, _mwidth, 0, _flags)
  241. static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)
  242. {
  243. struct ccu_common *common = hw_to_ccu_common(hw);
  244. return container_of(common, struct ccu_div, common);
  245. }
  246. extern const struct clk_ops ccu_div_ops;
  247. #endif /* _CCU_DIV_H_ */