clk-regmap.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) 2018 BayLibre, SAS.
  3. // Author: Jerome Brunet <jbrunet@baylibre.com>
  4. #include "clk-regmap.h"
  5. static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
  6. {
  7. struct clk_regmap *clk = to_clk_regmap(hw);
  8. struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
  9. int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
  10. set ^= enable;
  11. return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx),
  12. set ? BIT(gate->bit_idx) : 0);
  13. }
  14. static int clk_regmap_gate_enable(struct clk_hw *hw)
  15. {
  16. return clk_regmap_gate_endisable(hw, 1);
  17. }
  18. static void clk_regmap_gate_disable(struct clk_hw *hw)
  19. {
  20. clk_regmap_gate_endisable(hw, 0);
  21. }
  22. static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
  23. {
  24. struct clk_regmap *clk = to_clk_regmap(hw);
  25. struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
  26. unsigned int val;
  27. regmap_read(clk->map, gate->offset, &val);
  28. if (gate->flags & CLK_GATE_SET_TO_DISABLE)
  29. val ^= BIT(gate->bit_idx);
  30. val &= BIT(gate->bit_idx);
  31. return val ? 1 : 0;
  32. }
  33. const struct clk_ops clk_regmap_gate_ops = {
  34. .enable = clk_regmap_gate_enable,
  35. .disable = clk_regmap_gate_disable,
  36. .is_enabled = clk_regmap_gate_is_enabled,
  37. };
  38. EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
  39. static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
  40. unsigned long prate)
  41. {
  42. struct clk_regmap *clk = to_clk_regmap(hw);
  43. struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
  44. unsigned int val;
  45. int ret;
  46. ret = regmap_read(clk->map, div->offset, &val);
  47. if (ret)
  48. /* Gives a hint that something is wrong */
  49. return 0;
  50. val >>= div->shift;
  51. val &= clk_div_mask(div->width);
  52. return divider_recalc_rate(hw, prate, val, div->table, div->flags,
  53. div->width);
  54. }
  55. static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate,
  56. unsigned long *prate)
  57. {
  58. struct clk_regmap *clk = to_clk_regmap(hw);
  59. struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
  60. unsigned int val;
  61. int ret;
  62. /* if read only, just return current value */
  63. if (div->flags & CLK_DIVIDER_READ_ONLY) {
  64. ret = regmap_read(clk->map, div->offset, &val);
  65. if (ret)
  66. /* Gives a hint that something is wrong */
  67. return 0;
  68. val >>= div->shift;
  69. val &= clk_div_mask(div->width);
  70. return divider_ro_round_rate(hw, rate, prate, div->table,
  71. div->width, div->flags, val);
  72. }
  73. return divider_round_rate(hw, rate, prate, div->table, div->width,
  74. div->flags);
  75. }
  76. static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate,
  77. unsigned long parent_rate)
  78. {
  79. struct clk_regmap *clk = to_clk_regmap(hw);
  80. struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
  81. unsigned int val;
  82. int ret;
  83. ret = divider_get_val(rate, parent_rate, div->table, div->width,
  84. div->flags);
  85. if (ret < 0)
  86. return ret;
  87. val = (unsigned int)ret << div->shift;
  88. return regmap_update_bits(clk->map, div->offset,
  89. clk_div_mask(div->width) << div->shift, val);
  90. };
  91. /* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
  92. const struct clk_ops clk_regmap_divider_ops = {
  93. .recalc_rate = clk_regmap_div_recalc_rate,
  94. .round_rate = clk_regmap_div_round_rate,
  95. .set_rate = clk_regmap_div_set_rate,
  96. };
  97. EXPORT_SYMBOL_GPL(clk_regmap_divider_ops);
  98. const struct clk_ops clk_regmap_divider_ro_ops = {
  99. .recalc_rate = clk_regmap_div_recalc_rate,
  100. .round_rate = clk_regmap_div_round_rate,
  101. };
  102. EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops);
  103. static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
  104. {
  105. struct clk_regmap *clk = to_clk_regmap(hw);
  106. struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
  107. unsigned int val;
  108. int ret;
  109. ret = regmap_read(clk->map, mux->offset, &val);
  110. if (ret)
  111. return ret;
  112. val >>= mux->shift;
  113. val &= mux->mask;
  114. return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
  115. }
  116. static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
  117. {
  118. struct clk_regmap *clk = to_clk_regmap(hw);
  119. struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
  120. unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index);
  121. return regmap_update_bits(clk->map, mux->offset,
  122. mux->mask << mux->shift,
  123. val << mux->shift);
  124. }
  125. static int clk_regmap_mux_determine_rate(struct clk_hw *hw,
  126. struct clk_rate_request *req)
  127. {
  128. struct clk_regmap *clk = to_clk_regmap(hw);
  129. struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
  130. return clk_mux_determine_rate_flags(hw, req, mux->flags);
  131. }
  132. const struct clk_ops clk_regmap_mux_ops = {
  133. .get_parent = clk_regmap_mux_get_parent,
  134. .set_parent = clk_regmap_mux_set_parent,
  135. .determine_rate = clk_regmap_mux_determine_rate,
  136. };
  137. EXPORT_SYMBOL_GPL(clk_regmap_mux_ops);
  138. const struct clk_ops clk_regmap_mux_ro_ops = {
  139. .get_parent = clk_regmap_mux_get_parent,
  140. };
  141. EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);