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 
8682e09ffSMasahiro Yamada #include <linux/bitops.h>
9d9a70368SMasahiro Yamada #include <linux/delay.h>
10d9a70368SMasahiro Yamada #include <linux/errno.h>
11682e09ffSMasahiro Yamada #include <linux/io.h>
12682e09ffSMasahiro Yamada #include <linux/sizes.h>
13682e09ffSMasahiro Yamada 
14682e09ffSMasahiro Yamada #include "pll.h"
15682e09ffSMasahiro Yamada 
16682e09ffSMasahiro Yamada /* PLL type: SSC */
17682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_DK_MASK		GENMASK(14, 0)
18682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_EN		BIT(31)
19682e09ffSMasahiro Yamada #define SC_PLLCTRL2_NRSTDS		BIT(28)
20682e09ffSMasahiro Yamada #define SC_PLLCTRL2_SSC_JK_MASK		GENMASK(26, 0)
21bc647958SMasahiro Yamada #define SC_PLLCTRL3_REGI_SHIFT		16
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 
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;
44682e09ffSMasahiro Yamada 		tmp |= (487 * freq * ssc_rate / divn / 512) &
45682e09ffSMasahiro Yamada 							SC_PLLCTRL_SSC_DK_MASK;
46682e09ffSMasahiro Yamada 		writel(tmp, base);
47682e09ffSMasahiro Yamada 
48682e09ffSMasahiro Yamada 		tmp = readl(base + 4);
49682e09ffSMasahiro Yamada 		tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
50682e09ffSMasahiro Yamada 		tmp |= (41859 * freq / divn) & SC_PLLCTRL2_SSC_JK_MASK;
51*c30c44e7SDai Okamura 		writel(tmp, base + 4);
52682e09ffSMasahiro Yamada 
53682e09ffSMasahiro Yamada 		udelay(50);
54682e09ffSMasahiro Yamada 	}
55682e09ffSMasahiro Yamada 
56682e09ffSMasahiro Yamada 	tmp = readl(base + 4);		/* SSCPLLCTRL2 */
57682e09ffSMasahiro Yamada 	tmp |= SC_PLLCTRL2_NRSTDS;
58682e09ffSMasahiro Yamada 	writel(tmp, base + 4);
59682e09ffSMasahiro Yamada 
60682e09ffSMasahiro Yamada 	iounmap(base);
61682e09ffSMasahiro Yamada 
62682e09ffSMasahiro Yamada 	return 0;
63682e09ffSMasahiro Yamada }
64682e09ffSMasahiro Yamada 
65682e09ffSMasahiro Yamada int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
66682e09ffSMasahiro Yamada {
67682e09ffSMasahiro Yamada 	void __iomem *base;
68682e09ffSMasahiro Yamada 	u32 tmp;
69682e09ffSMasahiro Yamada 
70682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
71682e09ffSMasahiro Yamada 	if (!base)
72682e09ffSMasahiro Yamada 		return -ENOMEM;
73682e09ffSMasahiro Yamada 
74682e09ffSMasahiro Yamada 	tmp = readl(base);	/* SSCPLLCTRL */
75682e09ffSMasahiro Yamada 	tmp |= SC_PLLCTRL_SSC_EN;
76682e09ffSMasahiro Yamada 	writel(tmp, base);
77682e09ffSMasahiro Yamada 
78682e09ffSMasahiro Yamada 	iounmap(base);
79682e09ffSMasahiro Yamada 
80682e09ffSMasahiro Yamada 	return 0;
81682e09ffSMasahiro Yamada }
82682e09ffSMasahiro Yamada 
83bc647958SMasahiro Yamada int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi)
84bc647958SMasahiro Yamada {
85bc647958SMasahiro Yamada 	void __iomem *base;
86bc647958SMasahiro Yamada 	u32 tmp;
87bc647958SMasahiro Yamada 
88bc647958SMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
89bc647958SMasahiro Yamada 	if (!base)
90bc647958SMasahiro Yamada 		return -ENOMEM;
91bc647958SMasahiro Yamada 
924013bbb1SDai Okamura 	tmp = readl(base + 8);	/* SSCPLLCTRL3 */
93bc647958SMasahiro Yamada 	tmp &= ~SC_PLLCTRL3_REGI_MASK;
94bc647958SMasahiro Yamada 	tmp |= regi << SC_PLLCTRL3_REGI_SHIFT;
95bc647958SMasahiro Yamada 	writel(tmp, base + 8);
96bc647958SMasahiro Yamada 
97bc647958SMasahiro Yamada 	iounmap(base);
98bc647958SMasahiro Yamada 
99bc647958SMasahiro Yamada 	return 0;
100bc647958SMasahiro Yamada }
101bc647958SMasahiro Yamada 
102682e09ffSMasahiro Yamada int uniphier_ld20_vpll27_init(unsigned long reg_base)
103682e09ffSMasahiro Yamada {
104682e09ffSMasahiro Yamada 	void __iomem *base;
105682e09ffSMasahiro Yamada 	u32 tmp;
106682e09ffSMasahiro Yamada 
107682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
108682e09ffSMasahiro Yamada 	if (!base)
109682e09ffSMasahiro Yamada 		return -ENOMEM;
110682e09ffSMasahiro Yamada 
111682e09ffSMasahiro Yamada 	tmp = readl(base);		/* VPLL27CTRL */
112682e09ffSMasahiro Yamada 	tmp |= SC_VPLL27CTRL_WP;	/* write protect off */
113682e09ffSMasahiro Yamada 	writel(tmp, base);
114682e09ffSMasahiro Yamada 
115682e09ffSMasahiro Yamada 	tmp = readl(base + 8);		/* VPLL27CTRL3 */
116682e09ffSMasahiro Yamada 	tmp |= SC_VPLL27CTRL3_K_LD;
117682e09ffSMasahiro Yamada 	writel(tmp, base + 8);
118682e09ffSMasahiro Yamada 
119682e09ffSMasahiro Yamada 	tmp = readl(base);		/* VPLL27CTRL */
120682e09ffSMasahiro Yamada 	tmp &= ~SC_VPLL27CTRL_WP;	/* write protect on */
121682e09ffSMasahiro Yamada 	writel(tmp, base);
122682e09ffSMasahiro Yamada 
123682e09ffSMasahiro Yamada 	iounmap(base);
124682e09ffSMasahiro Yamada 
125682e09ffSMasahiro Yamada 	return 0;
126682e09ffSMasahiro Yamada }
127682e09ffSMasahiro Yamada 
128682e09ffSMasahiro Yamada int uniphier_ld20_dspll_init(unsigned long reg_base)
129682e09ffSMasahiro Yamada {
130682e09ffSMasahiro Yamada 	void __iomem *base;
131682e09ffSMasahiro Yamada 	u32 tmp;
132682e09ffSMasahiro Yamada 
133682e09ffSMasahiro Yamada 	base = ioremap(reg_base, SZ_16);
134682e09ffSMasahiro Yamada 	if (!base)
135682e09ffSMasahiro Yamada 		return -ENOMEM;
136682e09ffSMasahiro Yamada 
1374013bbb1SDai Okamura 	tmp = readl(base + 4);		/* DSPLLCTRL2 */
138682e09ffSMasahiro Yamada 	tmp |= SC_DSPLLCTRL2_K_LD;
1394013bbb1SDai Okamura 	writel(tmp, base + 4);
140682e09ffSMasahiro Yamada 
141682e09ffSMasahiro Yamada 	iounmap(base);
142682e09ffSMasahiro Yamada 
143682e09ffSMasahiro Yamada 	return 0;
144682e09ffSMasahiro Yamada }
145