1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017, Intel Corporation
5 #include <linux/slab.h>
6 #include <linux/clk-provider.h>
9 #include "stratix10-clk.h"
12 /* Clock Manager offsets */
13 #define CLK_MGR_PLL_CLK_SRC_SHIFT 16
14 #define CLK_MGR_PLL_CLK_SRC_MASK 0x3
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
30 #define SOCFPGA_N5X_PLLDIV_FDIV_MASK GENMASK(16, 8)
31 #define SOCFPGA_N5X_PLLDIV_FDIV_SHIFT 8
32 #define SOCFPGA_N5X_PLLDIV_RDIV_MASK GENMASK(5, 0)
33 #define SOCFPGA_N5X_PLLDIV_QDIV_MASK GENMASK(26, 24)
34 #define SOCFPGA_N5X_PLLDIV_QDIV_SHIFT 24
36 #define SOCFPGA_BOOT_CLK "boot_clk"
38 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
40 static unsigned long n5x_clk_pll_recalc_rate(struct clk_hw
*hwclk
,
41 unsigned long parent_rate
)
43 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
44 unsigned long fdiv
, reg
, rdiv
, qdiv
;
47 /* read VCO1 reg for numerator and denominator */
48 reg
= readl(socfpgaclk
->hw
.reg
+ 0x8);
49 fdiv
= (reg
& SOCFPGA_N5X_PLLDIV_FDIV_MASK
) >> SOCFPGA_N5X_PLLDIV_FDIV_SHIFT
;
50 rdiv
= (reg
& SOCFPGA_N5X_PLLDIV_RDIV_MASK
);
51 qdiv
= (reg
& SOCFPGA_N5X_PLLDIV_QDIV_MASK
) >> SOCFPGA_N5X_PLLDIV_QDIV_SHIFT
;
58 return ((parent_rate
* 2 * (fdiv
+ 1)) / ((rdiv
+ 1) * power
));
61 static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw
*hwclk
,
62 unsigned long parent_rate
)
64 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
65 unsigned long arefdiv
, reg
, mdiv
;
66 unsigned long long vco_freq
;
68 /* read VCO1 reg for numerator and denominator */
69 reg
= readl(socfpgaclk
->hw
.reg
);
70 arefdiv
= (reg
& SOCFPGA_PLL_AREFDIV_MASK
) >> SOCFPGA_PLL_REFDIV_SHIFT
;
72 vco_freq
= (unsigned long long)parent_rate
/ arefdiv
;
74 /* Read mdiv and fdiv from the fdbck register */
75 reg
= readl(socfpgaclk
->hw
.reg
+ 0x24);
76 mdiv
= reg
& SOCFPGA_AGILEX_PLL_MDIV_MASK
;
78 vco_freq
= (unsigned long long)vco_freq
* mdiv
;
79 return (unsigned long)vco_freq
;
82 static unsigned long clk_pll_recalc_rate(struct clk_hw
*hwclk
,
83 unsigned long parent_rate
)
85 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
89 unsigned long long vco_freq
;
91 /* read VCO1 reg for numerator and denominator */
92 reg
= readl(socfpgaclk
->hw
.reg
);
93 refdiv
= (reg
& SOCFPGA_PLL_REFDIV_MASK
) >> SOCFPGA_PLL_REFDIV_SHIFT
;
95 vco_freq
= parent_rate
;
96 do_div(vco_freq
, refdiv
);
98 /* Read mdiv and fdiv from the fdbck register */
99 reg
= readl(socfpgaclk
->hw
.reg
+ 0x4);
100 mdiv
= (reg
& SOCFPGA_PLL_MDIV_MASK
) >> SOCFPGA_PLL_MDIV_SHIFT
;
101 vco_freq
= (unsigned long long)vco_freq
* (mdiv
+ 6);
103 return (unsigned long)vco_freq
;
106 static unsigned long clk_boot_clk_recalc_rate(struct clk_hw
*hwclk
,
107 unsigned long parent_rate
)
109 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
112 div
= ((readl(socfpgaclk
->hw
.reg
) &
113 SWCTRLBTCLKSEL_MASK
) >>
114 SWCTRLBTCLKSEL_SHIFT
);
116 return parent_rate
/ div
;
120 static u8
clk_pll_get_parent(struct clk_hw
*hwclk
)
122 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
125 pll_src
= readl(socfpgaclk
->hw
.reg
);
126 return (pll_src
>> CLK_MGR_PLL_CLK_SRC_SHIFT
) &
127 CLK_MGR_PLL_CLK_SRC_MASK
;
130 static u8
clk_boot_get_parent(struct clk_hw
*hwclk
)
132 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
135 pll_src
= readl(socfpgaclk
->hw
.reg
);
136 return (pll_src
>> SWCTRLBTCLKSEL_SHIFT
) &
140 static int clk_pll_prepare(struct clk_hw
*hwclk
)
142 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
145 /* Bring PLL out of reset */
146 reg
= readl(socfpgaclk
->hw
.reg
);
147 reg
|= SOCFPGA_PLL_RESET_MASK
;
148 writel(reg
, socfpgaclk
->hw
.reg
);
153 static int n5x_clk_pll_prepare(struct clk_hw
*hwclk
)
155 struct socfpga_pll
*socfpgaclk
= to_socfpga_clk(hwclk
);
158 /* Bring PLL out of reset */
159 reg
= readl(socfpgaclk
->hw
.reg
+ 0x4);
160 reg
|= SOCFPGA_PLL_RESET_MASK
;
161 writel(reg
, socfpgaclk
->hw
.reg
+ 0x4);
166 static const struct clk_ops n5x_clk_pll_ops
= {
167 .recalc_rate
= n5x_clk_pll_recalc_rate
,
168 .get_parent
= clk_pll_get_parent
,
169 .prepare
= n5x_clk_pll_prepare
,
172 static const struct clk_ops agilex_clk_pll_ops
= {
173 .recalc_rate
= agilex_clk_pll_recalc_rate
,
174 .get_parent
= clk_pll_get_parent
,
175 .prepare
= clk_pll_prepare
,
178 static const struct clk_ops clk_pll_ops
= {
179 .recalc_rate
= clk_pll_recalc_rate
,
180 .get_parent
= clk_pll_get_parent
,
181 .prepare
= clk_pll_prepare
,
184 static const struct clk_ops clk_boot_ops
= {
185 .recalc_rate
= clk_boot_clk_recalc_rate
,
186 .get_parent
= clk_boot_get_parent
,
187 .prepare
= clk_pll_prepare
,
190 struct clk_hw
*s10_register_pll(const struct stratix10_pll_clock
*clks
,
193 struct clk_hw
*hw_clk
;
194 struct socfpga_pll
*pll_clk
;
195 struct clk_init_data init
;
196 const char *name
= clks
->name
;
199 pll_clk
= kzalloc(sizeof(*pll_clk
), GFP_KERNEL
);
200 if (WARN_ON(!pll_clk
))
203 pll_clk
->hw
.reg
= reg
+ clks
->offset
;
205 if (streq(name
, SOCFPGA_BOOT_CLK
))
206 init
.ops
= &clk_boot_ops
;
208 init
.ops
= &clk_pll_ops
;
211 init
.flags
= clks
->flags
;
213 init
.num_parents
= clks
->num_parents
;
214 init
.parent_names
= NULL
;
215 init
.parent_data
= clks
->parent_data
;
216 pll_clk
->hw
.hw
.init
= &init
;
218 pll_clk
->hw
.bit_idx
= SOCFPGA_PLL_POWER
;
220 hw_clk
= &pll_clk
->hw
.hw
;
222 ret
= clk_hw_register(NULL
, hw_clk
);
230 struct clk_hw
*agilex_register_pll(const struct stratix10_pll_clock
*clks
,
233 struct clk_hw
*hw_clk
;
234 struct socfpga_pll
*pll_clk
;
235 struct clk_init_data init
;
236 const char *name
= clks
->name
;
239 pll_clk
= kzalloc(sizeof(*pll_clk
), GFP_KERNEL
);
240 if (WARN_ON(!pll_clk
))
243 pll_clk
->hw
.reg
= reg
+ clks
->offset
;
245 if (streq(name
, SOCFPGA_BOOT_CLK
))
246 init
.ops
= &clk_boot_ops
;
248 init
.ops
= &agilex_clk_pll_ops
;
251 init
.flags
= clks
->flags
;
253 init
.num_parents
= clks
->num_parents
;
254 init
.parent_names
= NULL
;
255 init
.parent_data
= clks
->parent_data
;
256 pll_clk
->hw
.hw
.init
= &init
;
258 pll_clk
->hw
.bit_idx
= SOCFPGA_PLL_POWER
;
259 hw_clk
= &pll_clk
->hw
.hw
;
261 ret
= clk_hw_register(NULL
, hw_clk
);
269 struct clk_hw
*n5x_register_pll(const struct stratix10_pll_clock
*clks
,
272 struct clk_hw
*hw_clk
;
273 struct socfpga_pll
*pll_clk
;
274 struct clk_init_data init
;
275 const char *name
= clks
->name
;
278 pll_clk
= kzalloc(sizeof(*pll_clk
), GFP_KERNEL
);
279 if (WARN_ON(!pll_clk
))
282 pll_clk
->hw
.reg
= reg
+ clks
->offset
;
284 if (streq(name
, SOCFPGA_BOOT_CLK
))
285 init
.ops
= &clk_boot_ops
;
287 init
.ops
= &n5x_clk_pll_ops
;
290 init
.flags
= clks
->flags
;
292 init
.num_parents
= clks
->num_parents
;
293 init
.parent_names
= NULL
;
294 init
.parent_data
= clks
->parent_data
;
295 pll_clk
->hw
.hw
.init
= &init
;
297 pll_clk
->hw
.bit_idx
= SOCFPGA_PLL_POWER
;
298 hw_clk
= &pll_clk
->hw
.hw
;
300 ret
= clk_hw_register(NULL
, hw_clk
);