armada-39x.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Marvell Armada 39x SoC clocks
  4. *
  5. * Copyright (C) 2015 Marvell
  6. *
  7. * Gregory CLEMENT <gregory.clement@free-electrons.com>
  8. * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
  9. * Andrew Lunn <andrew@lunn.ch>
  10. * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  11. *
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/clk-provider.h>
  15. #include <linux/io.h>
  16. #include <linux/of.h>
  17. #include "common.h"
  18. /*
  19. * SARL[14:10] : Ratios between CPU, NBCLK, HCLK and DCLK.
  20. *
  21. * SARL[15] : TCLK frequency
  22. * 0 = 250 MHz
  23. * 1 = 200 MHz
  24. *
  25. * SARH[0] : Reference clock frequency
  26. * 0 = 25 Mhz
  27. * 1 = 40 Mhz
  28. */
  29. #define SARL 0
  30. #define SARL_A390_TCLK_FREQ_OPT 15
  31. #define SARL_A390_TCLK_FREQ_OPT_MASK 0x1
  32. #define SARL_A390_CPU_DDR_L2_FREQ_OPT 10
  33. #define SARL_A390_CPU_DDR_L2_FREQ_OPT_MASK 0x1F
  34. #define SARH 4
  35. #define SARH_A390_REFCLK_FREQ BIT(0)
  36. static const u32 armada_39x_tclk_frequencies[] __initconst = {
  37. 250000000,
  38. 200000000,
  39. };
  40. static u32 __init armada_39x_get_tclk_freq(void __iomem *sar)
  41. {
  42. u8 tclk_freq_select;
  43. tclk_freq_select = ((readl(sar + SARL) >> SARL_A390_TCLK_FREQ_OPT) &
  44. SARL_A390_TCLK_FREQ_OPT_MASK);
  45. return armada_39x_tclk_frequencies[tclk_freq_select];
  46. }
  47. static const u32 armada_39x_cpu_frequencies[] __initconst = {
  48. [0x0] = 666 * 1000 * 1000,
  49. [0x2] = 800 * 1000 * 1000,
  50. [0x3] = 800 * 1000 * 1000,
  51. [0x4] = 1066 * 1000 * 1000,
  52. [0x5] = 1066 * 1000 * 1000,
  53. [0x6] = 1200 * 1000 * 1000,
  54. [0x8] = 1332 * 1000 * 1000,
  55. [0xB] = 1600 * 1000 * 1000,
  56. [0xC] = 1600 * 1000 * 1000,
  57. [0x12] = 1800 * 1000 * 1000,
  58. [0x1E] = 1800 * 1000 * 1000,
  59. };
  60. static u32 __init armada_39x_get_cpu_freq(void __iomem *sar)
  61. {
  62. u8 cpu_freq_select;
  63. cpu_freq_select = ((readl(sar + SARL) >> SARL_A390_CPU_DDR_L2_FREQ_OPT) &
  64. SARL_A390_CPU_DDR_L2_FREQ_OPT_MASK);
  65. if (cpu_freq_select >= ARRAY_SIZE(armada_39x_cpu_frequencies)) {
  66. pr_err("Selected CPU frequency (%d) unsupported\n",
  67. cpu_freq_select);
  68. return 0;
  69. }
  70. return armada_39x_cpu_frequencies[cpu_freq_select];
  71. }
  72. enum { A390_CPU_TO_NBCLK, A390_CPU_TO_HCLK, A390_CPU_TO_DCLK };
  73. static const struct coreclk_ratio armada_39x_coreclk_ratios[] __initconst = {
  74. { .id = A390_CPU_TO_NBCLK, .name = "nbclk" },
  75. { .id = A390_CPU_TO_HCLK, .name = "hclk" },
  76. { .id = A390_CPU_TO_DCLK, .name = "dclk" },
  77. };
  78. static void __init armada_39x_get_clk_ratio(
  79. void __iomem *sar, int id, int *mult, int *div)
  80. {
  81. switch (id) {
  82. case A390_CPU_TO_NBCLK:
  83. *mult = 1;
  84. *div = 2;
  85. break;
  86. case A390_CPU_TO_HCLK:
  87. *mult = 1;
  88. *div = 4;
  89. break;
  90. case A390_CPU_TO_DCLK:
  91. *mult = 1;
  92. *div = 2;
  93. break;
  94. }
  95. }
  96. static u32 __init armada_39x_refclk_ratio(void __iomem *sar)
  97. {
  98. if (readl(sar + SARH) & SARH_A390_REFCLK_FREQ)
  99. return 40 * 1000 * 1000;
  100. else
  101. return 25 * 1000 * 1000;
  102. }
  103. static const struct coreclk_soc_desc armada_39x_coreclks = {
  104. .get_tclk_freq = armada_39x_get_tclk_freq,
  105. .get_cpu_freq = armada_39x_get_cpu_freq,
  106. .get_clk_ratio = armada_39x_get_clk_ratio,
  107. .get_refclk_freq = armada_39x_refclk_ratio,
  108. .ratios = armada_39x_coreclk_ratios,
  109. .num_ratios = ARRAY_SIZE(armada_39x_coreclk_ratios),
  110. };
  111. static void __init armada_39x_coreclk_init(struct device_node *np)
  112. {
  113. mvebu_coreclk_setup(np, &armada_39x_coreclks);
  114. }
  115. CLK_OF_DECLARE(armada_39x_core_clk, "marvell,armada-390-core-clock",
  116. armada_39x_coreclk_init);
  117. /*
  118. * Clock Gating Control
  119. */
  120. static const struct clk_gating_soc_desc armada_39x_gating_desc[] __initconst = {
  121. { "pex1", NULL, 5 },
  122. { "pex2", NULL, 6 },
  123. { "pex3", NULL, 7 },
  124. { "pex0", NULL, 8 },
  125. { "usb3h0", NULL, 9 },
  126. { "usb3h1", NULL, 10 },
  127. { "sata0", NULL, 15 },
  128. { "sdio", NULL, 17 },
  129. { "xor0", NULL, 22 },
  130. { "xor1", NULL, 28 },
  131. { }
  132. };
  133. static void __init armada_39x_clk_gating_init(struct device_node *np)
  134. {
  135. mvebu_clk_gating_setup(np, armada_39x_gating_desc);
  136. }
  137. CLK_OF_DECLARE(armada_39x_clk_gating, "marvell,armada-390-gating-clock",
  138. armada_39x_clk_gating_init);