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