clk.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com>
  4. */
  5. #include <common.h>
  6. #include <div64.h>
  7. #include <asm/arch/cpu.h>
  8. #include <asm/arch/clk.h>
  9. #include <asm/io.h>
  10. static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
  11. unsigned int get_sys_clk_rate(void)
  12. {
  13. if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397)
  14. return RTC_CLK_FREQUENCY * 397;
  15. else
  16. return OSC_CLK_FREQUENCY;
  17. }
  18. unsigned int get_hclk_pll_rate(void)
  19. {
  20. unsigned long long fin, fref, fcco, fout;
  21. u32 val, m_div, n_div, p_div;
  22. /*
  23. * Valid frequency ranges:
  24. * 1 * 10^6 <= Fin <= 20 * 10^6
  25. * 1 * 10^6 <= Fref <= 27 * 10^6
  26. * 156 * 10^6 <= Fcco <= 320 * 10^6
  27. */
  28. fref = fin = get_sys_clk_rate();
  29. if (fin > 20000000ULL || fin < 1000000ULL)
  30. return 0;
  31. val = readl(&clk->hclkpll_ctrl);
  32. m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1;
  33. n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1;
  34. if (val & CLK_HCLK_PLL_DIRECT)
  35. p_div = 0;
  36. else
  37. p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1;
  38. p_div = 1 << p_div;
  39. if (val & CLK_HCLK_PLL_BYPASS) {
  40. do_div(fin, p_div);
  41. return fin;
  42. }
  43. do_div(fref, n_div);
  44. if (fref > 27000000ULL || fref < 1000000ULL)
  45. return 0;
  46. fcco = fref * m_div;
  47. fout = fcco;
  48. if (val & CLK_HCLK_PLL_FEEDBACK)
  49. fcco *= p_div;
  50. else
  51. do_div(fout, p_div);
  52. if (fcco > 320000000ULL || fcco < 156000000ULL)
  53. return 0;
  54. return fout;
  55. }
  56. unsigned int get_hclk_clk_div(void)
  57. {
  58. u32 val;
  59. val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK;
  60. return 1 << val;
  61. }
  62. unsigned int get_hclk_clk_rate(void)
  63. {
  64. return get_hclk_pll_rate() / get_hclk_clk_div();
  65. }
  66. unsigned int get_periph_clk_div(void)
  67. {
  68. u32 val;
  69. val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK;
  70. return (val >> 2) + 1;
  71. }
  72. unsigned int get_periph_clk_rate(void)
  73. {
  74. if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
  75. return get_sys_clk_rate();
  76. return get_hclk_pll_rate() / get_periph_clk_div();
  77. }
  78. unsigned int get_sdram_clk_rate(void)
  79. {
  80. unsigned int src_clk;
  81. if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
  82. return get_sys_clk_rate();
  83. src_clk = get_hclk_pll_rate();
  84. if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) {
  85. /* using DDR */
  86. switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) {
  87. case CLK_HCLK_DDRAM_HALF:
  88. return src_clk/2;
  89. case CLK_HCLK_DDRAM_NOMINAL:
  90. return src_clk;
  91. default:
  92. return 0;
  93. }
  94. } else {
  95. /* using SDR */
  96. switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) {
  97. case CLK_HCLK_ARM_PLL_DIV_4:
  98. return src_clk/4;
  99. case CLK_HCLK_ARM_PLL_DIV_2:
  100. return src_clk/2;
  101. case CLK_HCLK_ARM_PLL_DIV_1:
  102. return src_clk;
  103. default:
  104. return 0;
  105. }
  106. }
  107. }
  108. int get_serial_clock(void)
  109. {
  110. return get_periph_clk_rate();
  111. }