fu740-prci.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018-2021 SiFive, Inc.
  4. * Wesley Terpstra
  5. * Paul Walmsley
  6. * Zong Li
  7. * Pragnesh Patel
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <dt-bindings/clock/sifive-fu740-prci.h>
  19. #include "sifive-prci.h"
  20. #include <asm/io.h>
  21. int sifive_prci_fu740_pcieauxclk_enable(struct __prci_clock *pc, bool enable)
  22. {
  23. struct __prci_wrpll_data *pwd = pc->pwd;
  24. struct __prci_data *pd = pc->pd;
  25. u32 v;
  26. if (pwd->cfg1_offs != PRCI_PCIEAUXCFG1_OFFSET)
  27. return -EINVAL;
  28. v = readl(pd->va + pwd->cfg1_offs);
  29. v = enable ? (v | PRCI_PCIEAUXCFG1_MASK) : (v & ~PRCI_PCIEAUXCFG1_MASK);
  30. writel(v, pd->va + pwd->cfg1_offs);
  31. return 0;
  32. }
  33. /* PRCI integration data for each WRPLL instance */
  34. static struct __prci_wrpll_data __prci_corepll_data = {
  35. .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
  36. .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
  37. .enable_bypass = sifive_prci_coreclksel_use_hfclk,
  38. .disable_bypass = sifive_prci_coreclksel_use_final_corepll,
  39. };
  40. static struct __prci_wrpll_data __prci_ddrpll_data = {
  41. .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
  42. .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
  43. .release_reset = sifive_prci_ddr_release_reset,
  44. };
  45. static struct __prci_wrpll_data __prci_gemgxlpll_data = {
  46. .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
  47. .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
  48. .release_reset = sifive_prci_ethernet_release_reset,
  49. };
  50. static struct __prci_wrpll_data __prci_dvfscorepll_data = {
  51. .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET,
  52. .cfg1_offs = PRCI_DVFSCOREPLLCFG1_OFFSET,
  53. .enable_bypass = sifive_prci_corepllsel_use_corepll,
  54. .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll,
  55. };
  56. static struct __prci_wrpll_data __prci_hfpclkpll_data = {
  57. .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET,
  58. .cfg1_offs = PRCI_HFPCLKPLLCFG1_OFFSET,
  59. .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk,
  60. .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll,
  61. };
  62. static struct __prci_wrpll_data __prci_cltxpll_data = {
  63. .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET,
  64. .cfg1_offs = PRCI_CLTXPLLCFG1_OFFSET,
  65. .release_reset = sifive_prci_cltx_release_reset,
  66. };
  67. static struct __prci_wrpll_data __prci_pcieaux_data = {
  68. .cfg1_offs = PRCI_PCIEAUXCFG1_OFFSET,
  69. };
  70. /* Linux clock framework integration */
  71. static const struct __prci_clock_ops sifive_fu740_prci_wrpll_clk_ops = {
  72. .set_rate = sifive_prci_wrpll_set_rate,
  73. .round_rate = sifive_prci_wrpll_round_rate,
  74. .recalc_rate = sifive_prci_wrpll_recalc_rate,
  75. .enable_clk = sifive_prci_clock_enable,
  76. };
  77. static const struct __prci_clock_ops sifive_fu740_prci_tlclksel_clk_ops = {
  78. .recalc_rate = sifive_prci_tlclksel_recalc_rate,
  79. };
  80. static const struct __prci_clock_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = {
  81. .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate,
  82. };
  83. static const struct __prci_clock_ops sifive_fu740_prci_pcieaux_clk_ops = {
  84. .enable_clk = sifive_prci_fu740_pcieauxclk_enable,
  85. };
  86. /* List of clock controls provided by the PRCI */
  87. struct __prci_clock __prci_init_clocks_fu740[] = {
  88. [PRCI_CLK_COREPLL] = {
  89. .name = "corepll",
  90. .parent_name = "hfclk",
  91. .ops = &sifive_fu740_prci_wrpll_clk_ops,
  92. .pwd = &__prci_corepll_data,
  93. },
  94. [PRCI_CLK_DDRPLL] = {
  95. .name = "ddrpll",
  96. .parent_name = "hfclk",
  97. .ops = &sifive_fu740_prci_wrpll_clk_ops,
  98. .pwd = &__prci_ddrpll_data,
  99. },
  100. [PRCI_CLK_GEMGXLPLL] = {
  101. .name = "gemgxlpll",
  102. .parent_name = "hfclk",
  103. .ops = &sifive_fu740_prci_wrpll_clk_ops,
  104. .pwd = &__prci_gemgxlpll_data,
  105. },
  106. [PRCI_CLK_DVFSCOREPLL] = {
  107. .name = "dvfscorepll",
  108. .parent_name = "hfclk",
  109. .ops = &sifive_fu740_prci_wrpll_clk_ops,
  110. .pwd = &__prci_dvfscorepll_data,
  111. },
  112. [PRCI_CLK_HFPCLKPLL] = {
  113. .name = "hfpclkpll",
  114. .parent_name = "hfclk",
  115. .ops = &sifive_fu740_prci_wrpll_clk_ops,
  116. .pwd = &__prci_hfpclkpll_data,
  117. },
  118. [PRCI_CLK_CLTXPLL] = {
  119. .name = "cltxpll",
  120. .parent_name = "hfclk",
  121. .ops = &sifive_fu740_prci_wrpll_clk_ops,
  122. .pwd = &__prci_cltxpll_data,
  123. },
  124. [PRCI_CLK_TLCLK] = {
  125. .name = "tlclk",
  126. .parent_name = "corepll",
  127. .ops = &sifive_fu740_prci_tlclksel_clk_ops,
  128. },
  129. [PRCI_CLK_PCLK] = {
  130. .name = "pclk",
  131. .parent_name = "hfpclkpll",
  132. .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops,
  133. },
  134. [PRCI_CLK_PCIEAUX] {
  135. .name = "pcieaux",
  136. .parent_name = "",
  137. .ops = &sifive_fu740_prci_pcieaux_clk_ops,
  138. .pwd = &__prci_pcieaux_data,
  139. }
  140. };