pll-base-ld20.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright (C) 2016 Socionext Inc.
  3. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <linux/bitops.h>
  9. #include <linux/io.h>
  10. #include <linux/sizes.h>
  11. #include "pll.h"
  12. /* PLL type: SSC */
  13. #define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0)
  14. #define SC_PLLCTRL_SSC_EN BIT(31)
  15. #define SC_PLLCTRL2_NRSTDS BIT(28)
  16. #define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0)
  17. /* PLL type: VPLL27 */
  18. #define SC_VPLL27CTRL_WP BIT(0)
  19. #define SC_VPLL27CTRL3_K_LD BIT(28)
  20. /* PLL type: DSPLL */
  21. #define SC_DSPLLCTRL2_K_LD BIT(28)
  22. int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
  23. unsigned int ssc_rate, unsigned int divn)
  24. {
  25. void __iomem *base;
  26. u32 tmp;
  27. base = ioremap(reg_base, SZ_16);
  28. if (!base)
  29. return -ENOMEM;
  30. if (freq != UNIPHIER_PLL_FREQ_DEFAULT) {
  31. tmp = readl(base); /* SSCPLLCTRL */
  32. tmp &= ~SC_PLLCTRL_SSC_DK_MASK;
  33. tmp |= (487 * freq * ssc_rate / divn / 512) &
  34. SC_PLLCTRL_SSC_DK_MASK;
  35. writel(tmp, base);
  36. tmp = readl(base + 4);
  37. tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
  38. tmp |= (41859 * freq / divn) & SC_PLLCTRL2_SSC_JK_MASK;
  39. udelay(50);
  40. }
  41. tmp = readl(base + 4); /* SSCPLLCTRL2 */
  42. tmp |= SC_PLLCTRL2_NRSTDS;
  43. writel(tmp, base + 4);
  44. iounmap(base);
  45. return 0;
  46. }
  47. int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
  48. {
  49. void __iomem *base;
  50. u32 tmp;
  51. base = ioremap(reg_base, SZ_16);
  52. if (!base)
  53. return -ENOMEM;
  54. mdelay(1);
  55. tmp = readl(base); /* SSCPLLCTRL */
  56. tmp |= SC_PLLCTRL_SSC_EN;
  57. writel(tmp, base);
  58. iounmap(base);
  59. return 0;
  60. }
  61. int uniphier_ld20_vpll27_init(unsigned long reg_base)
  62. {
  63. void __iomem *base;
  64. u32 tmp;
  65. base = ioremap(reg_base, SZ_16);
  66. if (!base)
  67. return -ENOMEM;
  68. tmp = readl(base); /* VPLL27CTRL */
  69. tmp |= SC_VPLL27CTRL_WP; /* write protect off */
  70. writel(tmp, base);
  71. tmp = readl(base + 8); /* VPLL27CTRL3 */
  72. tmp |= SC_VPLL27CTRL3_K_LD;
  73. writel(tmp, base + 8);
  74. tmp = readl(base); /* VPLL27CTRL */
  75. tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */
  76. writel(tmp, base);
  77. iounmap(base);
  78. return 0;
  79. }
  80. int uniphier_ld20_dspll_init(unsigned long reg_base)
  81. {
  82. void __iomem *base;
  83. u32 tmp;
  84. base = ioremap(reg_base, SZ_16);
  85. if (!base)
  86. return -ENOMEM;
  87. tmp = readl(base + 8); /* DSPLLCTRL2 */
  88. tmp |= SC_DSPLLCTRL2_K_LD;
  89. writel(tmp, base + 8);
  90. iounmap(base);
  91. return 0;
  92. }