clk-frac.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * mmp factor clock operation source file
  3. *
  4. * Copyright (C) 2012 Marvell
  5. * Chao Xie <xiechao.mail@gmail.com>
  6. *
  7. * This file is licensed under the terms of the GNU General Public
  8. * License version 2. This program is licensed "as is" without any
  9. * warranty of any kind, whether express or implied.
  10. */
  11. #include <linux/clk-provider.h>
  12. #include <linux/slab.h>
  13. #include <linux/io.h>
  14. #include <linux/err.h>
  15. #include "clk.h"
  16. /*
  17. * It is M/N clock
  18. *
  19. * Fout from synthesizer can be given from two equations:
  20. * numerator/denominator = Fin / (Fout * factor)
  21. */
  22. #define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
  23. struct clk_factor {
  24. struct clk_hw hw;
  25. void __iomem *base;
  26. struct clk_factor_masks *masks;
  27. struct clk_factor_tbl *ftbl;
  28. unsigned int ftbl_cnt;
  29. };
  30. static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
  31. unsigned long *prate)
  32. {
  33. struct clk_factor *factor = to_clk_factor(hw);
  34. unsigned long rate = 0, prev_rate;
  35. int i;
  36. for (i = 0; i < factor->ftbl_cnt; i++) {
  37. prev_rate = rate;
  38. rate = (((*prate / 10000) * factor->ftbl[i].num) /
  39. (factor->ftbl[i].den * factor->masks->factor)) * 10000;
  40. if (rate > drate)
  41. break;
  42. }
  43. if (i == 0)
  44. return rate;
  45. else
  46. return prev_rate;
  47. }
  48. static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
  49. unsigned long parent_rate)
  50. {
  51. struct clk_factor *factor = to_clk_factor(hw);
  52. struct clk_factor_masks *masks = factor->masks;
  53. unsigned int val, num, den;
  54. val = readl_relaxed(factor->base);
  55. /* calculate numerator */
  56. num = (val >> masks->num_shift) & masks->num_mask;
  57. /* calculate denominator */
  58. den = (val >> masks->den_shift) & masks->num_mask;
  59. if (!den)
  60. return 0;
  61. return (((parent_rate / 10000) * den) /
  62. (num * factor->masks->factor)) * 10000;
  63. }
  64. /* Configures new clock rate*/
  65. static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
  66. unsigned long prate)
  67. {
  68. struct clk_factor *factor = to_clk_factor(hw);
  69. struct clk_factor_masks *masks = factor->masks;
  70. int i;
  71. unsigned long val;
  72. unsigned long prev_rate, rate = 0;
  73. for (i = 0; i < factor->ftbl_cnt; i++) {
  74. prev_rate = rate;
  75. rate = (((prate / 10000) * factor->ftbl[i].num) /
  76. (factor->ftbl[i].den * factor->masks->factor)) * 10000;
  77. if (rate > drate)
  78. break;
  79. }
  80. if (i > 0)
  81. i--;
  82. val = readl_relaxed(factor->base);
  83. val &= ~(masks->num_mask << masks->num_shift);
  84. val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift;
  85. val &= ~(masks->den_mask << masks->den_shift);
  86. val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift;
  87. writel_relaxed(val, factor->base);
  88. return 0;
  89. }
  90. static struct clk_ops clk_factor_ops = {
  91. .recalc_rate = clk_factor_recalc_rate,
  92. .round_rate = clk_factor_round_rate,
  93. .set_rate = clk_factor_set_rate,
  94. };
  95. struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
  96. unsigned long flags, void __iomem *base,
  97. struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
  98. unsigned int ftbl_cnt)
  99. {
  100. struct clk_factor *factor;
  101. struct clk_init_data init;
  102. struct clk *clk;
  103. if (!masks) {
  104. pr_err("%s: must pass a clk_factor_mask\n", __func__);
  105. return ERR_PTR(-EINVAL);
  106. }
  107. factor = kzalloc(sizeof(*factor), GFP_KERNEL);
  108. if (!factor) {
  109. pr_err("%s: could not allocate factor clk\n", __func__);
  110. return ERR_PTR(-ENOMEM);
  111. }
  112. /* struct clk_aux assignments */
  113. factor->base = base;
  114. factor->masks = masks;
  115. factor->ftbl = ftbl;
  116. factor->ftbl_cnt = ftbl_cnt;
  117. factor->hw.init = &init;
  118. init.name = name;
  119. init.ops = &clk_factor_ops;
  120. init.flags = flags;
  121. init.parent_names = &parent_name;
  122. init.num_parents = 1;
  123. clk = clk_register(NULL, &factor->hw);
  124. if (IS_ERR_OR_NULL(clk))
  125. kfree(factor);
  126. return clk;
  127. }