1682e09ffSMasahiro Yamada /*
2682e09ffSMasahiro Yamada  * Copyright (C) 2016 Socionext Inc.
3682e09ffSMasahiro Yamada  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
4682e09ffSMasahiro Yamada  *
5682e09ffSMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
6682e09ffSMasahiro Yamada  */
7682e09ffSMasahiro Yamada 
8*7f8e7539SMasahiro Yamada #include <linux/bitfield.h>
9682e09ffSMasahiro Yamada #include <linux/bitops.h>
10d9a70368SMasahiro Yamada #include <linux/delay.h>
11f2ce50b2SMasahiro Yamada #include <linux/kernel.h>
12d9a70368SMasahiro Yamada #include <linux/errno.h>
13682e09ffSMasahiro Yamada #include <linux/io.h>
14682e09ffSMasahiro Yamada #include <linux/sizes.h>
15682e09ffSMasahiro Yamada 
16682e09ffSMasahiro Yamada #include "pll.h"
17682e09ffSMasahiro Yamada 
18682e09ffSMasahiro Yamada /* PLL type: SSC */
19682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_DK_MASK		GENMASK(14, 0)
20682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_EN		BIT(31)
21682e09ffSMasahiro Yamada #define SC_PLLCTRL2_NRSTDS		BIT(28)
22682e09ffSMasahiro Yamada #define SC_PLLCTRL2_SSC_JK_MASK		GENMASK(26, 0)
23bc647958SMasahiro Yamada #define SC_PLLCTRL3_REGI_MASK		GENMASK(19, 16)
24682e09ffSMasahiro Yamada 
25682e09ffSMasahiro Yamada /* PLL type: VPLL27 */
26682e09ffSMasahiro Yamada #define SC_VPLL27CTRL_WP		BIT(0)
27682e09ffSMasahiro Yamada #define SC_VPLL27CTRL3_K_LD		BIT(28)
28682e09ffSMasahiro Yamada 
29682e09ffSMasahiro Yamada /* PLL type: DSPLL */
30682e09ffSMasahiro Yamada #define SC_DSPLLCTRL2_K_LD		BIT(28)
31682e09ffSMasahiro Yamada 
32682e09ffSMasahiro Yamada int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
33682e09ffSMasahiro Yamada 			      unsigned int ssc_rate, unsigned int divn)
34682e09ffSMasahiro Yamada {
35682e09ffSMasahiro Yamada 	void __iomem *base;
36682e09ffSMasahiro Yamada 	u32 tmp;
37682e09ffSMasahiro Yamada 
38682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
39682e09ffSMasahiro Yamada 	if (!base)
40682e09ffSMasahiro Yamada 		return -ENOMEM;
41682e09ffSMasahiro Yamada 
42682e09ffSMasahiro Yamada 	if (freq != UNIPHIER_PLL_FREQ_DEFAULT) {
43682e09ffSMasahiro Yamada 		tmp = readl(base);	/* SSCPLLCTRL */
44682e09ffSMasahiro Yamada 		tmp &= ~SC_PLLCTRL_SSC_DK_MASK;
45*7f8e7539SMasahiro Yamada 		tmp |= FIELD_PREP(SC_PLLCTRL_SSC_DK_MASK,
46*7f8e7539SMasahiro Yamada 				  DIV_ROUND_CLOSEST(487UL * freq * ssc_rate,
47*7f8e7539SMasahiro Yamada 						    divn * 512));
48682e09ffSMasahiro Yamada 		writel(tmp, base);
49682e09ffSMasahiro Yamada 
50682e09ffSMasahiro Yamada 		tmp = readl(base + 4);
51682e09ffSMasahiro Yamada 		tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
52*7f8e7539SMasahiro Yamada 		tmp |= FIELD_PREP(SC_PLLCTRL2_SSC_JK_MASK,
53*7f8e7539SMasahiro Yamada 				  DIV_ROUND_CLOSEST(21431887UL * freq,
54*7f8e7539SMasahiro Yamada 						    divn * 512));
55c30c44e7SDai Okamura 		writel(tmp, base + 4);
56682e09ffSMasahiro Yamada 
57682e09ffSMasahiro Yamada 		udelay(50);
58682e09ffSMasahiro Yamada 	}
59682e09ffSMasahiro Yamada 
60682e09ffSMasahiro Yamada 	tmp = readl(base + 4);		/* SSCPLLCTRL2 */
61682e09ffSMasahiro Yamada 	tmp |= SC_PLLCTRL2_NRSTDS;
62682e09ffSMasahiro Yamada 	writel(tmp, base + 4);
63682e09ffSMasahiro Yamada 
64682e09ffSMasahiro Yamada 	iounmap(base);
65682e09ffSMasahiro Yamada 
66682e09ffSMasahiro Yamada 	return 0;
67682e09ffSMasahiro Yamada }
68682e09ffSMasahiro Yamada 
69682e09ffSMasahiro Yamada int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
70682e09ffSMasahiro Yamada {
71682e09ffSMasahiro Yamada 	void __iomem *base;
72682e09ffSMasahiro Yamada 	u32 tmp;
73682e09ffSMasahiro Yamada 
74682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
75682e09ffSMasahiro Yamada 	if (!base)
76682e09ffSMasahiro Yamada 		return -ENOMEM;
77682e09ffSMasahiro Yamada 
78682e09ffSMasahiro Yamada 	tmp = readl(base);	/* SSCPLLCTRL */
79682e09ffSMasahiro Yamada 	tmp |= SC_PLLCTRL_SSC_EN;
80682e09ffSMasahiro Yamada 	writel(tmp, base);
81682e09ffSMasahiro Yamada 
82682e09ffSMasahiro Yamada 	iounmap(base);
83682e09ffSMasahiro Yamada 
84682e09ffSMasahiro Yamada 	return 0;
85682e09ffSMasahiro Yamada }
86682e09ffSMasahiro Yamada 
87bc647958SMasahiro Yamada int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi)
88bc647958SMasahiro Yamada {
89bc647958SMasahiro Yamada 	void __iomem *base;
90bc647958SMasahiro Yamada 	u32 tmp;
91bc647958SMasahiro Yamada 
92bc647958SMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
93bc647958SMasahiro Yamada 	if (!base)
94bc647958SMasahiro Yamada 		return -ENOMEM;
95bc647958SMasahiro Yamada 
964013bbb1SDai Okamura 	tmp = readl(base + 8);	/* SSCPLLCTRL3 */
97bc647958SMasahiro Yamada 	tmp &= ~SC_PLLCTRL3_REGI_MASK;
98*7f8e7539SMasahiro Yamada 	tmp |= FIELD_PREP(SC_PLLCTRL3_REGI_MASK, regi);
99bc647958SMasahiro Yamada 	writel(tmp, base + 8);
100bc647958SMasahiro Yamada 
101bc647958SMasahiro Yamada 	iounmap(base);
102bc647958SMasahiro Yamada 
103bc647958SMasahiro Yamada 	return 0;
104bc647958SMasahiro Yamada }
105bc647958SMasahiro Yamada 
106682e09ffSMasahiro Yamada int uniphier_ld20_vpll27_init(unsigned long reg_base)
107682e09ffSMasahiro Yamada {
108682e09ffSMasahiro Yamada 	void __iomem *base;
109682e09ffSMasahiro Yamada 	u32 tmp;
110682e09ffSMasahiro Yamada 
111682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
112682e09ffSMasahiro Yamada 	if (!base)
113682e09ffSMasahiro Yamada 		return -ENOMEM;
114682e09ffSMasahiro Yamada 
115682e09ffSMasahiro Yamada 	tmp = readl(base);		/* VPLL27CTRL */
116682e09ffSMasahiro Yamada 	tmp |= SC_VPLL27CTRL_WP;	/* write protect off */
117682e09ffSMasahiro Yamada 	writel(tmp, base);
118682e09ffSMasahiro Yamada 
119682e09ffSMasahiro Yamada 	tmp = readl(base + 8);		/* VPLL27CTRL3 */
120682e09ffSMasahiro Yamada 	tmp |= SC_VPLL27CTRL3_K_LD;
121682e09ffSMasahiro Yamada 	writel(tmp, base + 8);
122682e09ffSMasahiro Yamada 
123682e09ffSMasahiro Yamada 	tmp = readl(base);		/* VPLL27CTRL */
124682e09ffSMasahiro Yamada 	tmp &= ~SC_VPLL27CTRL_WP;	/* write protect on */
125682e09ffSMasahiro Yamada 	writel(tmp, base);
126682e09ffSMasahiro Yamada 
127682e09ffSMasahiro Yamada 	iounmap(base);
128682e09ffSMasahiro Yamada 
129682e09ffSMasahiro Yamada 	return 0;
130682e09ffSMasahiro Yamada }
131682e09ffSMasahiro Yamada 
132682e09ffSMasahiro Yamada int uniphier_ld20_dspll_init(unsigned long reg_base)
133682e09ffSMasahiro Yamada {
134682e09ffSMasahiro Yamada 	void __iomem *base;
135682e09ffSMasahiro Yamada 	u32 tmp;
136682e09ffSMasahiro Yamada 
137682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
138682e09ffSMasahiro Yamada 	if (!base)
139682e09ffSMasahiro Yamada 		return -ENOMEM;
140682e09ffSMasahiro Yamada 
1414013bbb1SDai Okamura 	tmp = readl(base + 4);		/* DSPLLCTRL2 */
142682e09ffSMasahiro Yamada 	tmp |= SC_DSPLLCTRL2_K_LD;
1434013bbb1SDai Okamura 	writel(tmp, base + 4);
144682e09ffSMasahiro Yamada 
145682e09ffSMasahiro Yamada 	iounmap(base);
146682e09ffSMasahiro Yamada 
147682e09ffSMasahiro Yamada 	return 0;
148682e09ffSMasahiro Yamada }
149