mcde_clk_div.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/clk-provider.h>
  3. #include <linux/io.h>
  4. #include <linux/regulator/consumer.h>
  5. #include "mcde_drm.h"
  6. #include "mcde_display_regs.h"
  7. /* The MCDE internal clock dividers for FIFO A and B */
  8. struct mcde_clk_div {
  9. struct clk_hw hw;
  10. struct mcde *mcde;
  11. u32 cr;
  12. u32 cr_div;
  13. };
  14. static int mcde_clk_div_enable(struct clk_hw *hw)
  15. {
  16. struct mcde_clk_div *cdiv = container_of(hw, struct mcde_clk_div, hw);
  17. struct mcde *mcde = cdiv->mcde;
  18. u32 val;
  19. spin_lock(&mcde->fifo_crx1_lock);
  20. val = readl(mcde->regs + cdiv->cr);
  21. /*
  22. * Select the PLL72 (LCD) clock as parent
  23. * FIXME: implement other parents.
  24. */
  25. val &= ~MCDE_CRX1_CLKSEL_MASK;
  26. val |= MCDE_CRX1_CLKSEL_CLKPLL72 << MCDE_CRX1_CLKSEL_SHIFT;
  27. /* Internal clock */
  28. val |= MCDE_CRA1_CLKTYPE_TVXCLKSEL1;
  29. /* Clear then set the divider */
  30. val &= ~(MCDE_CRX1_BCD | MCDE_CRX1_PCD_MASK);
  31. val |= cdiv->cr_div;
  32. writel(val, mcde->regs + cdiv->cr);
  33. spin_unlock(&mcde->fifo_crx1_lock);
  34. return 0;
  35. }
  36. static int mcde_clk_div_choose_div(struct clk_hw *hw, unsigned long rate,
  37. unsigned long *prate, bool set_parent)
  38. {
  39. int best_div = 1, div;
  40. struct clk_hw *parent = clk_hw_get_parent(hw);
  41. unsigned long best_prate = 0;
  42. unsigned long best_diff = ~0ul;
  43. int max_div = (1 << MCDE_CRX1_PCD_BITS) - 1;
  44. for (div = 1; div < max_div; div++) {
  45. unsigned long this_prate, div_rate, diff;
  46. if (set_parent)
  47. this_prate = clk_hw_round_rate(parent, rate * div);
  48. else
  49. this_prate = *prate;
  50. div_rate = DIV_ROUND_UP_ULL(this_prate, div);
  51. diff = abs(rate - div_rate);
  52. if (diff < best_diff) {
  53. best_div = div;
  54. best_diff = diff;
  55. best_prate = this_prate;
  56. }
  57. }
  58. *prate = best_prate;
  59. return best_div;
  60. }
  61. static long mcde_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
  62. unsigned long *prate)
  63. {
  64. int div = mcde_clk_div_choose_div(hw, rate, prate, true);
  65. return DIV_ROUND_UP_ULL(*prate, div);
  66. }
  67. static unsigned long mcde_clk_div_recalc_rate(struct clk_hw *hw,
  68. unsigned long prate)
  69. {
  70. struct mcde_clk_div *cdiv = container_of(hw, struct mcde_clk_div, hw);
  71. struct mcde *mcde = cdiv->mcde;
  72. u32 cr;
  73. int div;
  74. /*
  75. * If the MCDE is not powered we can't access registers.
  76. * It will come up with 0 in the divider register bits, which
  77. * means "divide by 2".
  78. */
  79. if (!regulator_is_enabled(mcde->epod))
  80. return DIV_ROUND_UP_ULL(prate, 2);
  81. cr = readl(mcde->regs + cdiv->cr);
  82. if (cr & MCDE_CRX1_BCD)
  83. return prate;
  84. /* 0 in the PCD means "divide by 2", 1 means "divide by 3" etc */
  85. div = cr & MCDE_CRX1_PCD_MASK;
  86. div += 2;
  87. return DIV_ROUND_UP_ULL(prate, div);
  88. }
  89. static int mcde_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
  90. unsigned long prate)
  91. {
  92. struct mcde_clk_div *cdiv = container_of(hw, struct mcde_clk_div, hw);
  93. int div = mcde_clk_div_choose_div(hw, rate, &prate, false);
  94. u32 cr = 0;
  95. /*
  96. * We cache the CR bits to set the divide in the state so that
  97. * we can call this before we can even write to the hardware.
  98. */
  99. if (div == 1) {
  100. /* Bypass clock divider */
  101. cr |= MCDE_CRX1_BCD;
  102. } else {
  103. div -= 2;
  104. cr |= div & MCDE_CRX1_PCD_MASK;
  105. }
  106. cdiv->cr_div = cr;
  107. return 0;
  108. }
  109. static const struct clk_ops mcde_clk_div_ops = {
  110. .enable = mcde_clk_div_enable,
  111. .recalc_rate = mcde_clk_div_recalc_rate,
  112. .round_rate = mcde_clk_div_round_rate,
  113. .set_rate = mcde_clk_div_set_rate,
  114. };
  115. int mcde_init_clock_divider(struct mcde *mcde)
  116. {
  117. struct device *dev = mcde->dev;
  118. struct mcde_clk_div *fifoa;
  119. struct mcde_clk_div *fifob;
  120. const char *parent_name;
  121. struct clk_init_data fifoa_init = {
  122. .name = "fifoa",
  123. .ops = &mcde_clk_div_ops,
  124. .parent_names = &parent_name,
  125. .num_parents = 1,
  126. .flags = CLK_SET_RATE_PARENT,
  127. };
  128. struct clk_init_data fifob_init = {
  129. .name = "fifob",
  130. .ops = &mcde_clk_div_ops,
  131. .parent_names = &parent_name,
  132. .num_parents = 1,
  133. .flags = CLK_SET_RATE_PARENT,
  134. };
  135. int ret;
  136. spin_lock_init(&mcde->fifo_crx1_lock);
  137. parent_name = __clk_get_name(mcde->lcd_clk);
  138. /* Allocate 2 clocks */
  139. fifoa = devm_kzalloc(dev, sizeof(*fifoa), GFP_KERNEL);
  140. if (!fifoa)
  141. return -ENOMEM;
  142. fifob = devm_kzalloc(dev, sizeof(*fifob), GFP_KERNEL);
  143. if (!fifob)
  144. return -ENOMEM;
  145. fifoa->mcde = mcde;
  146. fifoa->cr = MCDE_CRA1;
  147. fifoa->hw.init = &fifoa_init;
  148. ret = devm_clk_hw_register(dev, &fifoa->hw);
  149. if (ret) {
  150. dev_err(dev, "error registering FIFO A clock divider\n");
  151. return ret;
  152. }
  153. mcde->fifoa_clk = fifoa->hw.clk;
  154. fifob->mcde = mcde;
  155. fifob->cr = MCDE_CRB1;
  156. fifob->hw.init = &fifob_init;
  157. ret = devm_clk_hw_register(dev, &fifob->hw);
  158. if (ret) {
  159. dev_err(dev, "error registering FIFO B clock divider\n");
  160. return ret;
  161. }
  162. mcde->fifob_clk = fifob->hw.clk;
  163. return 0;
  164. }