ccu_mp.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (c) 2016 Maxime Ripard. All rights reserved.
  4. */
  5. #ifndef _CCU_MP_H_
  6. #define _CCU_MP_H_
  7. #include <linux/bitops.h>
  8. #include <linux/clk-provider.h>
  9. #include "ccu_common.h"
  10. #include "ccu_div.h"
  11. #include "ccu_mult.h"
  12. #include "ccu_mux.h"
  13. /*
  14. * struct ccu_mp - Definition of an M-P clock
  15. *
  16. * Clocks based on the formula parent >> P / M
  17. */
  18. struct ccu_mp {
  19. u32 enable;
  20. struct ccu_div_internal m;
  21. struct ccu_div_internal p;
  22. struct ccu_mux_internal mux;
  23. unsigned int fixed_post_div;
  24. struct ccu_common common;
  25. };
  26. #define SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(_struct, _name, _parents, _reg, \
  27. _mshift, _mwidth, \
  28. _pshift, _pwidth, \
  29. _muxshift, _muxwidth, \
  30. _gate, _postdiv, _flags) \
  31. struct ccu_mp _struct = { \
  32. .enable = _gate, \
  33. .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  34. .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
  35. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  36. .fixed_post_div = _postdiv, \
  37. .common = { \
  38. .reg = _reg, \
  39. .features = CCU_FEATURE_FIXED_POSTDIV, \
  40. .hw.init = CLK_HW_INIT_PARENTS(_name, \
  41. _parents, \
  42. &ccu_mp_ops, \
  43. _flags), \
  44. } \
  45. }
  46. #define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  47. _mshift, _mwidth, \
  48. _pshift, _pwidth, \
  49. _muxshift, _muxwidth, \
  50. _gate, _flags) \
  51. struct ccu_mp _struct = { \
  52. .enable = _gate, \
  53. .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  54. .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
  55. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  56. .common = { \
  57. .reg = _reg, \
  58. .hw.init = CLK_HW_INIT_PARENTS(_name, \
  59. _parents, \
  60. &ccu_mp_ops, \
  61. _flags), \
  62. } \
  63. }
  64. #define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg, \
  65. _mshift, _mwidth, \
  66. _pshift, _pwidth, \
  67. _muxshift, _muxwidth, \
  68. _flags) \
  69. SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  70. _mshift, _mwidth, \
  71. _pshift, _pwidth, \
  72. _muxshift, _muxwidth, \
  73. 0, _flags)
  74. #define SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  75. _mshift, _mwidth, \
  76. _pshift, _pwidth, \
  77. _muxshift, _muxwidth, \
  78. _gate, _flags) \
  79. struct ccu_mp _struct = { \
  80. .enable = _gate, \
  81. .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  82. .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
  83. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  84. .common = { \
  85. .reg = _reg, \
  86. .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, \
  87. _parents, \
  88. &ccu_mp_ops, \
  89. _flags), \
  90. } \
  91. }
  92. #define SUNXI_CCU_MP_DATA_WITH_MUX(_struct, _name, _parents, _reg, \
  93. _mshift, _mwidth, \
  94. _pshift, _pwidth, \
  95. _muxshift, _muxwidth, \
  96. _flags) \
  97. SUNXI_CCU_MP_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  98. _mshift, _mwidth, \
  99. _pshift, _pwidth, \
  100. _muxshift, _muxwidth, \
  101. 0, _flags)
  102. #define SUNXI_CCU_MP_HW_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  103. _mshift, _mwidth, \
  104. _pshift, _pwidth, \
  105. _muxshift, _muxwidth, \
  106. _gate, _flags) \
  107. struct ccu_mp _struct = { \
  108. .enable = _gate, \
  109. .m = _SUNXI_CCU_DIV(_mshift, _mwidth), \
  110. .p = _SUNXI_CCU_DIV(_pshift, _pwidth), \
  111. .mux = _SUNXI_CCU_MUX(_muxshift, _muxwidth), \
  112. .common = { \
  113. .reg = _reg, \
  114. .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \
  115. _parents, \
  116. &ccu_mp_ops, \
  117. _flags), \
  118. } \
  119. }
  120. static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
  121. {
  122. struct ccu_common *common = hw_to_ccu_common(hw);
  123. return container_of(common, struct ccu_mp, common);
  124. }
  125. extern const struct clk_ops ccu_mp_ops;
  126. /*
  127. * Special class of M-P clock that supports MMC timing modes
  128. *
  129. * Since the MMC clock registers all follow the same layout, we can
  130. * simplify the macro for this particular case. In addition, as
  131. * switching modes also affects the output clock rate, we need to
  132. * have CLK_GET_RATE_NOCACHE for all these types of clocks.
  133. */
  134. #define SUNXI_CCU_MP_MMC_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
  135. _flags) \
  136. struct ccu_mp _struct = { \
  137. .enable = BIT(31), \
  138. .m = _SUNXI_CCU_DIV(0, 4), \
  139. .p = _SUNXI_CCU_DIV(16, 2), \
  140. .mux = _SUNXI_CCU_MUX(24, 2), \
  141. .common = { \
  142. .reg = _reg, \
  143. .features = CCU_FEATURE_MMC_TIMING_SWITCH, \
  144. .hw.init = CLK_HW_INIT_PARENTS(_name, \
  145. _parents, \
  146. &ccu_mp_mmc_ops, \
  147. CLK_GET_RATE_NOCACHE | \
  148. _flags), \
  149. } \
  150. }
  151. extern const struct clk_ops ccu_mp_mmc_ops;
  152. #endif /* _CCU_MP_H_ */