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