GNU Linux-libre 5.10.153-gnu1
[releases.git] / drivers / clk / socfpga / clk-pll-s10.c
1 // SPDX-License-Identifier:     GPL-2.0
2 /*
3  * Copyright (C) 2017, Intel Corporation
4  */
5 #include <linux/slab.h>
6 #include <linux/clk-provider.h>
7 #include <linux/io.h>
8
9 #include "stratix10-clk.h"
10 #include "clk.h"
11
12 /* Clock Manager offsets */
13 #define CLK_MGR_PLL_CLK_SRC_SHIFT       16
14 #define CLK_MGR_PLL_CLK_SRC_MASK        0x3
15
16 /* PLL Clock enable bits */
17 #define SOCFPGA_PLL_POWER               0
18 #define SOCFPGA_PLL_RESET_MASK          0x2
19 #define SOCFPGA_PLL_REFDIV_MASK         0x00003F00
20 #define SOCFPGA_PLL_REFDIV_SHIFT        8
21 #define SOCFPGA_PLL_AREFDIV_MASK        0x00000F00
22 #define SOCFPGA_PLL_DREFDIV_MASK        0x00003000
23 #define SOCFPGA_PLL_DREFDIV_SHIFT       12
24 #define SOCFPGA_PLL_MDIV_MASK           0xFF000000
25 #define SOCFPGA_PLL_MDIV_SHIFT          24
26 #define SOCFPGA_AGILEX_PLL_MDIV_MASK    0x000003FF
27 #define SWCTRLBTCLKSEL_MASK             0x200
28 #define SWCTRLBTCLKSEL_SHIFT            9
29
30 #define SOCFPGA_BOOT_CLK                "boot_clk"
31
32 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
33
34 static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw *hwclk,
35                                                 unsigned long parent_rate)
36 {
37         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
38         unsigned long arefdiv, reg, mdiv;
39         unsigned long long vco_freq;
40
41         /* read VCO1 reg for numerator and denominator */
42         reg = readl(socfpgaclk->hw.reg);
43         arefdiv = (reg & SOCFPGA_PLL_AREFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
44
45         vco_freq = (unsigned long long)parent_rate / arefdiv;
46
47         /* Read mdiv and fdiv from the fdbck register */
48         reg = readl(socfpgaclk->hw.reg + 0x24);
49         mdiv = reg & SOCFPGA_AGILEX_PLL_MDIV_MASK;
50
51         vco_freq = (unsigned long long)vco_freq * mdiv;
52         return (unsigned long)vco_freq;
53 }
54
55 static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
56                                          unsigned long parent_rate)
57 {
58         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
59         unsigned long mdiv;
60         unsigned long refdiv;
61         unsigned long reg;
62         unsigned long long vco_freq;
63
64         /* read VCO1 reg for numerator and denominator */
65         reg = readl(socfpgaclk->hw.reg);
66         refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
67
68         vco_freq = parent_rate;
69         do_div(vco_freq, refdiv);
70
71         /* Read mdiv and fdiv from the fdbck register */
72         reg = readl(socfpgaclk->hw.reg + 0x4);
73         mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
74         vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
75
76         return (unsigned long)vco_freq;
77 }
78
79 static unsigned long clk_boot_clk_recalc_rate(struct clk_hw *hwclk,
80                                          unsigned long parent_rate)
81 {
82         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
83         u32 div = 1;
84
85         div = ((readl(socfpgaclk->hw.reg) &
86                 SWCTRLBTCLKSEL_MASK) >>
87                 SWCTRLBTCLKSEL_SHIFT);
88         div += 1;
89         return parent_rate /= div;
90 }
91
92
93 static u8 clk_pll_get_parent(struct clk_hw *hwclk)
94 {
95         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
96         u32 pll_src;
97
98         pll_src = readl(socfpgaclk->hw.reg);
99         return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
100                 CLK_MGR_PLL_CLK_SRC_MASK;
101 }
102
103 static u8 clk_boot_get_parent(struct clk_hw *hwclk)
104 {
105         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
106         u32 pll_src;
107
108         pll_src = readl(socfpgaclk->hw.reg);
109         return (pll_src >> SWCTRLBTCLKSEL_SHIFT) &
110                 SWCTRLBTCLKSEL_MASK;
111 }
112
113 static int clk_pll_prepare(struct clk_hw *hwclk)
114 {
115         struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
116         u32 reg;
117
118         /* Bring PLL out of reset */
119         reg = readl(socfpgaclk->hw.reg);
120         reg |= SOCFPGA_PLL_RESET_MASK;
121         writel(reg, socfpgaclk->hw.reg);
122
123         return 0;
124 }
125
126 static const struct clk_ops agilex_clk_pll_ops = {
127         .recalc_rate = agilex_clk_pll_recalc_rate,
128         .get_parent = clk_pll_get_parent,
129         .prepare = clk_pll_prepare,
130 };
131
132 static const struct clk_ops clk_pll_ops = {
133         .recalc_rate = clk_pll_recalc_rate,
134         .get_parent = clk_pll_get_parent,
135         .prepare = clk_pll_prepare,
136 };
137
138 static const struct clk_ops clk_boot_ops = {
139         .recalc_rate = clk_boot_clk_recalc_rate,
140         .get_parent = clk_boot_get_parent,
141         .prepare = clk_pll_prepare,
142 };
143
144 struct clk *s10_register_pll(const struct stratix10_pll_clock *clks,
145                              void __iomem *reg)
146 {
147         struct clk *clk;
148         struct socfpga_pll *pll_clk;
149         struct clk_init_data init;
150         const char *name = clks->name;
151
152         pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
153         if (WARN_ON(!pll_clk))
154                 return NULL;
155
156         pll_clk->hw.reg = reg + clks->offset;
157
158         if (streq(name, SOCFPGA_BOOT_CLK))
159                 init.ops = &clk_boot_ops;
160         else
161                 init.ops = &clk_pll_ops;
162
163         init.name = name;
164         init.flags = clks->flags;
165
166         init.num_parents = clks->num_parents;
167         init.parent_names = NULL;
168         init.parent_data = clks->parent_data;
169         pll_clk->hw.hw.init = &init;
170
171         pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
172
173         clk = clk_register(NULL, &pll_clk->hw.hw);
174         if (WARN_ON(IS_ERR(clk))) {
175                 kfree(pll_clk);
176                 return NULL;
177         }
178         return clk;
179 }
180
181 struct clk *agilex_register_pll(const struct stratix10_pll_clock *clks,
182                                 void __iomem *reg)
183 {
184         struct clk *clk;
185         struct socfpga_pll *pll_clk;
186         struct clk_init_data init;
187         const char *name = clks->name;
188
189         pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
190         if (WARN_ON(!pll_clk))
191                 return NULL;
192
193         pll_clk->hw.reg = reg + clks->offset;
194
195         if (streq(name, SOCFPGA_BOOT_CLK))
196                 init.ops = &clk_boot_ops;
197         else
198                 init.ops = &agilex_clk_pll_ops;
199
200         init.name = name;
201         init.flags = clks->flags;
202
203         init.num_parents = clks->num_parents;
204         init.parent_names = NULL;
205         init.parent_data = clks->parent_data;
206         pll_clk->hw.hw.init = &init;
207
208         pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER;
209
210         clk = clk_register(NULL, &pll_clk->hw.hw);
211         if (WARN_ON(IS_ERR(clk))) {
212                 kfree(pll_clk);
213                 return NULL;
214         }
215         return clk;
216 }