blob: 20369453e0b1a9ada8ed9e936b3ccca37770c5b4 [file] [log] [blame]
Yann Gautier9aea69e2018-07-24 17:13:36 +02001/*
Yann Gautiera2e2a302019-02-14 11:13:39 +01002 * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
Yann Gautier9aea69e2018-07-24 17:13:36 +02003 *
4 * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5 */
6
Yann Gautier9aea69e2018-07-24 17:13:36 +02007#include <assert.h>
Yann Gautier9aea69e2018-07-24 17:13:36 +02008#include <errno.h>
Yann Gautier9aea69e2018-07-24 17:13:36 +02009#include <stdint.h>
Antonio Nino Diaz00086e32018-08-16 16:46:06 +010010#include <stdio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
12#include <libfdt.h>
13
Yann Gautier57e282b2019-01-07 11:17:24 +010014#include <platform_def.h>
15
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <arch.h>
17#include <arch_helpers.h>
18#include <common/debug.h>
Andre Przywaracc99f3f2020-03-26 12:51:21 +000019#include <common/fdt_wrappers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000020#include <drivers/delay_timer.h>
21#include <drivers/generic_delay_timer.h>
Yann Gautier4d429472019-02-14 11:15:20 +010022#include <drivers/st/stm32mp_clkfunc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000023#include <drivers/st/stm32mp1_clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000024#include <drivers/st/stm32mp1_rcc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000025#include <dt-bindings/clock/stm32mp1-clksrc.h>
26#include <lib/mmio.h>
Yann Gautiere4a3c352019-02-14 10:53:33 +010027#include <lib/spinlock.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000028#include <lib/utils_def.h>
29#include <plat/common/platform.h>
30
Yann Gautier2299d572019-02-14 11:14:39 +010031#define MAX_HSI_HZ 64000000
Yann Gautiere4a3c352019-02-14 10:53:33 +010032#define USB_PHY_48_MHZ 48000000
Yann Gautier9aea69e2018-07-24 17:13:36 +020033
Yann Gautier2299d572019-02-14 11:14:39 +010034#define TIMEOUT_US_200MS U(200000)
35#define TIMEOUT_US_1S U(1000000)
Yann Gautier9aea69e2018-07-24 17:13:36 +020036
Yann Gautier2299d572019-02-14 11:14:39 +010037#define PLLRDY_TIMEOUT TIMEOUT_US_200MS
38#define CLKSRC_TIMEOUT TIMEOUT_US_200MS
39#define CLKDIV_TIMEOUT TIMEOUT_US_200MS
40#define HSIDIV_TIMEOUT TIMEOUT_US_200MS
41#define OSCRDY_TIMEOUT TIMEOUT_US_1S
Yann Gautier9aea69e2018-07-24 17:13:36 +020042
Yann Gautier5f2e8742019-05-17 15:57:56 +020043const char *stm32mp_osc_node_label[NB_OSC] = {
44 [_LSI] = "clk-lsi",
45 [_LSE] = "clk-lse",
46 [_HSI] = "clk-hsi",
47 [_HSE] = "clk-hse",
48 [_CSI] = "clk-csi",
49 [_I2S_CKIN] = "i2s_ckin",
50};
51
Yann Gautier9aea69e2018-07-24 17:13:36 +020052enum stm32mp1_parent_id {
53/* Oscillators are defined in enum stm32mp_osc_id */
54
55/* Other parent source */
56 _HSI_KER = NB_OSC,
57 _HSE_KER,
58 _HSE_KER_DIV2,
59 _CSI_KER,
60 _PLL1_P,
61 _PLL1_Q,
62 _PLL1_R,
63 _PLL2_P,
64 _PLL2_Q,
65 _PLL2_R,
66 _PLL3_P,
67 _PLL3_Q,
68 _PLL3_R,
69 _PLL4_P,
70 _PLL4_Q,
71 _PLL4_R,
72 _ACLK,
73 _PCLK1,
74 _PCLK2,
75 _PCLK3,
76 _PCLK4,
77 _PCLK5,
78 _HCLK6,
79 _HCLK2,
80 _CK_PER,
81 _CK_MPU,
Yann Gautiered342322019-02-15 17:33:27 +010082 _CK_MCU,
Yann Gautiere4a3c352019-02-14 10:53:33 +010083 _USB_PHY_48,
Yann Gautier9aea69e2018-07-24 17:13:36 +020084 _PARENT_NB,
85 _UNKNOWN_ID = 0xff,
86};
87
Yann Gautiere4a3c352019-02-14 10:53:33 +010088/* Lists only the parent clock we are interested in */
Yann Gautier9aea69e2018-07-24 17:13:36 +020089enum stm32mp1_parent_sel {
Yann Gautiere4a3c352019-02-14 10:53:33 +010090 _I2C12_SEL,
91 _I2C35_SEL,
92 _STGEN_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020093 _I2C46_SEL,
Yann Gautiere4a3c352019-02-14 10:53:33 +010094 _SPI6_SEL,
Yann Gautier9d8bbcd2019-05-07 18:49:33 +020095 _UART1_SEL,
Yann Gautiere4a3c352019-02-14 10:53:33 +010096 _RNG1_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020097 _UART6_SEL,
98 _UART24_SEL,
99 _UART35_SEL,
100 _UART78_SEL,
101 _SDMMC12_SEL,
102 _SDMMC3_SEL,
103 _QSPI_SEL,
104 _FMC_SEL,
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200105 _AXIS_SEL,
106 _MCUS_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200107 _USBPHY_SEL,
108 _USBO_SEL,
Etienne Carriere04132612019-12-08 08:20:12 +0100109 _MPU_SEL,
110 _PER_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200111 _PARENT_SEL_NB,
112 _UNKNOWN_SEL = 0xff,
113};
114
Etienne Carriere04132612019-12-08 08:20:12 +0100115/* State the parent clock ID straight related to a clock */
116static const uint8_t parent_id_clock_id[_PARENT_NB] = {
117 [_HSE] = CK_HSE,
118 [_HSI] = CK_HSI,
119 [_CSI] = CK_CSI,
120 [_LSE] = CK_LSE,
121 [_LSI] = CK_LSI,
122 [_I2S_CKIN] = _UNKNOWN_ID,
123 [_USB_PHY_48] = _UNKNOWN_ID,
124 [_HSI_KER] = CK_HSI,
125 [_HSE_KER] = CK_HSE,
126 [_HSE_KER_DIV2] = CK_HSE_DIV2,
127 [_CSI_KER] = CK_CSI,
128 [_PLL1_P] = PLL1_P,
129 [_PLL1_Q] = PLL1_Q,
130 [_PLL1_R] = PLL1_R,
131 [_PLL2_P] = PLL2_P,
132 [_PLL2_Q] = PLL2_Q,
133 [_PLL2_R] = PLL2_R,
134 [_PLL3_P] = PLL3_P,
135 [_PLL3_Q] = PLL3_Q,
136 [_PLL3_R] = PLL3_R,
137 [_PLL4_P] = PLL4_P,
138 [_PLL4_Q] = PLL4_Q,
139 [_PLL4_R] = PLL4_R,
140 [_ACLK] = CK_AXI,
141 [_PCLK1] = CK_AXI,
142 [_PCLK2] = CK_AXI,
143 [_PCLK3] = CK_AXI,
144 [_PCLK4] = CK_AXI,
145 [_PCLK5] = CK_AXI,
146 [_CK_PER] = CK_PER,
147 [_CK_MPU] = CK_MPU,
148 [_CK_MCU] = CK_MCU,
149};
150
151static unsigned int clock_id2parent_id(unsigned long id)
152{
153 unsigned int n;
154
155 for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
156 if (parent_id_clock_id[n] == id) {
157 return n;
158 }
159 }
160
161 return _UNKNOWN_ID;
162}
163
Yann Gautier9aea69e2018-07-24 17:13:36 +0200164enum stm32mp1_pll_id {
165 _PLL1,
166 _PLL2,
167 _PLL3,
168 _PLL4,
169 _PLL_NB
170};
171
172enum stm32mp1_div_id {
173 _DIV_P,
174 _DIV_Q,
175 _DIV_R,
176 _DIV_NB,
177};
178
179enum stm32mp1_clksrc_id {
180 CLKSRC_MPU,
181 CLKSRC_AXI,
Yann Gautiered342322019-02-15 17:33:27 +0100182 CLKSRC_MCU,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200183 CLKSRC_PLL12,
184 CLKSRC_PLL3,
185 CLKSRC_PLL4,
186 CLKSRC_RTC,
187 CLKSRC_MCO1,
188 CLKSRC_MCO2,
189 CLKSRC_NB
190};
191
192enum stm32mp1_clkdiv_id {
193 CLKDIV_MPU,
194 CLKDIV_AXI,
Yann Gautiered342322019-02-15 17:33:27 +0100195 CLKDIV_MCU,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200196 CLKDIV_APB1,
197 CLKDIV_APB2,
198 CLKDIV_APB3,
199 CLKDIV_APB4,
200 CLKDIV_APB5,
201 CLKDIV_RTC,
202 CLKDIV_MCO1,
203 CLKDIV_MCO2,
204 CLKDIV_NB
205};
206
207enum stm32mp1_pllcfg {
208 PLLCFG_M,
209 PLLCFG_N,
210 PLLCFG_P,
211 PLLCFG_Q,
212 PLLCFG_R,
213 PLLCFG_O,
214 PLLCFG_NB
215};
216
217enum stm32mp1_pllcsg {
218 PLLCSG_MOD_PER,
219 PLLCSG_INC_STEP,
220 PLLCSG_SSCG_MODE,
221 PLLCSG_NB
222};
223
224enum stm32mp1_plltype {
225 PLL_800,
226 PLL_1600,
227 PLL_TYPE_NB
228};
229
230struct stm32mp1_pll {
231 uint8_t refclk_min;
232 uint8_t refclk_max;
233 uint8_t divn_max;
234};
235
236struct stm32mp1_clk_gate {
237 uint16_t offset;
238 uint8_t bit;
239 uint8_t index;
240 uint8_t set_clr;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100241 uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
242 uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
Yann Gautier9aea69e2018-07-24 17:13:36 +0200243};
244
245struct stm32mp1_clk_sel {
246 uint16_t offset;
247 uint8_t src;
248 uint8_t msk;
249 uint8_t nb_parent;
250 const uint8_t *parent;
251};
252
253#define REFCLK_SIZE 4
254struct stm32mp1_clk_pll {
255 enum stm32mp1_plltype plltype;
256 uint16_t rckxselr;
257 uint16_t pllxcfgr1;
258 uint16_t pllxcfgr2;
259 uint16_t pllxfracr;
260 uint16_t pllxcr;
261 uint16_t pllxcsgr;
262 enum stm32mp_osc_id refclk[REFCLK_SIZE];
263};
264
Yann Gautiere4a3c352019-02-14 10:53:33 +0100265/* Clocks with selectable source and non set/clr register access */
266#define _CLK_SELEC(off, b, idx, s) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200267 { \
268 .offset = (off), \
269 .bit = (b), \
270 .index = (idx), \
271 .set_clr = 0, \
272 .sel = (s), \
273 .fixed = _UNKNOWN_ID, \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200274 }
275
Yann Gautiere4a3c352019-02-14 10:53:33 +0100276/* Clocks with fixed source and non set/clr register access */
277#define _CLK_FIXED(off, b, idx, f) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200278 { \
279 .offset = (off), \
280 .bit = (b), \
281 .index = (idx), \
282 .set_clr = 0, \
283 .sel = _UNKNOWN_SEL, \
284 .fixed = (f), \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200285 }
286
Yann Gautiere4a3c352019-02-14 10:53:33 +0100287/* Clocks with selectable source and set/clr register access */
288#define _CLK_SC_SELEC(off, b, idx, s) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200289 { \
290 .offset = (off), \
291 .bit = (b), \
292 .index = (idx), \
293 .set_clr = 1, \
294 .sel = (s), \
295 .fixed = _UNKNOWN_ID, \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200296 }
297
Yann Gautiere4a3c352019-02-14 10:53:33 +0100298/* Clocks with fixed source and set/clr register access */
299#define _CLK_SC_FIXED(off, b, idx, f) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200300 { \
301 .offset = (off), \
302 .bit = (b), \
303 .index = (idx), \
304 .set_clr = 1, \
305 .sel = _UNKNOWN_SEL, \
306 .fixed = (f), \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200307 }
308
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200309#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \
310 [_ ## _label ## _SEL] = { \
311 .offset = _rcc_selr, \
312 .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \
313 .msk = _rcc_selr ## _ ## _label ## SRC_MASK, \
314 .parent = (_parents), \
315 .nb_parent = ARRAY_SIZE(_parents) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200316 }
317
Yann Gautiere4a3c352019-02-14 10:53:33 +0100318#define _CLK_PLL(idx, type, off1, off2, off3, \
319 off4, off5, off6, \
320 p1, p2, p3, p4) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200321 [(idx)] = { \
322 .plltype = (type), \
323 .rckxselr = (off1), \
324 .pllxcfgr1 = (off2), \
325 .pllxcfgr2 = (off3), \
326 .pllxfracr = (off4), \
327 .pllxcr = (off5), \
328 .pllxcsgr = (off6), \
329 .refclk[0] = (p1), \
330 .refclk[1] = (p2), \
331 .refclk[2] = (p3), \
332 .refclk[3] = (p4), \
333 }
334
Yann Gautiere4a3c352019-02-14 10:53:33 +0100335#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate)
336
Yann Gautier9aea69e2018-07-24 17:13:36 +0200337static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100338 _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK),
339 _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
340 _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK),
341 _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
342 _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
343 _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
344 _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
345 _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
346 _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK),
347 _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
348 _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
349
350 _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
351 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
352 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
353 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
354 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
355 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
356 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
357 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
358 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
359 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
360 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
361
362 _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
363 _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
364
Yann Gautier3edc7c32019-05-20 19:17:08 +0200365 _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
366
Yann Gautiere4a3c352019-02-14 10:53:33 +0100367 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
368 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
369 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
370
371 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
372 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
373 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200374 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
Yann Gautiere4a3c352019-02-14 10:53:33 +0100375 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
376 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
377 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
378 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
379 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
380 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
381 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
382
383 _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
384 _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
385
386 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
387 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
388 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
389 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
390 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
391 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
392 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
393 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
394 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
395 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
396 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
397
398 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
399 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
400 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
401 _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
402 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
403
404 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
405 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
406 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
407 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
408 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
409
410 _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
411};
412
413static const uint8_t i2c12_parents[] = {
414 _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
415};
416
417static const uint8_t i2c35_parents[] = {
418 _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
419};
420
421static const uint8_t stgen_parents[] = {
422 _HSI_KER, _HSE_KER
423};
424
425static const uint8_t i2c46_parents[] = {
426 _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
427};
428
429static const uint8_t spi6_parents[] = {
430 _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
431};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200432
Yann Gautiere4a3c352019-02-14 10:53:33 +0100433static const uint8_t usart1_parents[] = {
434 _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
435};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200436
Yann Gautiere4a3c352019-02-14 10:53:33 +0100437static const uint8_t rng1_parents[] = {
438 _CSI, _PLL4_R, _LSE, _LSI
439};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200440
Yann Gautiere4a3c352019-02-14 10:53:33 +0100441static const uint8_t uart6_parents[] = {
442 _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
443};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200444
Yann Gautiere4a3c352019-02-14 10:53:33 +0100445static const uint8_t uart234578_parents[] = {
446 _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
447};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200448
Yann Gautiere4a3c352019-02-14 10:53:33 +0100449static const uint8_t sdmmc12_parents[] = {
450 _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
451};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200452
Yann Gautiere4a3c352019-02-14 10:53:33 +0100453static const uint8_t sdmmc3_parents[] = {
454 _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
455};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200456
Yann Gautiere4a3c352019-02-14 10:53:33 +0100457static const uint8_t qspi_parents[] = {
458 _ACLK, _PLL3_R, _PLL4_P, _CK_PER
459};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200460
Yann Gautiere4a3c352019-02-14 10:53:33 +0100461static const uint8_t fmc_parents[] = {
462 _ACLK, _PLL3_R, _PLL4_P, _CK_PER
463};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200464
Yann Gautiere4a3c352019-02-14 10:53:33 +0100465static const uint8_t ass_parents[] = {
466 _HSI, _HSE, _PLL2
Yann Gautier9aea69e2018-07-24 17:13:36 +0200467};
468
Yann Gautiered342322019-02-15 17:33:27 +0100469static const uint8_t mss_parents[] = {
470 _HSI, _HSE, _CSI, _PLL3
471};
472
Yann Gautiere4a3c352019-02-14 10:53:33 +0100473static const uint8_t usbphy_parents[] = {
474 _HSE_KER, _PLL4_R, _HSE_KER_DIV2
475};
476
477static const uint8_t usbo_parents[] = {
478 _PLL4_R, _USB_PHY_48
479};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200480
Etienne Carriere04132612019-12-08 08:20:12 +0100481static const uint8_t mpu_parents[] = {
482 _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
483};
484
485static const uint8_t per_parents[] = {
486 _HSI, _HSE, _CSI,
487};
488
Yann Gautier9aea69e2018-07-24 17:13:36 +0200489static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200490 _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
491 _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
492 _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
493 _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
494 _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
495 _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
496 _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
Etienne Carriere04132612019-12-08 08:20:12 +0100497 _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
498 _CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents),
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200499 _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
500 _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
501 _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
502 _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
503 _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
504 _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
505 _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
506 _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
507 _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents),
508 _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents),
509 _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
510 _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
Yann Gautier9aea69e2018-07-24 17:13:36 +0200511};
512
513/* Define characteristic of PLL according type */
514#define DIVN_MIN 24
515static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
516 [PLL_800] = {
517 .refclk_min = 4,
518 .refclk_max = 16,
519 .divn_max = 99,
520 },
521 [PLL_1600] = {
522 .refclk_min = 8,
523 .refclk_max = 16,
524 .divn_max = 199,
525 },
526};
527
528/* PLLNCFGR2 register divider by output */
529static const uint8_t pllncfgr2[_DIV_NB] = {
530 [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
531 [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
Yann Gautiere4a3c352019-02-14 10:53:33 +0100532 [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200533};
534
535static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100536 _CLK_PLL(_PLL1, PLL_1600,
537 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
538 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
539 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
540 _CLK_PLL(_PLL2, PLL_1600,
541 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
542 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
543 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
544 _CLK_PLL(_PLL3, PLL_800,
545 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
546 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
547 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
548 _CLK_PLL(_PLL4, PLL_800,
549 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
550 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
551 _HSI, _HSE, _CSI, _I2S_CKIN),
Yann Gautier9aea69e2018-07-24 17:13:36 +0200552};
553
554/* Prescaler table lookups for clock computation */
Yann Gautiered342322019-02-15 17:33:27 +0100555/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
556static const uint8_t stm32mp1_mcu_div[16] = {
557 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
558};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200559
560/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
561#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
562#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
563static const uint8_t stm32mp1_mpu_apbx_div[8] = {
564 0, 1, 2, 3, 4, 4, 4, 4
565};
566
567/* div = /1 /2 /3 /4 */
568static const uint8_t stm32mp1_axi_div[8] = {
569 1, 2, 3, 4, 4, 4, 4, 4
570};
571
Yann Gautiere4a3c352019-02-14 10:53:33 +0100572/* RCC clock device driver private */
573static unsigned long stm32mp1_osc[NB_OSC];
574static struct spinlock reg_lock;
575static unsigned int gate_refcounts[NB_GATES];
576static struct spinlock refcount_lock;
577
578static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
579{
580 return &stm32mp1_clk_gate[idx];
581}
Yann Gautier9aea69e2018-07-24 17:13:36 +0200582
Yann Gautiere4a3c352019-02-14 10:53:33 +0100583static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
584{
585 return &stm32mp1_clk_sel[idx];
586}
Yann Gautier9aea69e2018-07-24 17:13:36 +0200587
Yann Gautiere4a3c352019-02-14 10:53:33 +0100588static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
589{
590 return &stm32mp1_clk_pll[idx];
591}
592
Yann Gautiere4a3c352019-02-14 10:53:33 +0100593static void stm32mp1_clk_lock(struct spinlock *lock)
594{
Yann Gautierf540a592019-05-22 19:13:51 +0200595 if (stm32mp_lock_available()) {
596 /* Assume interrupts are masked */
597 spin_lock(lock);
Yann Gautiere4a3c352019-02-14 10:53:33 +0100598 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100599}
600
601static void stm32mp1_clk_unlock(struct spinlock *lock)
602{
Yann Gautierf540a592019-05-22 19:13:51 +0200603 if (stm32mp_lock_available()) {
604 spin_unlock(lock);
Yann Gautiere4a3c352019-02-14 10:53:33 +0100605 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100606}
607
608bool stm32mp1_rcc_is_secure(void)
609{
610 uintptr_t rcc_base = stm32mp_rcc_base();
611
612 return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0;
613}
614
Yann Gautiered342322019-02-15 17:33:27 +0100615bool stm32mp1_rcc_is_mckprot(void)
616{
617 uintptr_t rcc_base = stm32mp_rcc_base();
618
619 return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0;
620}
621
Yann Gautiere4a3c352019-02-14 10:53:33 +0100622void stm32mp1_clk_rcc_regs_lock(void)
623{
624 stm32mp1_clk_lock(&reg_lock);
625}
626
627void stm32mp1_clk_rcc_regs_unlock(void)
628{
629 stm32mp1_clk_unlock(&reg_lock);
630}
631
632static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200633{
634 if (idx >= NB_OSC) {
635 return 0;
636 }
637
Yann Gautiere4a3c352019-02-14 10:53:33 +0100638 return stm32mp1_osc[idx];
Yann Gautier9aea69e2018-07-24 17:13:36 +0200639}
640
Yann Gautiere4a3c352019-02-14 10:53:33 +0100641static int stm32mp1_clk_get_gated_id(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200642{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100643 unsigned int i;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200644
Yann Gautiere4a3c352019-02-14 10:53:33 +0100645 for (i = 0U; i < NB_GATES; i++) {
646 if (gate_ref(i)->index == id) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200647 return i;
648 }
649 }
650
651 ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id);
652
653 return -EINVAL;
654}
655
Yann Gautiere4a3c352019-02-14 10:53:33 +0100656static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200657{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100658 return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200659}
660
Yann Gautiere4a3c352019-02-14 10:53:33 +0100661static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200662{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100663 return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200664}
665
Yann Gautiere4a3c352019-02-14 10:53:33 +0100666static int stm32mp1_clk_get_parent(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200667{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100668 const struct stm32mp1_clk_sel *sel;
Etienne Carriere04132612019-12-08 08:20:12 +0100669 uint32_t p_sel;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200670 int i;
671 enum stm32mp1_parent_id p;
672 enum stm32mp1_parent_sel s;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100673 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200674
Etienne Carriere04132612019-12-08 08:20:12 +0100675 /* Few non gateable clock have a static parent ID, find them */
676 i = (int)clock_id2parent_id(id);
677 if (i != _UNKNOWN_ID) {
678 return i;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200679 }
680
Yann Gautiere4a3c352019-02-14 10:53:33 +0100681 i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200682 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100683 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200684 }
685
Yann Gautiere4a3c352019-02-14 10:53:33 +0100686 p = stm32mp1_clk_get_fixed_parent(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200687 if (p < _PARENT_NB) {
688 return (int)p;
689 }
690
Yann Gautiere4a3c352019-02-14 10:53:33 +0100691 s = stm32mp1_clk_get_sel(i);
692 if (s == _UNKNOWN_SEL) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200693 return -EINVAL;
694 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100695 if (s >= _PARENT_SEL_NB) {
696 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200697 }
698
Yann Gautiere4a3c352019-02-14 10:53:33 +0100699 sel = clk_sel_ref(s);
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200700 p_sel = (mmio_read_32(rcc_base + sel->offset) & sel->msk) >> sel->src;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100701 if (p_sel < sel->nb_parent) {
702 return (int)sel->parent[p_sel];
703 }
Yann Gautier9aea69e2018-07-24 17:13:36 +0200704
705 return -EINVAL;
706}
707
Yann Gautiere4a3c352019-02-14 10:53:33 +0100708static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200709{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100710 uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
711 uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200712
Yann Gautiere4a3c352019-02-14 10:53:33 +0100713 return stm32mp1_clk_get_fixed(pll->refclk[src]);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200714}
715
716/*
717 * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
718 * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
719 * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1)
720 * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
721 */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100722static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200723{
Yann Gautier9aea69e2018-07-24 17:13:36 +0200724 unsigned long refclk, fvco;
725 uint32_t cfgr1, fracr, divm, divn;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100726 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200727
Yann Gautiere4a3c352019-02-14 10:53:33 +0100728 cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
729 fracr = mmio_read_32(rcc_base + pll->pllxfracr);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200730
731 divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
732 divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
733
Yann Gautiere4a3c352019-02-14 10:53:33 +0100734 refclk = stm32mp1_pll_get_fref(pll);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200735
736 /*
737 * With FRACV :
738 * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
739 * Without FRACV
740 * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
741 */
742 if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100743 uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
744 RCC_PLLNFRACR_FRACV_SHIFT;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200745 unsigned long long numerator, denominator;
746
Yann Gautiere4a3c352019-02-14 10:53:33 +0100747 numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
748 numerator = refclk * numerator;
749 denominator = ((unsigned long long)divm + 1U) << 13;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200750 fvco = (unsigned long)(numerator / denominator);
751 } else {
752 fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
753 }
754
755 return fvco;
756}
757
Yann Gautiere4a3c352019-02-14 10:53:33 +0100758static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200759 enum stm32mp1_div_id div_id)
760{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100761 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200762 unsigned long dfout;
763 uint32_t cfgr2, divy;
764
765 if (div_id >= _DIV_NB) {
766 return 0;
767 }
768
Yann Gautiere4a3c352019-02-14 10:53:33 +0100769 cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200770 divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
771
Yann Gautiere4a3c352019-02-14 10:53:33 +0100772 dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200773
774 return dfout;
775}
776
Yann Gautiere4a3c352019-02-14 10:53:33 +0100777static unsigned long get_clock_rate(int p)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200778{
779 uint32_t reg, clkdiv;
780 unsigned long clock = 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100781 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200782
783 switch (p) {
784 case _CK_MPU:
785 /* MPU sub system */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100786 reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200787 switch (reg & RCC_SELR_SRC_MASK) {
788 case RCC_MPCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100789 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200790 break;
791 case RCC_MPCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100792 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200793 break;
794 case RCC_MPCKSELR_PLL:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100795 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200796 break;
797 case RCC_MPCKSELR_PLL_MPUDIV:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100798 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200799
Yann Gautiere4a3c352019-02-14 10:53:33 +0100800 reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200801 clkdiv = reg & RCC_MPUDIV_MASK;
802 if (clkdiv != 0U) {
803 clock /= stm32mp1_mpu_div[clkdiv];
804 }
Yann Gautier9aea69e2018-07-24 17:13:36 +0200805 break;
806 default:
807 break;
808 }
809 break;
810 /* AXI sub system */
811 case _ACLK:
812 case _HCLK2:
813 case _HCLK6:
814 case _PCLK4:
815 case _PCLK5:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100816 reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200817 switch (reg & RCC_SELR_SRC_MASK) {
818 case RCC_ASSCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100819 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200820 break;
821 case RCC_ASSCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100822 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200823 break;
824 case RCC_ASSCKSELR_PLL:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100825 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200826 break;
827 default:
828 break;
829 }
830
831 /* System clock divider */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100832 reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200833 clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
834
835 switch (p) {
836 case _PCLK4:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100837 reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200838 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
839 break;
840 case _PCLK5:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100841 reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200842 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
843 break;
844 default:
845 break;
846 }
847 break;
Yann Gautiered342322019-02-15 17:33:27 +0100848 /* MCU sub system */
849 case _CK_MCU:
850 case _PCLK1:
851 case _PCLK2:
852 case _PCLK3:
853 reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
854 switch (reg & RCC_SELR_SRC_MASK) {
855 case RCC_MSSCKSELR_HSI:
856 clock = stm32mp1_clk_get_fixed(_HSI);
857 break;
858 case RCC_MSSCKSELR_HSE:
859 clock = stm32mp1_clk_get_fixed(_HSE);
860 break;
861 case RCC_MSSCKSELR_CSI:
862 clock = stm32mp1_clk_get_fixed(_CSI);
863 break;
864 case RCC_MSSCKSELR_PLL:
865 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
866 break;
867 default:
868 break;
869 }
870
871 /* MCU clock divider */
872 reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
873 clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
874
875 switch (p) {
876 case _PCLK1:
877 reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
878 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
879 break;
880 case _PCLK2:
881 reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
882 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
883 break;
884 case _PCLK3:
885 reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
886 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
887 break;
888 case _CK_MCU:
889 default:
890 break;
891 }
892 break;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200893 case _CK_PER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100894 reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200895 switch (reg & RCC_SELR_SRC_MASK) {
896 case RCC_CPERCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100897 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200898 break;
899 case RCC_CPERCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100900 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200901 break;
902 case RCC_CPERCKSELR_CSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100903 clock = stm32mp1_clk_get_fixed(_CSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200904 break;
905 default:
906 break;
907 }
908 break;
909 case _HSI:
910 case _HSI_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100911 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200912 break;
913 case _CSI:
914 case _CSI_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100915 clock = stm32mp1_clk_get_fixed(_CSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200916 break;
917 case _HSE:
918 case _HSE_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100919 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200920 break;
921 case _HSE_KER_DIV2:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100922 clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200923 break;
924 case _LSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100925 clock = stm32mp1_clk_get_fixed(_LSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200926 break;
927 case _LSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100928 clock = stm32mp1_clk_get_fixed(_LSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200929 break;
930 /* PLL */
931 case _PLL1_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100932 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200933 break;
934 case _PLL1_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100935 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200936 break;
937 case _PLL1_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100938 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200939 break;
940 case _PLL2_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100941 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200942 break;
943 case _PLL2_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100944 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200945 break;
946 case _PLL2_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100947 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200948 break;
949 case _PLL3_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100950 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200951 break;
952 case _PLL3_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100953 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200954 break;
955 case _PLL3_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100956 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200957 break;
958 case _PLL4_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100959 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200960 break;
961 case _PLL4_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100962 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200963 break;
964 case _PLL4_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100965 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200966 break;
967 /* Other */
968 case _USB_PHY_48:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100969 clock = USB_PHY_48_MHZ;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200970 break;
971 default:
972 break;
973 }
974
975 return clock;
976}
977
Yann Gautiere4a3c352019-02-14 10:53:33 +0100978static void __clk_enable(struct stm32mp1_clk_gate const *gate)
979{
980 uintptr_t rcc_base = stm32mp_rcc_base();
981
982 if (gate->set_clr != 0U) {
983 mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
984 } else {
985 mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
986 }
987
988 VERBOSE("Clock %d has been enabled", gate->index);
989}
990
991static void __clk_disable(struct stm32mp1_clk_gate const *gate)
992{
993 uintptr_t rcc_base = stm32mp_rcc_base();
994
995 if (gate->set_clr != 0U) {
996 mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
997 BIT(gate->bit));
998 } else {
999 mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
1000 }
1001
1002 VERBOSE("Clock %d has been disabled", gate->index);
1003}
1004
1005static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
1006{
1007 uintptr_t rcc_base = stm32mp_rcc_base();
1008
1009 return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
1010}
1011
1012unsigned int stm32mp1_clk_get_refcount(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001013{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001014 int i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001015
1016 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001017 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001018 }
1019
Yann Gautiere4a3c352019-02-14 10:53:33 +01001020 return gate_refcounts[i];
Yann Gautier9aea69e2018-07-24 17:13:36 +02001021}
1022
Yann Gautiere4a3c352019-02-14 10:53:33 +01001023void __stm32mp1_clk_enable(unsigned long id, bool secure)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001024{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001025 const struct stm32mp1_clk_gate *gate;
1026 int i = stm32mp1_clk_get_gated_id(id);
1027 unsigned int *refcnt;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001028
1029 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001030 ERROR("Clock %d can't be enabled\n", (uint32_t)id);
1031 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001032 }
1033
Yann Gautiere4a3c352019-02-14 10:53:33 +01001034 gate = gate_ref(i);
1035 refcnt = &gate_refcounts[i];
1036
1037 stm32mp1_clk_lock(&refcount_lock);
1038
1039 if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) {
1040 __clk_enable(gate);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001041 }
1042
Yann Gautiere4a3c352019-02-14 10:53:33 +01001043 stm32mp1_clk_unlock(&refcount_lock);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001044}
1045
Yann Gautiere4a3c352019-02-14 10:53:33 +01001046void __stm32mp1_clk_disable(unsigned long id, bool secure)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001047{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001048 const struct stm32mp1_clk_gate *gate;
1049 int i = stm32mp1_clk_get_gated_id(id);
1050 unsigned int *refcnt;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001051
1052 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001053 ERROR("Clock %d can't be disabled\n", (uint32_t)id);
1054 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001055 }
1056
Yann Gautiere4a3c352019-02-14 10:53:33 +01001057 gate = gate_ref(i);
1058 refcnt = &gate_refcounts[i];
1059
1060 stm32mp1_clk_lock(&refcount_lock);
1061
1062 if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) {
1063 __clk_disable(gate);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001064 }
1065
Yann Gautiere4a3c352019-02-14 10:53:33 +01001066 stm32mp1_clk_unlock(&refcount_lock);
1067}
1068
1069void stm32mp_clk_enable(unsigned long id)
1070{
1071 __stm32mp1_clk_enable(id, true);
1072}
1073
1074void stm32mp_clk_disable(unsigned long id)
1075{
1076 __stm32mp1_clk_disable(id, true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001077}
1078
Yann Gautiere4a3c352019-02-14 10:53:33 +01001079bool stm32mp_clk_is_enabled(unsigned long id)
1080{
1081 int i = stm32mp1_clk_get_gated_id(id);
1082
1083 if (i < 0) {
1084 panic();
1085 }
1086
1087 return __clk_is_enabled(gate_ref(i));
1088}
1089
Yann Gautiera2e2a302019-02-14 11:13:39 +01001090unsigned long stm32mp_clk_get_rate(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001091{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001092 int p = stm32mp1_clk_get_parent(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001093
1094 if (p < 0) {
1095 return 0;
1096 }
1097
Yann Gautiere4a3c352019-02-14 10:53:33 +01001098 return get_clock_rate(p);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001099}
1100
Yann Gautiere4a3c352019-02-14 10:53:33 +01001101static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001102{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001103 uintptr_t address = stm32mp_rcc_base() + offset;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001104
Yann Gautiere4a3c352019-02-14 10:53:33 +01001105 if (enable) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001106 mmio_setbits_32(address, mask_on);
1107 } else {
1108 mmio_clrbits_32(address, mask_on);
1109 }
1110}
1111
Yann Gautiere4a3c352019-02-14 10:53:33 +01001112static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001113{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001114 uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
1115 uintptr_t address = stm32mp_rcc_base() + offset;
1116
1117 mmio_write_32(address, mask_on);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001118}
1119
Yann Gautiere4a3c352019-02-14 10:53:33 +01001120static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001121{
Yann Gautier2299d572019-02-14 11:14:39 +01001122 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001123 uint32_t mask_test;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001124 uintptr_t address = stm32mp_rcc_base() + offset;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001125
Yann Gautiere4a3c352019-02-14 10:53:33 +01001126 if (enable) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001127 mask_test = mask_rdy;
1128 } else {
1129 mask_test = 0;
1130 }
1131
Yann Gautier2299d572019-02-14 11:14:39 +01001132 timeout = timeout_init_us(OSCRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001133 while ((mmio_read_32(address) & mask_rdy) != mask_test) {
Yann Gautier2299d572019-02-14 11:14:39 +01001134 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001135 ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001136 mask_rdy, address, enable, mmio_read_32(address));
1137 return -ETIMEDOUT;
1138 }
1139 }
1140
1141 return 0;
1142}
1143
Yann Gautiere4a3c352019-02-14 10:53:33 +01001144static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001145{
1146 uint32_t value;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001147 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001148
Yann Gautiere4a3c352019-02-14 10:53:33 +01001149 if (digbyp) {
1150 mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001151 }
1152
Yann Gautiere4a3c352019-02-14 10:53:33 +01001153 if (bypass || digbyp) {
1154 mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
1155 }
1156
Yann Gautier9aea69e2018-07-24 17:13:36 +02001157 /*
1158 * Warning: not recommended to switch directly from "high drive"
1159 * to "medium low drive", and vice-versa.
1160 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001161 value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
Yann Gautier9aea69e2018-07-24 17:13:36 +02001162 RCC_BDCR_LSEDRV_SHIFT;
1163
1164 while (value != lsedrv) {
1165 if (value > lsedrv) {
1166 value--;
1167 } else {
1168 value++;
1169 }
1170
Yann Gautiere4a3c352019-02-14 10:53:33 +01001171 mmio_clrsetbits_32(rcc_base + RCC_BDCR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001172 RCC_BDCR_LSEDRV_MASK,
1173 value << RCC_BDCR_LSEDRV_SHIFT);
1174 }
1175
Yann Gautiere4a3c352019-02-14 10:53:33 +01001176 stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001177}
1178
Yann Gautiere4a3c352019-02-14 10:53:33 +01001179static void stm32mp1_lse_wait(void)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001180{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001181 if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001182 VERBOSE("%s: failed\n", __func__);
1183 }
1184}
1185
Yann Gautiere4a3c352019-02-14 10:53:33 +01001186static void stm32mp1_lsi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001187{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001188 stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
1189
1190 if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001191 VERBOSE("%s: failed\n", __func__);
1192 }
1193}
1194
Yann Gautiere4a3c352019-02-14 10:53:33 +01001195static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001196{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001197 uintptr_t rcc_base = stm32mp_rcc_base();
1198
1199 if (digbyp) {
1200 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001201 }
1202
Yann Gautiere4a3c352019-02-14 10:53:33 +01001203 if (bypass || digbyp) {
1204 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
1205 }
1206
1207 stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
1208 if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001209 VERBOSE("%s: failed\n", __func__);
1210 }
1211
1212 if (css) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001213 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001214 }
1215}
1216
Yann Gautiere4a3c352019-02-14 10:53:33 +01001217static void stm32mp1_csi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001218{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001219 stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
1220 if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001221 VERBOSE("%s: failed\n", __func__);
1222 }
1223}
1224
Yann Gautiere4a3c352019-02-14 10:53:33 +01001225static void stm32mp1_hsi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001226{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001227 stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
1228 if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001229 VERBOSE("%s: failed\n", __func__);
1230 }
1231}
1232
Yann Gautiere4a3c352019-02-14 10:53:33 +01001233static int stm32mp1_set_hsidiv(uint8_t hsidiv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001234{
Yann Gautier2299d572019-02-14 11:14:39 +01001235 uint64_t timeout;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001236 uintptr_t rcc_base = stm32mp_rcc_base();
1237 uintptr_t address = rcc_base + RCC_OCRDYR;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001238
Yann Gautiere4a3c352019-02-14 10:53:33 +01001239 mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001240 RCC_HSICFGR_HSIDIV_MASK,
1241 RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
1242
Yann Gautier2299d572019-02-14 11:14:39 +01001243 timeout = timeout_init_us(HSIDIV_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001244 while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001245 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001246 ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001247 address, mmio_read_32(address));
1248 return -ETIMEDOUT;
1249 }
1250 }
1251
1252 return 0;
1253}
1254
Yann Gautiere4a3c352019-02-14 10:53:33 +01001255static int stm32mp1_hsidiv(unsigned long hsifreq)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001256{
1257 uint8_t hsidiv;
1258 uint32_t hsidivfreq = MAX_HSI_HZ;
1259
1260 for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
1261 if (hsidivfreq == hsifreq) {
1262 break;
1263 }
1264
1265 hsidivfreq /= 2U;
1266 }
1267
1268 if (hsidiv == 4U) {
1269 ERROR("Invalid clk-hsi frequency\n");
1270 return -1;
1271 }
1272
1273 if (hsidiv != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001274 return stm32mp1_set_hsidiv(hsidiv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001275 }
1276
1277 return 0;
1278}
1279
Yann Gautiere4a3c352019-02-14 10:53:33 +01001280static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
1281 unsigned int clksrc,
1282 uint32_t *pllcfg, int plloff)
1283{
1284 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1285 uintptr_t rcc_base = stm32mp_rcc_base();
1286 uintptr_t pllxcr = rcc_base + pll->pllxcr;
1287 enum stm32mp1_plltype type = pll->plltype;
1288 uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
1289 unsigned long refclk;
1290 uint32_t ifrge = 0U;
Andre Przywara2d5690c2020-03-26 11:50:33 +00001291 uint32_t src, value, fracv = 0;
1292 void *fdt;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001293
1294 /* Check PLL output */
1295 if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
1296 return false;
1297 }
1298
1299 /* Check current clksrc */
1300 src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
1301 if (src != (clksrc & RCC_SELR_SRC_MASK)) {
1302 return false;
1303 }
1304
1305 /* Check Div */
1306 src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
1307
1308 refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
1309 (pllcfg[PLLCFG_M] + 1U);
1310
1311 if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
1312 (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
1313 return false;
1314 }
1315
1316 if ((type == PLL_800) && (refclk >= 8000000U)) {
1317 ifrge = 1U;
1318 }
1319
1320 value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
1321 RCC_PLLNCFGR1_DIVN_MASK;
1322 value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
1323 RCC_PLLNCFGR1_DIVM_MASK;
1324 value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
1325 RCC_PLLNCFGR1_IFRGE_MASK;
1326 if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
1327 return false;
1328 }
1329
1330 /* Fractional configuration */
Andre Przywara2d5690c2020-03-26 11:50:33 +00001331 if (fdt_get_address(&fdt) == 1) {
1332 fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1333 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001334
1335 value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
1336 value |= RCC_PLLNFRACR_FRACLE;
1337 if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
1338 return false;
1339 }
1340
1341 /* Output config */
1342 value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
1343 RCC_PLLNCFGR2_DIVP_MASK;
1344 value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
1345 RCC_PLLNCFGR2_DIVQ_MASK;
1346 value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
1347 RCC_PLLNCFGR2_DIVR_MASK;
1348 if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
1349 return false;
1350 }
1351
1352 return true;
1353}
1354
1355static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001356{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001357 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1358 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001359
Yann Gautierd0dcbaa2019-06-04 15:55:37 +02001360 /* Preserve RCC_PLLNCR_SSCG_CTRL value */
1361 mmio_clrsetbits_32(pllxcr,
1362 RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1363 RCC_PLLNCR_DIVREN,
1364 RCC_PLLNCR_PLLON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001365}
1366
Yann Gautiere4a3c352019-02-14 10:53:33 +01001367static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001368{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001369 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1370 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier2299d572019-02-14 11:14:39 +01001371 uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001372
Yann Gautier9aea69e2018-07-24 17:13:36 +02001373 /* Wait PLL lock */
1374 while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001375 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001376 ERROR("PLL%d start failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001377 pll_id, pllxcr, mmio_read_32(pllxcr));
1378 return -ETIMEDOUT;
1379 }
1380 }
1381
1382 /* Start the requested output */
1383 mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
1384
1385 return 0;
1386}
1387
Yann Gautiere4a3c352019-02-14 10:53:33 +01001388static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001389{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001390 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1391 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier2299d572019-02-14 11:14:39 +01001392 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001393
1394 /* Stop all output */
1395 mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1396 RCC_PLLNCR_DIVREN);
1397
1398 /* Stop PLL */
1399 mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
1400
Yann Gautier2299d572019-02-14 11:14:39 +01001401 timeout = timeout_init_us(PLLRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001402 /* Wait PLL stopped */
1403 while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001404 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001405 ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001406 pll_id, pllxcr, mmio_read_32(pllxcr));
1407 return -ETIMEDOUT;
1408 }
1409 }
1410
1411 return 0;
1412}
1413
Yann Gautiere4a3c352019-02-14 10:53:33 +01001414static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001415 uint32_t *pllcfg)
1416{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001417 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1418 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001419 uint32_t value;
1420
1421 value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
1422 RCC_PLLNCFGR2_DIVP_MASK;
1423 value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
1424 RCC_PLLNCFGR2_DIVQ_MASK;
1425 value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
1426 RCC_PLLNCFGR2_DIVR_MASK;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001427 mmio_write_32(rcc_base + pll->pllxcfgr2, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001428}
1429
Yann Gautiere4a3c352019-02-14 10:53:33 +01001430static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001431 uint32_t *pllcfg, uint32_t fracv)
1432{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001433 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1434 uintptr_t rcc_base = stm32mp_rcc_base();
1435 enum stm32mp1_plltype type = pll->plltype;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001436 unsigned long refclk;
1437 uint32_t ifrge = 0;
1438 uint32_t src, value;
1439
Yann Gautiere4a3c352019-02-14 10:53:33 +01001440 src = mmio_read_32(rcc_base + pll->rckxselr) &
Yann Gautier9aea69e2018-07-24 17:13:36 +02001441 RCC_SELR_REFCLK_SRC_MASK;
1442
Yann Gautiere4a3c352019-02-14 10:53:33 +01001443 refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
Yann Gautier9aea69e2018-07-24 17:13:36 +02001444 (pllcfg[PLLCFG_M] + 1U);
1445
1446 if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
1447 (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
1448 return -EINVAL;
1449 }
1450
1451 if ((type == PLL_800) && (refclk >= 8000000U)) {
1452 ifrge = 1U;
1453 }
1454
1455 value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
1456 RCC_PLLNCFGR1_DIVN_MASK;
1457 value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
1458 RCC_PLLNCFGR1_DIVM_MASK;
1459 value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
1460 RCC_PLLNCFGR1_IFRGE_MASK;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001461 mmio_write_32(rcc_base + pll->pllxcfgr1, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001462
1463 /* Fractional configuration */
1464 value = 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001465 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001466
1467 value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001468 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001469
1470 value |= RCC_PLLNFRACR_FRACLE;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001471 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001472
Yann Gautiere4a3c352019-02-14 10:53:33 +01001473 stm32mp1_pll_config_output(pll_id, pllcfg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001474
1475 return 0;
1476}
1477
Yann Gautiere4a3c352019-02-14 10:53:33 +01001478static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001479{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001480 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001481 uint32_t pllxcsg = 0;
1482
1483 pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
1484 RCC_PLLNCSGR_MOD_PER_MASK;
1485
1486 pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
1487 RCC_PLLNCSGR_INC_STEP_MASK;
1488
1489 pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
1490 RCC_PLLNCSGR_SSCG_MODE_MASK;
1491
Yann Gautiere4a3c352019-02-14 10:53:33 +01001492 mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
Yann Gautierd0dcbaa2019-06-04 15:55:37 +02001493
1494 mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
1495 RCC_PLLNCR_SSCG_CTRL);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001496}
1497
Yann Gautiere4a3c352019-02-14 10:53:33 +01001498static int stm32mp1_set_clksrc(unsigned int clksrc)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001499{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001500 uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
Yann Gautier2299d572019-02-14 11:14:39 +01001501 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001502
Yann Gautiere4a3c352019-02-14 10:53:33 +01001503 mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001504 clksrc & RCC_SELR_SRC_MASK);
1505
Yann Gautier2299d572019-02-14 11:14:39 +01001506 timeout = timeout_init_us(CLKSRC_TIMEOUT);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001507 while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001508 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001509 ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
1510 clksrc_address, mmio_read_32(clksrc_address));
Yann Gautier9aea69e2018-07-24 17:13:36 +02001511 return -ETIMEDOUT;
1512 }
1513 }
1514
1515 return 0;
1516}
1517
Yann Gautiere4a3c352019-02-14 10:53:33 +01001518static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001519{
Yann Gautier2299d572019-02-14 11:14:39 +01001520 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001521
1522 mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
1523 clkdiv & RCC_DIVR_DIV_MASK);
1524
Yann Gautier2299d572019-02-14 11:14:39 +01001525 timeout = timeout_init_us(CLKDIV_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001526 while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001527 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001528 ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001529 clkdiv, address, mmio_read_32(address));
1530 return -ETIMEDOUT;
1531 }
1532 }
1533
1534 return 0;
1535}
1536
Yann Gautiere4a3c352019-02-14 10:53:33 +01001537static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001538{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001539 uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001540
1541 /*
1542 * Binding clksrc :
1543 * bit15-4 offset
1544 * bit3: disable
1545 * bit2-0: MCOSEL[2:0]
1546 */
1547 if ((clksrc & 0x8U) != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001548 mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001549 } else {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001550 mmio_clrsetbits_32(clksrc_address,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001551 RCC_MCOCFG_MCOSRC_MASK,
1552 clksrc & RCC_MCOCFG_MCOSRC_MASK);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001553 mmio_clrsetbits_32(clksrc_address,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001554 RCC_MCOCFG_MCODIV_MASK,
1555 clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001556 mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001557 }
1558}
1559
Yann Gautiere4a3c352019-02-14 10:53:33 +01001560static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001561{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001562 uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001563
1564 if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
1565 (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
1566 mmio_clrsetbits_32(address,
1567 RCC_BDCR_RTCSRC_MASK,
1568 clksrc << RCC_BDCR_RTCSRC_SHIFT);
1569
1570 mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
1571 }
1572
1573 if (lse_css) {
1574 mmio_setbits_32(address, RCC_BDCR_LSECSSON);
1575 }
1576}
1577
Yann Gautiere4a3c352019-02-14 10:53:33 +01001578static void stm32mp1_stgen_config(void)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001579{
1580 uintptr_t stgen;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001581 uint32_t cntfid0;
1582 unsigned long rate;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001583 unsigned long long counter;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001584
1585 stgen = fdt_get_stgen_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001586 cntfid0 = mmio_read_32(stgen + CNTFID_OFF);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001587 rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K));
Yann Gautier9aea69e2018-07-24 17:13:36 +02001588
Yann Gautiere4a3c352019-02-14 10:53:33 +01001589 if (cntfid0 == rate) {
1590 return;
1591 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001592
Yann Gautiere4a3c352019-02-14 10:53:33 +01001593 mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
1594 counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF);
1595 counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32;
1596 counter = (counter * rate / cntfid0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001597
Yann Gautiere4a3c352019-02-14 10:53:33 +01001598 mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter);
1599 mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32));
1600 mmio_write_32(stgen + CNTFID_OFF, rate);
1601 mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001602
Yann Gautiere4a3c352019-02-14 10:53:33 +01001603 write_cntfrq((u_register_t)rate);
1604
1605 /* Need to update timer with new frequency */
1606 generic_delay_timer_init();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001607}
1608
1609void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
1610{
1611 uintptr_t stgen;
1612 unsigned long long cnt;
1613
1614 stgen = fdt_get_stgen_base();
1615
1616 cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
1617 mmio_read_32(stgen + CNTCVL_OFF);
1618
1619 cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U;
1620
1621 mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
1622 mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt);
1623 mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(cnt >> 32));
1624 mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
1625}
1626
Yann Gautiere4a3c352019-02-14 10:53:33 +01001627static void stm32mp1_pkcs_config(uint32_t pkcs)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001628{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001629 uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001630 uint32_t value = pkcs & 0xFU;
1631 uint32_t mask = 0xFU;
1632
1633 if ((pkcs & BIT(31)) != 0U) {
1634 mask <<= 4;
1635 value <<= 4;
1636 }
1637
1638 mmio_clrsetbits_32(address, mask, value);
1639}
1640
1641int stm32mp1_clk_init(void)
1642{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001643 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001644 unsigned int clksrc[CLKSRC_NB];
1645 unsigned int clkdiv[CLKDIV_NB];
1646 unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
1647 int plloff[_PLL_NB];
1648 int ret, len;
1649 enum stm32mp1_pll_id i;
1650 bool lse_css = false;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001651 bool pll3_preserve = false;
1652 bool pll4_preserve = false;
1653 bool pll4_bootrom = false;
Yann Gautierf9af3bc2018-11-09 15:57:18 +01001654 const fdt32_t *pkcs_cell;
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001655 void *fdt;
1656
1657 if (fdt_get_address(&fdt) == 0) {
1658 return false;
1659 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001660
1661 /* Check status field to disable security */
1662 if (!fdt_get_rcc_secure_status()) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001663 mmio_write_32(rcc_base + RCC_TZCR, 0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001664 }
1665
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001666 ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
1667 clksrc);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001668 if (ret < 0) {
1669 return -FDT_ERR_NOTFOUND;
1670 }
1671
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001672 ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
1673 clkdiv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001674 if (ret < 0) {
1675 return -FDT_ERR_NOTFOUND;
1676 }
1677
1678 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1679 char name[12];
1680
Antonio Nino Diaz00086e32018-08-16 16:46:06 +01001681 snprintf(name, sizeof(name), "st,pll@%d", i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001682 plloff[i] = fdt_rcc_subnode_offset(name);
1683
1684 if (!fdt_check_node(plloff[i])) {
1685 continue;
1686 }
1687
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001688 ret = fdt_read_uint32_array(fdt, plloff[i], "cfg",
1689 (int)PLLCFG_NB, pllcfg[i]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001690 if (ret < 0) {
1691 return -FDT_ERR_NOTFOUND;
1692 }
1693 }
1694
Yann Gautiere4a3c352019-02-14 10:53:33 +01001695 stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
1696 stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001697
1698 /*
1699 * Switch ON oscillator found in device-tree.
1700 * Note: HSI already ON after BootROM stage.
1701 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001702 if (stm32mp1_osc[_LSI] != 0U) {
1703 stm32mp1_lsi_set(true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001704 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001705 if (stm32mp1_osc[_LSE] != 0U) {
1706 bool bypass, digbyp;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001707 uint32_t lsedrv;
1708
1709 bypass = fdt_osc_read_bool(_LSE, "st,bypass");
Yann Gautiere4a3c352019-02-14 10:53:33 +01001710 digbyp = fdt_osc_read_bool(_LSE, "st,digbypass");
Yann Gautier9aea69e2018-07-24 17:13:36 +02001711 lse_css = fdt_osc_read_bool(_LSE, "st,css");
1712 lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive",
1713 LSEDRV_MEDIUM_HIGH);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001714 stm32mp1_lse_enable(bypass, digbyp, lsedrv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001715 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001716 if (stm32mp1_osc[_HSE] != 0U) {
1717 bool bypass, digbyp, css;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001718
Yann Gautiere4a3c352019-02-14 10:53:33 +01001719 bypass = fdt_osc_read_bool(_HSE, "st,bypass");
1720 digbyp = fdt_osc_read_bool(_HSE, "st,digbypass");
1721 css = fdt_osc_read_bool(_HSE, "st,css");
1722 stm32mp1_hse_enable(bypass, digbyp, css);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001723 }
1724 /*
1725 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
1726 * => switch on CSI even if node is not present in device tree
1727 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001728 stm32mp1_csi_set(true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001729
1730 /* Come back to HSI */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001731 ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001732 if (ret != 0) {
1733 return ret;
1734 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001735 ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001736 if (ret != 0) {
1737 return ret;
1738 }
Yann Gautiered342322019-02-15 17:33:27 +01001739 ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
1740 if (ret != 0) {
1741 return ret;
1742 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001743
Yann Gautiere4a3c352019-02-14 10:53:33 +01001744 if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
1745 RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
1746 pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
1747 clksrc[CLKSRC_PLL3],
1748 pllcfg[_PLL3],
1749 plloff[_PLL3]);
1750 pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
1751 clksrc[CLKSRC_PLL4],
1752 pllcfg[_PLL4],
1753 plloff[_PLL4]);
1754 }
1755
Yann Gautier9aea69e2018-07-24 17:13:36 +02001756 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001757 if (((i == _PLL3) && pll3_preserve) ||
1758 ((i == _PLL4) && pll4_preserve)) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001759 continue;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001760 }
1761
1762 ret = stm32mp1_pll_stop(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001763 if (ret != 0) {
1764 return ret;
1765 }
1766 }
1767
1768 /* Configure HSIDIV */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001769 if (stm32mp1_osc[_HSI] != 0U) {
1770 ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001771 if (ret != 0) {
1772 return ret;
1773 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001774 stm32mp1_stgen_config();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001775 }
1776
1777 /* Select DIV */
1778 /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001779 mmio_write_32(rcc_base + RCC_MPCKDIVR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001780 clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001781 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001782 if (ret != 0) {
1783 return ret;
1784 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001785 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001786 if (ret != 0) {
1787 return ret;
1788 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001789 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001790 if (ret != 0) {
1791 return ret;
1792 }
Yann Gautiered342322019-02-15 17:33:27 +01001793 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
1794 if (ret != 0) {
1795 return ret;
1796 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001797 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001798 if (ret != 0) {
1799 return ret;
1800 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001801 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001802 if (ret != 0) {
1803 return ret;
1804 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001805 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001806 if (ret != 0) {
1807 return ret;
1808 }
1809
1810 /* No ready bit for RTC */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001811 mmio_write_32(rcc_base + RCC_RTCDIVR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001812 clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
1813
1814 /* Configure PLLs source */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001815 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001816 if (ret != 0) {
1817 return ret;
1818 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001819
1820 if (!pll3_preserve) {
1821 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
1822 if (ret != 0) {
1823 return ret;
1824 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001825 }
1826
Yann Gautiere4a3c352019-02-14 10:53:33 +01001827 if (!pll4_preserve) {
1828 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
1829 if (ret != 0) {
1830 return ret;
1831 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001832 }
1833
1834 /* Configure and start PLLs */
1835 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1836 uint32_t fracv;
1837 uint32_t csg[PLLCSG_NB];
1838
Yann Gautiere4a3c352019-02-14 10:53:33 +01001839 if (((i == _PLL3) && pll3_preserve) ||
1840 ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
1841 continue;
1842 }
1843
Yann Gautier9aea69e2018-07-24 17:13:36 +02001844 if (!fdt_check_node(plloff[i])) {
1845 continue;
1846 }
1847
Yann Gautiere4a3c352019-02-14 10:53:33 +01001848 if ((i == _PLL4) && pll4_bootrom) {
1849 /* Set output divider if not done by the Bootrom */
1850 stm32mp1_pll_config_output(i, pllcfg[i]);
1851 continue;
1852 }
1853
Andre Przywara2d5690c2020-03-26 11:50:33 +00001854 fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001855
Yann Gautiere4a3c352019-02-14 10:53:33 +01001856 ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001857 if (ret != 0) {
1858 return ret;
1859 }
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001860 ret = fdt_read_uint32_array(fdt, plloff[i], "csg",
1861 (uint32_t)PLLCSG_NB, csg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001862 if (ret == 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001863 stm32mp1_pll_csg(i, csg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001864 } else if (ret != -FDT_ERR_NOTFOUND) {
1865 return ret;
1866 }
1867
Yann Gautiere4a3c352019-02-14 10:53:33 +01001868 stm32mp1_pll_start(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001869 }
1870 /* Wait and start PLLs ouptut when ready */
1871 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1872 if (!fdt_check_node(plloff[i])) {
1873 continue;
1874 }
1875
Yann Gautiere4a3c352019-02-14 10:53:33 +01001876 ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001877 if (ret != 0) {
1878 return ret;
1879 }
1880 }
1881 /* Wait LSE ready before to use it */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001882 if (stm32mp1_osc[_LSE] != 0U) {
1883 stm32mp1_lse_wait();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001884 }
1885
1886 /* Configure with expected clock source */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001887 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001888 if (ret != 0) {
1889 return ret;
1890 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001891 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001892 if (ret != 0) {
1893 return ret;
1894 }
Yann Gautiered342322019-02-15 17:33:27 +01001895 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
1896 if (ret != 0) {
1897 return ret;
1898 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001899 stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001900
1901 /* Configure PKCK */
1902 pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
1903 if (pkcs_cell != NULL) {
1904 bool ckper_disabled = false;
1905 uint32_t j;
1906
Yann Gautier9aea69e2018-07-24 17:13:36 +02001907 for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
Yann Gautierf9af3bc2018-11-09 15:57:18 +01001908 uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001909
1910 if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
1911 ckper_disabled = true;
1912 continue;
1913 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001914 stm32mp1_pkcs_config(pkcs);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001915 }
1916
1917 /*
1918 * CKPER is source for some peripheral clocks
1919 * (FMC-NAND / QPSI-NOR) and switching source is allowed
1920 * only if previous clock is still ON
1921 * => deactivated CKPER only after switching clock
1922 */
1923 if (ckper_disabled) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001924 stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001925 }
1926 }
1927
1928 /* Switch OFF HSI if not found in device-tree */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001929 if (stm32mp1_osc[_HSI] == 0U) {
1930 stm32mp1_hsi_set(false);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001931 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001932 stm32mp1_stgen_config();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001933
1934 /* Software Self-Refresh mode (SSR) during DDR initilialization */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001935 mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001936 RCC_DDRITFCR_DDRCKMOD_MASK,
1937 RCC_DDRITFCR_DDRCKMOD_SSR <<
1938 RCC_DDRITFCR_DDRCKMOD_SHIFT);
1939
1940 return 0;
1941}
1942
1943static void stm32mp1_osc_clk_init(const char *name,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001944 enum stm32mp_osc_id index)
1945{
1946 uint32_t frequency;
1947
Yann Gautiere4a3c352019-02-14 10:53:33 +01001948 if (fdt_osc_read_freq(name, &frequency) == 0) {
1949 stm32mp1_osc[index] = frequency;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001950 }
1951}
1952
1953static void stm32mp1_osc_init(void)
1954{
Yann Gautier9aea69e2018-07-24 17:13:36 +02001955 enum stm32mp_osc_id i;
1956
1957 for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001958 stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001959 }
1960}
1961
Yann Gautierc7f9e962019-05-20 14:39:26 +02001962static void sync_earlyboot_clocks_state(void)
1963{
1964 if (!stm32mp_is_single_core()) {
1965 stm32mp1_clk_enable_secure(RTCAPB);
1966 }
1967}
1968
Yann Gautier9aea69e2018-07-24 17:13:36 +02001969int stm32mp1_clk_probe(void)
1970{
Yann Gautier9aea69e2018-07-24 17:13:36 +02001971 stm32mp1_osc_init();
1972
Yann Gautierc7f9e962019-05-20 14:39:26 +02001973 sync_earlyboot_clocks_state();
1974
Yann Gautier9aea69e2018-07-24 17:13:36 +02001975 return 0;
1976}