clk-aux-synth.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2012 ST Microelectronics
  4. * Viresh Kumar <[email protected]>
  5. *
  6. * Auxiliary Synthesizer clock implementation
  7. */
  8. #define pr_fmt(fmt) "clk-aux-synth: " fmt
  9. #include <linux/clk-provider.h>
  10. #include <linux/slab.h>
  11. #include <linux/io.h>
  12. #include <linux/err.h>
  13. #include "clk.h"
  14. /*
  15. * DOC: Auxiliary Synthesizer clock
  16. *
  17. * Aux synth gives rate for different values of eq, x and y
  18. *
  19. * Fout from synthesizer can be given from two equations:
  20. * Fout1 = (Fin * X/Y)/2 EQ1
  21. * Fout2 = Fin * X/Y EQ2
  22. */
  23. #define to_clk_aux(_hw) container_of(_hw, struct clk_aux, hw)
  24. static const struct aux_clk_masks default_aux_masks = {
  25. .eq_sel_mask = AUX_EQ_SEL_MASK,
  26. .eq_sel_shift = AUX_EQ_SEL_SHIFT,
  27. .eq1_mask = AUX_EQ1_SEL,
  28. .eq2_mask = AUX_EQ2_SEL,
  29. .xscale_sel_mask = AUX_XSCALE_MASK,
  30. .xscale_sel_shift = AUX_XSCALE_SHIFT,
  31. .yscale_sel_mask = AUX_YSCALE_MASK,
  32. .yscale_sel_shift = AUX_YSCALE_SHIFT,
  33. .enable_bit = AUX_SYNT_ENB,
  34. };
  35. static unsigned long aux_calc_rate(struct clk_hw *hw, unsigned long prate,
  36. int index)
  37. {
  38. struct clk_aux *aux = to_clk_aux(hw);
  39. struct aux_rate_tbl *rtbl = aux->rtbl;
  40. u8 eq = rtbl[index].eq ? 1 : 2;
  41. return (((prate / 10000) * rtbl[index].xscale) /
  42. (rtbl[index].yscale * eq)) * 10000;
  43. }
  44. static long clk_aux_round_rate(struct clk_hw *hw, unsigned long drate,
  45. unsigned long *prate)
  46. {
  47. struct clk_aux *aux = to_clk_aux(hw);
  48. int unused;
  49. return clk_round_rate_index(hw, drate, *prate, aux_calc_rate,
  50. aux->rtbl_cnt, &unused);
  51. }
  52. static unsigned long clk_aux_recalc_rate(struct clk_hw *hw,
  53. unsigned long parent_rate)
  54. {
  55. struct clk_aux *aux = to_clk_aux(hw);
  56. unsigned int num = 1, den = 1, val, eqn;
  57. unsigned long flags = 0;
  58. if (aux->lock)
  59. spin_lock_irqsave(aux->lock, flags);
  60. val = readl_relaxed(aux->reg);
  61. if (aux->lock)
  62. spin_unlock_irqrestore(aux->lock, flags);
  63. eqn = (val >> aux->masks->eq_sel_shift) & aux->masks->eq_sel_mask;
  64. if (eqn == aux->masks->eq1_mask)
  65. den = 2;
  66. /* calculate numerator */
  67. num = (val >> aux->masks->xscale_sel_shift) &
  68. aux->masks->xscale_sel_mask;
  69. /* calculate denominator */
  70. den *= (val >> aux->masks->yscale_sel_shift) &
  71. aux->masks->yscale_sel_mask;
  72. if (!den)
  73. return 0;
  74. return (((parent_rate / 10000) * num) / den) * 10000;
  75. }
  76. /* Configures new clock rate of aux */
  77. static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate,
  78. unsigned long prate)
  79. {
  80. struct clk_aux *aux = to_clk_aux(hw);
  81. struct aux_rate_tbl *rtbl = aux->rtbl;
  82. unsigned long val, flags = 0;
  83. int i;
  84. clk_round_rate_index(hw, drate, prate, aux_calc_rate, aux->rtbl_cnt,
  85. &i);
  86. if (aux->lock)
  87. spin_lock_irqsave(aux->lock, flags);
  88. val = readl_relaxed(aux->reg) &
  89. ~(aux->masks->eq_sel_mask << aux->masks->eq_sel_shift);
  90. val |= (rtbl[i].eq & aux->masks->eq_sel_mask) <<
  91. aux->masks->eq_sel_shift;
  92. val &= ~(aux->masks->xscale_sel_mask << aux->masks->xscale_sel_shift);
  93. val |= (rtbl[i].xscale & aux->masks->xscale_sel_mask) <<
  94. aux->masks->xscale_sel_shift;
  95. val &= ~(aux->masks->yscale_sel_mask << aux->masks->yscale_sel_shift);
  96. val |= (rtbl[i].yscale & aux->masks->yscale_sel_mask) <<
  97. aux->masks->yscale_sel_shift;
  98. writel_relaxed(val, aux->reg);
  99. if (aux->lock)
  100. spin_unlock_irqrestore(aux->lock, flags);
  101. return 0;
  102. }
  103. static const struct clk_ops clk_aux_ops = {
  104. .recalc_rate = clk_aux_recalc_rate,
  105. .round_rate = clk_aux_round_rate,
  106. .set_rate = clk_aux_set_rate,
  107. };
  108. struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
  109. const char *parent_name, unsigned long flags, void __iomem *reg,
  110. const struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl,
  111. u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk)
  112. {
  113. struct clk_aux *aux;
  114. struct clk_init_data init;
  115. struct clk *clk;
  116. if (!aux_name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
  117. pr_err("Invalid arguments passed");
  118. return ERR_PTR(-EINVAL);
  119. }
  120. aux = kzalloc(sizeof(*aux), GFP_KERNEL);
  121. if (!aux)
  122. return ERR_PTR(-ENOMEM);
  123. /* struct clk_aux assignments */
  124. if (!masks)
  125. aux->masks = &default_aux_masks;
  126. else
  127. aux->masks = masks;
  128. aux->reg = reg;
  129. aux->rtbl = rtbl;
  130. aux->rtbl_cnt = rtbl_cnt;
  131. aux->lock = lock;
  132. aux->hw.init = &init;
  133. init.name = aux_name;
  134. init.ops = &clk_aux_ops;
  135. init.flags = flags;
  136. init.parent_names = &parent_name;
  137. init.num_parents = 1;
  138. clk = clk_register(NULL, &aux->hw);
  139. if (IS_ERR_OR_NULL(clk))
  140. goto free_aux;
  141. if (gate_name) {
  142. struct clk *tgate_clk;
  143. tgate_clk = clk_register_gate(NULL, gate_name, aux_name,
  144. CLK_SET_RATE_PARENT, reg,
  145. aux->masks->enable_bit, 0, lock);
  146. if (IS_ERR_OR_NULL(tgate_clk))
  147. goto free_aux;
  148. if (gate_clk)
  149. *gate_clk = tgate_clk;
  150. }
  151. return clk;
  152. free_aux:
  153. kfree(aux);
  154. pr_err("clk register failed\n");
  155. return NULL;
  156. }