]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-uniphier/clk/pll-base-ld20.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / arch / arm / mach-uniphier / clk / pll-base-ld20.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Socionext Inc.
4  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5  */
6
7 #include <linux/bitfield.h>
8 #include <linux/bitops.h>
9 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/io.h>
13 #include <linux/sizes.h>
14
15 #include "pll.h"
16
17 /* PLL type: SSC */
18 #define SC_PLLCTRL_SSC_DK_MASK          GENMASK(14, 0)
19 #define SC_PLLCTRL_SSC_EN               BIT(31)
20 #define SC_PLLCTRL2_NRSTDS              BIT(28)
21 #define SC_PLLCTRL2_SSC_JK_MASK         GENMASK(26, 0)
22 #define SC_PLLCTRL3_REGI_MASK           GENMASK(19, 16)
23
24 /* PLL type: VPLL27 */
25 #define SC_VPLL27CTRL_WP                BIT(0)
26 #define SC_VPLL27CTRL3_K_LD             BIT(28)
27
28 /* PLL type: DSPLL */
29 #define SC_DSPLLCTRL2_K_LD              BIT(28)
30
31 int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq,
32                               unsigned int ssc_rate, unsigned int divn)
33 {
34         void __iomem *base;
35         u32 tmp;
36
37         base = ioremap(reg_base, SZ_16);
38         if (!base)
39                 return -ENOMEM;
40
41         if (freq != UNIPHIER_PLL_FREQ_DEFAULT) {
42                 tmp = readl(base);      /* SSCPLLCTRL */
43                 tmp &= ~SC_PLLCTRL_SSC_DK_MASK;
44                 tmp |= FIELD_PREP(SC_PLLCTRL_SSC_DK_MASK,
45                                   DIV_ROUND_CLOSEST(487UL * freq * ssc_rate,
46                                                     divn * 512));
47                 writel(tmp, base);
48
49                 tmp = readl(base + 4);
50                 tmp &= ~SC_PLLCTRL2_SSC_JK_MASK;
51                 tmp |= FIELD_PREP(SC_PLLCTRL2_SSC_JK_MASK,
52                                   DIV_ROUND_CLOSEST(21431887UL * freq,
53                                                     divn * 512));
54                 writel(tmp, base + 4);
55
56                 udelay(50);
57         }
58
59         tmp = readl(base + 4);          /* SSCPLLCTRL2 */
60         tmp |= SC_PLLCTRL2_NRSTDS;
61         writel(tmp, base + 4);
62
63         iounmap(base);
64
65         return 0;
66 }
67
68 int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base)
69 {
70         void __iomem *base;
71         u32 tmp;
72
73         base = ioremap(reg_base, SZ_16);
74         if (!base)
75                 return -ENOMEM;
76
77         tmp = readl(base);      /* SSCPLLCTRL */
78         tmp |= SC_PLLCTRL_SSC_EN;
79         writel(tmp, base);
80
81         iounmap(base);
82
83         return 0;
84 }
85
86 int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi)
87 {
88         void __iomem *base;
89         u32 tmp;
90
91         base = ioremap(reg_base, SZ_16);
92         if (!base)
93                 return -ENOMEM;
94
95         tmp = readl(base + 8);  /* SSCPLLCTRL3 */
96         tmp &= ~SC_PLLCTRL3_REGI_MASK;
97         tmp |= FIELD_PREP(SC_PLLCTRL3_REGI_MASK, regi);
98         writel(tmp, base + 8);
99
100         iounmap(base);
101
102         return 0;
103 }
104
105 int uniphier_ld20_vpll27_init(unsigned long reg_base)
106 {
107         void __iomem *base;
108         u32 tmp;
109
110         base = ioremap(reg_base, SZ_16);
111         if (!base)
112                 return -ENOMEM;
113
114         tmp = readl(base);              /* VPLL27CTRL */
115         tmp |= SC_VPLL27CTRL_WP;        /* write protect off */
116         writel(tmp, base);
117
118         tmp = readl(base + 8);          /* VPLL27CTRL3 */
119         tmp |= SC_VPLL27CTRL3_K_LD;
120         writel(tmp, base + 8);
121
122         tmp = readl(base);              /* VPLL27CTRL */
123         tmp &= ~SC_VPLL27CTRL_WP;       /* write protect on */
124         writel(tmp, base);
125
126         iounmap(base);
127
128         return 0;
129 }
130
131 int uniphier_ld20_dspll_init(unsigned long reg_base)
132 {
133         void __iomem *base;
134         u32 tmp;
135
136         base = ioremap(reg_base, SZ_16);
137         if (!base)
138                 return -ENOMEM;
139
140         tmp = readl(base + 4);          /* DSPLLCTRL2 */
141         tmp |= SC_DSPLLCTRL2_K_LD;
142         writel(tmp, base + 4);
143
144         iounmap(base);
145
146         return 0;
147 }