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