1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
9 #include <asm/arch/clock_manager.h>
10 #include <asm/arch/handoff_s10.h>
11 #include <asm/arch/system_manager.h>
13 DECLARE_GLOBAL_DATA_PTR;
16 * function to write the bypass register which requires a poll of the
19 static void cm_write_bypass_mainpll(u32 val)
21 writel(val, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_BYPASS);
25 static void cm_write_bypass_perpll(u32 val)
27 writel(val, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_BYPASS);
31 /* function to write the ctrl register which requires a poll of the busy bit */
32 static void cm_write_ctrl(u32 val)
34 writel(val, socfpga_get_clkmgr_addr() + CLKMGR_S10_CTRL);
39 * Setup clocks while making no assumptions about previous state of the clocks.
41 void cm_basic_init(const struct cm_config * const cfg)
43 u32 mdiv, refclkdiv, mscnt, hscnt, vcocalib;
48 /* Put all plls in bypass */
49 cm_write_bypass_mainpll(CLKMGR_BYPASS_MAINPLL_ALL);
50 cm_write_bypass_perpll(CLKMGR_BYPASS_PERPLL_ALL);
52 /* setup main PLL dividers where calculate the vcocalib value */
53 mdiv = (cfg->main_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
54 CLKMGR_FDBCK_MDIV_MASK;
55 refclkdiv = (cfg->main_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
56 CLKMGR_PLLGLOB_REFCLKDIV_MASK;
57 mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
58 hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
60 vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
61 ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
62 CLKMGR_VCOCALIB_MSCNT_OFFSET);
64 writel((cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
65 ~CLKMGR_PLLGLOB_RST_MASK),
66 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_PLLGLOB);
67 writel(cfg->main_pll_fdbck,
68 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_FDBCK);
70 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_VCOCALIB);
71 writel(cfg->main_pll_pllc0,
72 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_PLLC0);
73 writel(cfg->main_pll_pllc1,
74 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_PLLC1);
75 writel(cfg->main_pll_nocdiv,
76 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_NOCDIV);
78 /* setup peripheral PLL dividers */
79 /* calculate the vcocalib value */
80 mdiv = (cfg->per_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
81 CLKMGR_FDBCK_MDIV_MASK;
82 refclkdiv = (cfg->per_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
83 CLKMGR_PLLGLOB_REFCLKDIV_MASK;
84 mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
85 hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
87 vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
88 ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
89 CLKMGR_VCOCALIB_MSCNT_OFFSET);
91 writel((cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
92 ~CLKMGR_PLLGLOB_RST_MASK),
93 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_PLLGLOB);
94 writel(cfg->per_pll_fdbck,
95 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_FDBCK);
97 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_VCOCALIB);
98 writel(cfg->per_pll_pllc0,
99 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_PLLC0);
100 writel(cfg->per_pll_pllc1,
101 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_PLLC1);
102 writel(cfg->per_pll_emacctl,
103 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_EMACCTL);
104 writel(cfg->per_pll_gpiodiv,
105 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_GPIODIV);
107 /* Take both PLL out of reset and power up */
108 setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_PLLGLOB,
109 CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
110 setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_PLLGLOB,
111 CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
113 #define LOCKED_MASK \
114 (CLKMGR_STAT_MAINPLL_LOCKED | \
115 CLKMGR_STAT_PERPLL_LOCKED)
117 cm_wait_for_lock(LOCKED_MASK);
120 * Dividers for C2 to C9 only init after PLLs are lock. As dividers
121 * only take effect upon value change, we shall set a maximum value as
124 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_MPUCLK);
125 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_NOCCLK);
126 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR2CLK);
127 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR3CLK);
128 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR4CLK);
129 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR5CLK);
130 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR6CLK);
131 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR7CLK);
132 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR8CLK);
133 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR9CLK);
134 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR2CLK);
135 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR3CLK);
136 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR4CLK);
137 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR5CLK);
138 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR6CLK);
139 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR7CLK);
140 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR8CLK);
141 writel(0xff, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR9CLK);
143 writel(cfg->main_pll_mpuclk,
144 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_MPUCLK);
145 writel(cfg->main_pll_nocclk,
146 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_NOCCLK);
147 writel(cfg->main_pll_cntr2clk,
148 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR2CLK);
149 writel(cfg->main_pll_cntr3clk,
150 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR3CLK);
151 writel(cfg->main_pll_cntr4clk,
152 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR4CLK);
153 writel(cfg->main_pll_cntr5clk,
154 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR5CLK);
155 writel(cfg->main_pll_cntr6clk,
156 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR6CLK);
157 writel(cfg->main_pll_cntr7clk,
158 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR7CLK);
159 writel(cfg->main_pll_cntr8clk,
160 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR8CLK);
161 writel(cfg->main_pll_cntr9clk,
162 socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_CNTR9CLK);
163 writel(cfg->per_pll_cntr2clk,
164 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR2CLK);
165 writel(cfg->per_pll_cntr3clk,
166 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR3CLK);
167 writel(cfg->per_pll_cntr4clk,
168 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR4CLK);
169 writel(cfg->per_pll_cntr5clk,
170 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR5CLK);
171 writel(cfg->per_pll_cntr6clk,
172 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR6CLK);
173 writel(cfg->per_pll_cntr7clk,
174 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR7CLK);
175 writel(cfg->per_pll_cntr8clk,
176 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR8CLK);
177 writel(cfg->per_pll_cntr9clk,
178 socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_CNTR9CLK);
180 /* Take all PLLs out of bypass */
181 cm_write_bypass_mainpll(0);
182 cm_write_bypass_perpll(0);
184 /* clear safe mode / out of boot mode */
185 cm_write_ctrl(readl(socfpga_get_clkmgr_addr() + CLKMGR_S10_CTRL) &
186 ~(CLKMGR_CTRL_SAFEMODE));
188 /* Now ungate non-hw-managed clocks */
189 writel(~0, socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_EN);
190 writel(~0, socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_EN);
192 /* Clear the loss of lock bits (write 1 to clear) */
193 writel(CLKMGR_INTER_PERPLLLOST_MASK |
194 CLKMGR_INTER_MAINPLLLOST_MASK,
195 socfpga_get_clkmgr_addr() + CLKMGR_S10_INTRCLR);
198 static unsigned long cm_get_main_vco_clk_hz(void)
200 unsigned long fref, refdiv, mdiv, reg, vco;
202 reg = readl(socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_PLLGLOB);
204 fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
205 CLKMGR_PLLGLOB_VCO_PSRC_MASK;
207 case CLKMGR_VCO_PSRC_EOSC1:
208 fref = cm_get_osc_clk_hz();
210 case CLKMGR_VCO_PSRC_INTOSC:
211 fref = cm_get_intosc_clk_hz();
213 case CLKMGR_VCO_PSRC_F2S:
214 fref = cm_get_fpga_clk_hz();
218 refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
219 CLKMGR_PLLGLOB_REFCLKDIV_MASK;
221 reg = readl(socfpga_get_clkmgr_addr() + CLKMGR_S10_MAINPLL_FDBCK);
222 mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
225 vco = vco * (CLKMGR_MDIV_CONST + mdiv);
229 static unsigned long cm_get_per_vco_clk_hz(void)
231 unsigned long fref, refdiv, mdiv, reg, vco;
233 reg = readl(socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_PLLGLOB);
235 fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
236 CLKMGR_PLLGLOB_VCO_PSRC_MASK;
238 case CLKMGR_VCO_PSRC_EOSC1:
239 fref = cm_get_osc_clk_hz();
241 case CLKMGR_VCO_PSRC_INTOSC:
242 fref = cm_get_intosc_clk_hz();
244 case CLKMGR_VCO_PSRC_F2S:
245 fref = cm_get_fpga_clk_hz();
249 refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
250 CLKMGR_PLLGLOB_REFCLKDIV_MASK;
252 reg = readl(socfpga_get_clkmgr_addr() + CLKMGR_S10_PERPLL_FDBCK);
253 mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
256 vco = vco * (CLKMGR_MDIV_CONST + mdiv);
260 unsigned long cm_get_mpu_clk_hz(void)
262 unsigned long clock = readl(socfpga_get_clkmgr_addr() +
263 CLKMGR_S10_MAINPLL_MPUCLK);
265 clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
268 case CLKMGR_CLKSRC_MAIN:
269 clock = cm_get_main_vco_clk_hz();
270 clock /= (readl(socfpga_get_clkmgr_addr() +
271 CLKMGR_S10_MAINPLL_PLLC0) &
272 CLKMGR_PLLC0_DIV_MASK);
275 case CLKMGR_CLKSRC_PER:
276 clock = cm_get_per_vco_clk_hz();
277 clock /= (readl(socfpga_get_clkmgr_addr() +
278 CLKMGR_S10_PERPLL_PLLC0) &
282 case CLKMGR_CLKSRC_OSC1:
283 clock = cm_get_osc_clk_hz();
286 case CLKMGR_CLKSRC_INTOSC:
287 clock = cm_get_intosc_clk_hz();
290 case CLKMGR_CLKSRC_FPGA:
291 clock = cm_get_fpga_clk_hz();
295 clock /= 1 + (readl(socfpga_get_clkmgr_addr() +
296 CLKMGR_S10_MAINPLL_MPUCLK) & CLKMGR_CLKCNT_MSK);
300 unsigned int cm_get_l3_main_clk_hz(void)
302 u32 clock = readl(socfpga_get_clkmgr_addr() +
303 CLKMGR_S10_MAINPLL_NOCCLK);
305 clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
308 case CLKMGR_CLKSRC_MAIN:
309 clock = cm_get_main_vco_clk_hz();
310 clock /= (readl(socfpga_get_clkmgr_addr() +
311 CLKMGR_S10_MAINPLL_PLLC1) &
312 CLKMGR_PLLC0_DIV_MASK);
315 case CLKMGR_CLKSRC_PER:
316 clock = cm_get_per_vco_clk_hz();
317 clock /= (readl(socfpga_get_clkmgr_addr() +
318 CLKMGR_S10_PERPLL_PLLC1) & CLKMGR_CLKCNT_MSK);
321 case CLKMGR_CLKSRC_OSC1:
322 clock = cm_get_osc_clk_hz();
325 case CLKMGR_CLKSRC_INTOSC:
326 clock = cm_get_intosc_clk_hz();
329 case CLKMGR_CLKSRC_FPGA:
330 clock = cm_get_fpga_clk_hz();
334 clock /= 1 + (readl(socfpga_get_clkmgr_addr() +
335 CLKMGR_S10_MAINPLL_NOCCLK) & CLKMGR_CLKCNT_MSK);
339 unsigned int cm_get_mmc_controller_clk_hz(void)
341 u32 clock = readl(socfpga_get_clkmgr_addr() +
342 CLKMGR_S10_PERPLL_CNTR6CLK);
344 clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
347 case CLKMGR_CLKSRC_MAIN:
348 clock = cm_get_l3_main_clk_hz();
349 clock /= 1 + (readl(socfpga_get_clkmgr_addr() +
350 CLKMGR_S10_MAINPLL_CNTR6CLK) &
354 case CLKMGR_CLKSRC_PER:
355 clock = cm_get_l3_main_clk_hz();
356 clock /= 1 + (readl(socfpga_get_clkmgr_addr() +
357 CLKMGR_S10_PERPLL_CNTR6CLK) &
361 case CLKMGR_CLKSRC_OSC1:
362 clock = cm_get_osc_clk_hz();
365 case CLKMGR_CLKSRC_INTOSC:
366 clock = cm_get_intosc_clk_hz();
369 case CLKMGR_CLKSRC_FPGA:
370 clock = cm_get_fpga_clk_hz();
376 unsigned int cm_get_l4_sp_clk_hz(void)
378 u32 clock = cm_get_l3_main_clk_hz();
380 clock /= (1 << ((readl(socfpga_get_clkmgr_addr() +
381 CLKMGR_S10_MAINPLL_NOCDIV) >>
382 CLKMGR_NOCDIV_L4SPCLK_OFFSET) & CLKMGR_CLKCNT_MSK));
386 unsigned int cm_get_qspi_controller_clk_hz(void)
388 return readl(socfpga_get_sysmgr_addr() +
389 SYSMGR_SOC64_BOOT_SCRATCH_COLD0);
392 unsigned int cm_get_spi_controller_clk_hz(void)
394 u32 clock = cm_get_l3_main_clk_hz();
396 clock /= (1 << ((readl(socfpga_get_clkmgr_addr() +
397 CLKMGR_S10_MAINPLL_NOCDIV) >>
398 CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_CLKCNT_MSK));
402 unsigned int cm_get_l4_sys_free_clk_hz(void)
404 return cm_get_l3_main_clk_hz() / 4;
407 void cm_print_clock_quick_summary(void)
409 printf("MPU %d kHz\n", (u32)(cm_get_mpu_clk_hz() / 1000));
410 printf("L3 main %d kHz\n", cm_get_l3_main_clk_hz() / 1000);
411 printf("Main VCO %d kHz\n", (u32)(cm_get_main_vco_clk_hz() / 1000));
412 printf("Per VCO %d kHz\n", (u32)(cm_get_per_vco_clk_hz() / 1000));
413 printf("EOSC1 %d kHz\n", cm_get_osc_clk_hz() / 1000);
414 printf("HPS MMC %d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
415 printf("UART %d kHz\n", cm_get_l4_sp_clk_hz() / 1000);