clk_owl.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Common clock driver for Actions Semi SoCs.
  4. *
  5. * Copyright (C) 2015 Actions Semi Co., Ltd.
  6. * Copyright (C) 2018 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
  7. */
  8. #include <common.h>
  9. #include <dm.h>
  10. #include "clk_owl.h"
  11. #include <asm/io.h>
  12. #if defined(CONFIG_MACH_S900)
  13. #include <asm/arch-owl/regs_s900.h>
  14. #include <dt-bindings/clock/actions,s900-cmu.h>
  15. #elif defined(CONFIG_MACH_S700)
  16. #include <asm/arch-owl/regs_s700.h>
  17. #include <dt-bindings/clock/actions,s700-cmu.h>
  18. #endif
  19. #include <linux/bitops.h>
  20. #include <linux/delay.h>
  21. void owl_clk_init(struct owl_clk_priv *priv)
  22. {
  23. u32 bus_clk = 0, core_pll, dev_pll;
  24. #if defined(CONFIG_MACH_S900)
  25. /* Enable ASSIST_PLL */
  26. setbits_le32(priv->base + CMU_ASSISTPLL, BIT(0));
  27. udelay(PLL_STABILITY_WAIT_US);
  28. #endif
  29. /* Source HOSC to DEV_CLK */
  30. clrbits_le32(priv->base + CMU_DEVPLL, CMU_DEVPLL_CLK);
  31. /* Configure BUS_CLK */
  32. bus_clk |= (CMU_PDBGDIV_DIV | CMU_PERDIV_DIV | CMU_NOCDIV_DIV |
  33. CMU_DMMCLK_SRC | CMU_APBCLK_DIV | CMU_AHBCLK_DIV |
  34. CMU_NOCCLK_SRC | CMU_CORECLK_HOSC);
  35. writel(bus_clk, priv->base + CMU_BUSCLK);
  36. udelay(PLL_STABILITY_WAIT_US);
  37. /* Configure CORE_PLL */
  38. core_pll = readl(priv->base + CMU_COREPLL);
  39. core_pll |= (CMU_COREPLL_EN | CMU_COREPLL_HOSC_EN | CMU_COREPLL_OUT);
  40. writel(core_pll, priv->base + CMU_COREPLL);
  41. udelay(PLL_STABILITY_WAIT_US);
  42. /* Configure DEV_PLL */
  43. dev_pll = readl(priv->base + CMU_DEVPLL);
  44. dev_pll |= (CMU_DEVPLL_EN | CMU_DEVPLL_OUT);
  45. writel(dev_pll, priv->base + CMU_DEVPLL);
  46. udelay(PLL_STABILITY_WAIT_US);
  47. /* Source CORE_PLL for CORE_CLK */
  48. clrsetbits_le32(priv->base + CMU_BUSCLK, CMU_CORECLK_MASK,
  49. CMU_CORECLK_CPLL);
  50. /* Source DEV_PLL for DEV_CLK */
  51. setbits_le32(priv->base + CMU_DEVPLL, CMU_DEVPLL_CLK);
  52. udelay(PLL_STABILITY_WAIT_US);
  53. }
  54. int owl_clk_enable(struct clk *clk)
  55. {
  56. struct owl_clk_priv *priv = dev_get_priv(clk->dev);
  57. enum owl_soc model = dev_get_driver_data(clk->dev);
  58. switch (clk->id) {
  59. case CLK_UART5:
  60. if (model != S900)
  61. return -EINVAL;
  62. /* Source HOSC for UART5 interface */
  63. clrbits_le32(priv->base + CMU_UART5CLK, CMU_UARTCLK_SRC_DEVPLL);
  64. /* Enable UART5 interface clock */
  65. setbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART5);
  66. break;
  67. case CLK_UART3:
  68. if (model != S700)
  69. return -EINVAL;
  70. /* Source HOSC for UART3 interface */
  71. clrbits_le32(priv->base + CMU_UART3CLK, CMU_UARTCLK_SRC_DEVPLL);
  72. /* Enable UART3 interface clock */
  73. setbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART3);
  74. break;
  75. case CLK_RMII_REF:
  76. case CLK_ETHERNET:
  77. setbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_ETH);
  78. setbits_le32(priv->base + CMU_ETHERNETPLL, 5);
  79. break;
  80. default:
  81. return -EINVAL;
  82. }
  83. return 0;
  84. }
  85. int owl_clk_disable(struct clk *clk)
  86. {
  87. struct owl_clk_priv *priv = dev_get_priv(clk->dev);
  88. enum owl_soc model = dev_get_driver_data(clk->dev);
  89. switch (clk->id) {
  90. case CLK_UART5:
  91. if (model != S900)
  92. return -EINVAL;
  93. /* Disable UART5 interface clock */
  94. clrbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART5);
  95. break;
  96. case CLK_UART3:
  97. if (model != S700)
  98. return -EINVAL;
  99. /* Disable UART3 interface clock */
  100. clrbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_UART3);
  101. break;
  102. case CLK_RMII_REF:
  103. case CLK_ETHERNET:
  104. clrbits_le32(priv->base + CMU_DEVCLKEN1, CMU_DEVCLKEN1_ETH);
  105. break;
  106. default:
  107. return -EINVAL;
  108. }
  109. return 0;
  110. }
  111. static int owl_clk_probe(struct udevice *dev)
  112. {
  113. struct owl_clk_priv *priv = dev_get_priv(dev);
  114. priv->base = dev_read_addr(dev);
  115. if (priv->base == FDT_ADDR_T_NONE)
  116. return -EINVAL;
  117. /* setup necessary clocks */
  118. owl_clk_init(priv);
  119. return 0;
  120. }
  121. static const struct clk_ops owl_clk_ops = {
  122. .enable = owl_clk_enable,
  123. .disable = owl_clk_disable,
  124. };
  125. static const struct udevice_id owl_clk_ids[] = {
  126. #if defined(CONFIG_MACH_S900)
  127. { .compatible = "actions,s900-cmu", .data = S900 },
  128. #elif defined(CONFIG_MACH_S700)
  129. { .compatible = "actions,s700-cmu", .data = S700 },
  130. #endif
  131. { }
  132. };
  133. U_BOOT_DRIVER(clk_owl) = {
  134. .name = "clk_owl",
  135. .id = UCLASS_CLK,
  136. .of_match = owl_clk_ids,
  137. .ops = &owl_clk_ops,
  138. .priv_auto_alloc_size = sizeof(struct owl_clk_priv),
  139. .probe = owl_clk_probe,
  140. };