mv98dx3236.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Marvell MV98DX3236 SoC clocks
  4. *
  5. * Copyright (C) 2012 Marvell
  6. *
  7. * Gregory CLEMENT <[email protected]>
  8. * Sebastian Hesselbarth <[email protected]>
  9. * Andrew Lunn <[email protected]>
  10. *
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/clk-provider.h>
  14. #include <linux/io.h>
  15. #include <linux/of.h>
  16. #include "common.h"
  17. /*
  18. * For 98DX4251 Sample At Reset the CPU, DDR and Main PLL clocks are all
  19. * defined at the same time
  20. *
  21. * SAR1[20:18] : CPU frequency DDR frequency MPLL frequency
  22. * 0 = 400 MHz 400 MHz 800 MHz
  23. * 2 = 667 MHz 667 MHz 2000 MHz
  24. * 3 = 800 MHz 800 MHz 1600 MHz
  25. * others reserved.
  26. *
  27. * For 98DX3236 Sample At Reset the CPU, DDR and Main PLL clocks are all
  28. * defined at the same time
  29. *
  30. * SAR1[20:18] : CPU frequency DDR frequency MPLL frequency
  31. * 1 = 667 MHz 667 MHz 2000 MHz
  32. * 2 = 400 MHz 400 MHz 400 MHz
  33. * 3 = 800 MHz 800 MHz 800 MHz
  34. * 5 = 800 MHz 400 MHz 800 MHz
  35. * others reserved.
  36. */
  37. #define SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT 18
  38. #define SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT_MASK 0x7
  39. static u32 __init mv98dx3236_get_tclk_freq(void __iomem *sar)
  40. {
  41. /* Tclk = 200MHz, no SaR dependency */
  42. return 200000000;
  43. }
  44. static const u32 mv98dx3236_cpu_frequencies[] __initconst = {
  45. 0,
  46. 667000000,
  47. 400000000,
  48. 800000000,
  49. 0,
  50. 800000000,
  51. 0, 0,
  52. };
  53. static const u32 mv98dx4251_cpu_frequencies[] __initconst = {
  54. 400000000,
  55. 0,
  56. 667000000,
  57. 800000000,
  58. 0, 0, 0, 0,
  59. };
  60. static u32 __init mv98dx3236_get_cpu_freq(void __iomem *sar)
  61. {
  62. u32 cpu_freq = 0;
  63. u8 cpu_freq_select = 0;
  64. cpu_freq_select = ((readl(sar) >> SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT) &
  65. SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT_MASK);
  66. if (of_machine_is_compatible("marvell,armadaxp-98dx4251"))
  67. cpu_freq = mv98dx4251_cpu_frequencies[cpu_freq_select];
  68. else if (of_machine_is_compatible("marvell,armadaxp-98dx3236"))
  69. cpu_freq = mv98dx3236_cpu_frequencies[cpu_freq_select];
  70. if (!cpu_freq)
  71. pr_err("CPU freq select unsupported %d\n", cpu_freq_select);
  72. return cpu_freq;
  73. }
  74. enum {
  75. MV98DX3236_CPU_TO_DDR,
  76. MV98DX3236_CPU_TO_MPLL
  77. };
  78. static const struct coreclk_ratio mv98dx3236_core_ratios[] __initconst = {
  79. { .id = MV98DX3236_CPU_TO_DDR, .name = "ddrclk" },
  80. { .id = MV98DX3236_CPU_TO_MPLL, .name = "mpll" },
  81. };
  82. static const int __initconst mv98dx3236_cpu_mpll_ratios[8][2] = {
  83. {0, 1}, {3, 1}, {1, 1}, {1, 1},
  84. {0, 1}, {1, 1}, {0, 1}, {0, 1},
  85. };
  86. static const int __initconst mv98dx3236_cpu_ddr_ratios[8][2] = {
  87. {0, 1}, {1, 1}, {1, 1}, {1, 1},
  88. {0, 1}, {1, 2}, {0, 1}, {0, 1},
  89. };
  90. static const int __initconst mv98dx4251_cpu_mpll_ratios[8][2] = {
  91. {2, 1}, {0, 1}, {3, 1}, {2, 1},
  92. {0, 1}, {0, 1}, {0, 1}, {0, 1},
  93. };
  94. static const int __initconst mv98dx4251_cpu_ddr_ratios[8][2] = {
  95. {1, 1}, {0, 1}, {1, 1}, {1, 1},
  96. {0, 1}, {0, 1}, {0, 1}, {0, 1},
  97. };
  98. static void __init mv98dx3236_get_clk_ratio(
  99. void __iomem *sar, int id, int *mult, int *div)
  100. {
  101. u32 opt = ((readl(sar) >> SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT) &
  102. SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT_MASK);
  103. switch (id) {
  104. case MV98DX3236_CPU_TO_DDR:
  105. if (of_machine_is_compatible("marvell,armadaxp-98dx4251")) {
  106. *mult = mv98dx4251_cpu_ddr_ratios[opt][0];
  107. *div = mv98dx4251_cpu_ddr_ratios[opt][1];
  108. } else if (of_machine_is_compatible("marvell,armadaxp-98dx3236")) {
  109. *mult = mv98dx3236_cpu_ddr_ratios[opt][0];
  110. *div = mv98dx3236_cpu_ddr_ratios[opt][1];
  111. }
  112. break;
  113. case MV98DX3236_CPU_TO_MPLL:
  114. if (of_machine_is_compatible("marvell,armadaxp-98dx4251")) {
  115. *mult = mv98dx4251_cpu_mpll_ratios[opt][0];
  116. *div = mv98dx4251_cpu_mpll_ratios[opt][1];
  117. } else if (of_machine_is_compatible("marvell,armadaxp-98dx3236")) {
  118. *mult = mv98dx3236_cpu_mpll_ratios[opt][0];
  119. *div = mv98dx3236_cpu_mpll_ratios[opt][1];
  120. }
  121. break;
  122. }
  123. }
  124. static const struct coreclk_soc_desc mv98dx3236_core_clocks = {
  125. .get_tclk_freq = mv98dx3236_get_tclk_freq,
  126. .get_cpu_freq = mv98dx3236_get_cpu_freq,
  127. .get_clk_ratio = mv98dx3236_get_clk_ratio,
  128. .ratios = mv98dx3236_core_ratios,
  129. .num_ratios = ARRAY_SIZE(mv98dx3236_core_ratios),
  130. };
  131. /*
  132. * Clock Gating Control
  133. */
  134. static const struct clk_gating_soc_desc mv98dx3236_gating_desc[] __initconst = {
  135. { "ge1", NULL, 3, 0 },
  136. { "ge0", NULL, 4, 0 },
  137. { "pex00", NULL, 5, 0 },
  138. { "sdio", NULL, 17, 0 },
  139. { "usb0", NULL, 18, 0 },
  140. { "xor0", NULL, 22, 0 },
  141. { }
  142. };
  143. static void __init mv98dx3236_clk_init(struct device_node *np)
  144. {
  145. struct device_node *cgnp =
  146. of_find_compatible_node(NULL, NULL, "marvell,mv98dx3236-gating-clock");
  147. mvebu_coreclk_setup(np, &mv98dx3236_core_clocks);
  148. if (cgnp) {
  149. mvebu_clk_gating_setup(cgnp, mv98dx3236_gating_desc);
  150. of_node_put(cgnp);
  151. }
  152. }
  153. CLK_OF_DECLARE(mv98dx3236_clk, "marvell,mv98dx3236-core-clock", mv98dx3236_clk_init);