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