mv98dx3236.c 4.9 KB

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