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 8 #include <linux/bitops.h> 9 #include <linux/delay.h> 10 #include <linux/errno.h> 11 #include <linux/io.h> 12 #include <linux/sizes.h> 13 14 #include "pll.h" 15 16 /* PLL type: SSC */ 17 #define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0) 18 #define SC_PLLCTRL_SSC_EN BIT(31) 19 #define SC_PLLCTRL2_NRSTDS BIT(28) 20 #define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0) 21 22 /* PLL type: VPLL27 */ 23 #define SC_VPLL27CTRL_WP BIT(0) 24 #define SC_VPLL27CTRL3_K_LD BIT(28) 25 26 /* PLL type: DSPLL */ 27 #define SC_DSPLLCTRL2_K_LD BIT(28) 28 29 int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq, 30 unsigned int ssc_rate, unsigned int divn) 31 { 32 void __iomem *base; 33 u32 tmp; 34 35 base = ioremap(reg_base, SZ_16); 36 if (!base) 37 return -ENOMEM; 38 39 if (freq != UNIPHIER_PLL_FREQ_DEFAULT) { 40 tmp = readl(base); /* SSCPLLCTRL */ 41 tmp &= ~SC_PLLCTRL_SSC_DK_MASK; 42 tmp |= (487 * freq * ssc_rate / divn / 512) & 43 SC_PLLCTRL_SSC_DK_MASK; 44 writel(tmp, base); 45 46 tmp = readl(base + 4); 47 tmp &= ~SC_PLLCTRL2_SSC_JK_MASK; 48 tmp |= (41859 * freq / divn) & SC_PLLCTRL2_SSC_JK_MASK; 49 50 udelay(50); 51 } 52 53 tmp = readl(base + 4); /* SSCPLLCTRL2 */ 54 tmp |= SC_PLLCTRL2_NRSTDS; 55 writel(tmp, base + 4); 56 57 iounmap(base); 58 59 return 0; 60 } 61 62 int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base) 63 { 64 void __iomem *base; 65 u32 tmp; 66 67 base = ioremap(reg_base, SZ_16); 68 if (!base) 69 return -ENOMEM; 70 71 tmp = readl(base); /* SSCPLLCTRL */ 72 tmp |= SC_PLLCTRL_SSC_EN; 73 writel(tmp, base); 74 75 iounmap(base); 76 77 return 0; 78 } 79 80 int uniphier_ld20_vpll27_init(unsigned long reg_base) 81 { 82 void __iomem *base; 83 u32 tmp; 84 85 base = ioremap(reg_base, SZ_16); 86 if (!base) 87 return -ENOMEM; 88 89 tmp = readl(base); /* VPLL27CTRL */ 90 tmp |= SC_VPLL27CTRL_WP; /* write protect off */ 91 writel(tmp, base); 92 93 tmp = readl(base + 8); /* VPLL27CTRL3 */ 94 tmp |= SC_VPLL27CTRL3_K_LD; 95 writel(tmp, base + 8); 96 97 tmp = readl(base); /* VPLL27CTRL */ 98 tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */ 99 writel(tmp, base); 100 101 iounmap(base); 102 103 return 0; 104 } 105 106 int uniphier_ld20_dspll_init(unsigned long reg_base) 107 { 108 void __iomem *base; 109 u32 tmp; 110 111 base = ioremap(reg_base, SZ_16); 112 if (!base) 113 return -ENOMEM; 114 115 tmp = readl(base + 8); /* DSPLLCTRL2 */ 116 tmp |= SC_DSPLLCTRL2_K_LD; 117 writel(tmp, base + 8); 118 119 iounmap(base); 120 121 return 0; 122 } 123