blob: c9bb9ff2b642773fec936fec5b31a81093b91546 [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>
19#include <drivers/delay_timer.h>
20#include <drivers/generic_delay_timer.h>
Yann Gautier4d429472019-02-14 11:15:20 +010021#include <drivers/st/stm32mp_clkfunc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000022#include <drivers/st/stm32mp1_clk.h>
23#include <drivers/st/stm32mp1_clkfunc.h>
24#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
43enum stm32mp1_parent_id {
44/* Oscillators are defined in enum stm32mp_osc_id */
45
46/* Other parent source */
47 _HSI_KER = NB_OSC,
48 _HSE_KER,
49 _HSE_KER_DIV2,
50 _CSI_KER,
51 _PLL1_P,
52 _PLL1_Q,
53 _PLL1_R,
54 _PLL2_P,
55 _PLL2_Q,
56 _PLL2_R,
57 _PLL3_P,
58 _PLL3_Q,
59 _PLL3_R,
60 _PLL4_P,
61 _PLL4_Q,
62 _PLL4_R,
63 _ACLK,
64 _PCLK1,
65 _PCLK2,
66 _PCLK3,
67 _PCLK4,
68 _PCLK5,
69 _HCLK6,
70 _HCLK2,
71 _CK_PER,
72 _CK_MPU,
Yann Gautiere4a3c352019-02-14 10:53:33 +010073 _USB_PHY_48,
Yann Gautier9aea69e2018-07-24 17:13:36 +020074 _PARENT_NB,
75 _UNKNOWN_ID = 0xff,
76};
77
Yann Gautiere4a3c352019-02-14 10:53:33 +010078/* Lists only the parent clock we are interested in */
Yann Gautier9aea69e2018-07-24 17:13:36 +020079enum stm32mp1_parent_sel {
Yann Gautiere4a3c352019-02-14 10:53:33 +010080 _I2C12_SEL,
81 _I2C35_SEL,
82 _STGEN_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020083 _I2C46_SEL,
Yann Gautiere4a3c352019-02-14 10:53:33 +010084 _SPI6_SEL,
85 _USART1_SEL,
86 _RNG1_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020087 _UART6_SEL,
88 _UART24_SEL,
89 _UART35_SEL,
90 _UART78_SEL,
91 _SDMMC12_SEL,
92 _SDMMC3_SEL,
93 _QSPI_SEL,
94 _FMC_SEL,
Yann Gautiere4a3c352019-02-14 10:53:33 +010095 _ASS_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020096 _USBPHY_SEL,
97 _USBO_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020098 _PARENT_SEL_NB,
99 _UNKNOWN_SEL = 0xff,
100};
101
102enum stm32mp1_pll_id {
103 _PLL1,
104 _PLL2,
105 _PLL3,
106 _PLL4,
107 _PLL_NB
108};
109
110enum stm32mp1_div_id {
111 _DIV_P,
112 _DIV_Q,
113 _DIV_R,
114 _DIV_NB,
115};
116
117enum stm32mp1_clksrc_id {
118 CLKSRC_MPU,
119 CLKSRC_AXI,
120 CLKSRC_PLL12,
121 CLKSRC_PLL3,
122 CLKSRC_PLL4,
123 CLKSRC_RTC,
124 CLKSRC_MCO1,
125 CLKSRC_MCO2,
126 CLKSRC_NB
127};
128
129enum stm32mp1_clkdiv_id {
130 CLKDIV_MPU,
131 CLKDIV_AXI,
132 CLKDIV_APB1,
133 CLKDIV_APB2,
134 CLKDIV_APB3,
135 CLKDIV_APB4,
136 CLKDIV_APB5,
137 CLKDIV_RTC,
138 CLKDIV_MCO1,
139 CLKDIV_MCO2,
140 CLKDIV_NB
141};
142
143enum stm32mp1_pllcfg {
144 PLLCFG_M,
145 PLLCFG_N,
146 PLLCFG_P,
147 PLLCFG_Q,
148 PLLCFG_R,
149 PLLCFG_O,
150 PLLCFG_NB
151};
152
153enum stm32mp1_pllcsg {
154 PLLCSG_MOD_PER,
155 PLLCSG_INC_STEP,
156 PLLCSG_SSCG_MODE,
157 PLLCSG_NB
158};
159
160enum stm32mp1_plltype {
161 PLL_800,
162 PLL_1600,
163 PLL_TYPE_NB
164};
165
166struct stm32mp1_pll {
167 uint8_t refclk_min;
168 uint8_t refclk_max;
169 uint8_t divn_max;
170};
171
172struct stm32mp1_clk_gate {
173 uint16_t offset;
174 uint8_t bit;
175 uint8_t index;
176 uint8_t set_clr;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100177 uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
178 uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
Yann Gautier9aea69e2018-07-24 17:13:36 +0200179};
180
181struct stm32mp1_clk_sel {
182 uint16_t offset;
183 uint8_t src;
184 uint8_t msk;
185 uint8_t nb_parent;
186 const uint8_t *parent;
187};
188
189#define REFCLK_SIZE 4
190struct stm32mp1_clk_pll {
191 enum stm32mp1_plltype plltype;
192 uint16_t rckxselr;
193 uint16_t pllxcfgr1;
194 uint16_t pllxcfgr2;
195 uint16_t pllxfracr;
196 uint16_t pllxcr;
197 uint16_t pllxcsgr;
198 enum stm32mp_osc_id refclk[REFCLK_SIZE];
199};
200
Yann Gautiere4a3c352019-02-14 10:53:33 +0100201/* Clocks with selectable source and non set/clr register access */
202#define _CLK_SELEC(off, b, idx, s) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200203 { \
204 .offset = (off), \
205 .bit = (b), \
206 .index = (idx), \
207 .set_clr = 0, \
208 .sel = (s), \
209 .fixed = _UNKNOWN_ID, \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200210 }
211
Yann Gautiere4a3c352019-02-14 10:53:33 +0100212/* Clocks with fixed source and non set/clr register access */
213#define _CLK_FIXED(off, b, idx, f) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200214 { \
215 .offset = (off), \
216 .bit = (b), \
217 .index = (idx), \
218 .set_clr = 0, \
219 .sel = _UNKNOWN_SEL, \
220 .fixed = (f), \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200221 }
222
Yann Gautiere4a3c352019-02-14 10:53:33 +0100223/* Clocks with selectable source and set/clr register access */
224#define _CLK_SC_SELEC(off, b, idx, s) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200225 { \
226 .offset = (off), \
227 .bit = (b), \
228 .index = (idx), \
229 .set_clr = 1, \
230 .sel = (s), \
231 .fixed = _UNKNOWN_ID, \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200232 }
233
Yann Gautiere4a3c352019-02-14 10:53:33 +0100234/* Clocks with fixed source and set/clr register access */
235#define _CLK_SC_FIXED(off, b, idx, f) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200236 { \
237 .offset = (off), \
238 .bit = (b), \
239 .index = (idx), \
240 .set_clr = 1, \
241 .sel = _UNKNOWN_SEL, \
242 .fixed = (f), \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200243 }
244
Yann Gautiere4a3c352019-02-14 10:53:33 +0100245#define _CLK_PARENT(idx, off, s, m, p) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200246 [(idx)] = { \
247 .offset = (off), \
248 .src = (s), \
249 .msk = (m), \
250 .parent = (p), \
Yann Gautiere4a3c352019-02-14 10:53:33 +0100251 .nb_parent = ARRAY_SIZE(p) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200252 }
253
Yann Gautiere4a3c352019-02-14 10:53:33 +0100254#define _CLK_PLL(idx, type, off1, off2, off3, \
255 off4, off5, off6, \
256 p1, p2, p3, p4) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200257 [(idx)] = { \
258 .plltype = (type), \
259 .rckxselr = (off1), \
260 .pllxcfgr1 = (off2), \
261 .pllxcfgr2 = (off3), \
262 .pllxfracr = (off4), \
263 .pllxcr = (off5), \
264 .pllxcsgr = (off6), \
265 .refclk[0] = (p1), \
266 .refclk[1] = (p2), \
267 .refclk[2] = (p3), \
268 .refclk[3] = (p4), \
269 }
270
271static const uint8_t stm32mp1_clks[][2] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100272 { CK_PER, _CK_PER },
273 { CK_MPU, _CK_MPU },
274 { CK_AXI, _ACLK },
275 { CK_HSE, _HSE },
276 { CK_CSI, _CSI },
277 { CK_LSI, _LSI },
278 { CK_LSE, _LSE },
279 { CK_HSI, _HSI },
280 { CK_HSE_DIV2, _HSE_KER_DIV2 },
Yann Gautier9aea69e2018-07-24 17:13:36 +0200281};
282
Yann Gautiere4a3c352019-02-14 10:53:33 +0100283#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate)
284
Yann Gautier9aea69e2018-07-24 17:13:36 +0200285static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100286 _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK),
287 _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
288 _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK),
289 _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
290 _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
291 _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
292 _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
293 _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
294 _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK),
295 _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
296 _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
297
298 _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
299 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
300 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
301 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
302 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
303 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
304 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
305 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
306 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
307 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
308 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
309
310 _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
311 _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
312
313 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
314 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
315 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
316
317 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
318 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
319 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
320 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _USART1_SEL),
321 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
322 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
323 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
324 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
325 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
326 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
327 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
328
329 _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
330 _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
331
332 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
333 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
334 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
335 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
336 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
337 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
338 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
339 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
340 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
341 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
342 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
343
344 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
345 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
346 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
347 _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
348 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
349
350 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
351 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
352 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
353 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
354 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
355
356 _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
357};
358
359static const uint8_t i2c12_parents[] = {
360 _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
361};
362
363static const uint8_t i2c35_parents[] = {
364 _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
365};
366
367static const uint8_t stgen_parents[] = {
368 _HSI_KER, _HSE_KER
369};
370
371static const uint8_t i2c46_parents[] = {
372 _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
373};
374
375static const uint8_t spi6_parents[] = {
376 _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
377};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200378
Yann Gautiere4a3c352019-02-14 10:53:33 +0100379static const uint8_t usart1_parents[] = {
380 _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
381};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200382
Yann Gautiere4a3c352019-02-14 10:53:33 +0100383static const uint8_t rng1_parents[] = {
384 _CSI, _PLL4_R, _LSE, _LSI
385};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200386
Yann Gautiere4a3c352019-02-14 10:53:33 +0100387static const uint8_t uart6_parents[] = {
388 _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
389};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200390
Yann Gautiere4a3c352019-02-14 10:53:33 +0100391static const uint8_t uart234578_parents[] = {
392 _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
393};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200394
Yann Gautiere4a3c352019-02-14 10:53:33 +0100395static const uint8_t sdmmc12_parents[] = {
396 _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
397};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200398
Yann Gautiere4a3c352019-02-14 10:53:33 +0100399static const uint8_t sdmmc3_parents[] = {
400 _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
401};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200402
Yann Gautiere4a3c352019-02-14 10:53:33 +0100403static const uint8_t qspi_parents[] = {
404 _ACLK, _PLL3_R, _PLL4_P, _CK_PER
405};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200406
Yann Gautiere4a3c352019-02-14 10:53:33 +0100407static const uint8_t fmc_parents[] = {
408 _ACLK, _PLL3_R, _PLL4_P, _CK_PER
409};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200410
Yann Gautiere4a3c352019-02-14 10:53:33 +0100411static const uint8_t ass_parents[] = {
412 _HSI, _HSE, _PLL2
Yann Gautier9aea69e2018-07-24 17:13:36 +0200413};
414
Yann Gautiere4a3c352019-02-14 10:53:33 +0100415static const uint8_t usbphy_parents[] = {
416 _HSE_KER, _PLL4_R, _HSE_KER_DIV2
417};
418
419static const uint8_t usbo_parents[] = {
420 _PLL4_R, _USB_PHY_48
421};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200422
423static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100424 _CLK_PARENT(_I2C12_SEL, RCC_I2C12CKSELR, 0, 0x7, i2c12_parents),
425 _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents),
426 _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
427 _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents),
428 _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents),
429 _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents),
430 _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents),
431 _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents),
432 _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents),
433 _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents),
434 _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents),
435 _CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7, sdmmc12_parents),
436 _CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7, sdmmc3_parents),
437 _CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents),
438 _CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents),
439 _CLK_PARENT(_ASS_SEL, RCC_ASSCKSELR, 0, 0x3, ass_parents),
440 _CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents),
441 _CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents),
Yann Gautier9aea69e2018-07-24 17:13:36 +0200442};
443
444/* Define characteristic of PLL according type */
445#define DIVN_MIN 24
446static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
447 [PLL_800] = {
448 .refclk_min = 4,
449 .refclk_max = 16,
450 .divn_max = 99,
451 },
452 [PLL_1600] = {
453 .refclk_min = 8,
454 .refclk_max = 16,
455 .divn_max = 199,
456 },
457};
458
459/* PLLNCFGR2 register divider by output */
460static const uint8_t pllncfgr2[_DIV_NB] = {
461 [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
462 [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
Yann Gautiere4a3c352019-02-14 10:53:33 +0100463 [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200464};
465
466static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100467 _CLK_PLL(_PLL1, PLL_1600,
468 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
469 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
470 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
471 _CLK_PLL(_PLL2, PLL_1600,
472 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
473 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
474 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
475 _CLK_PLL(_PLL3, PLL_800,
476 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
477 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
478 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
479 _CLK_PLL(_PLL4, PLL_800,
480 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
481 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
482 _HSI, _HSE, _CSI, _I2S_CKIN),
Yann Gautier9aea69e2018-07-24 17:13:36 +0200483};
484
485/* Prescaler table lookups for clock computation */
486
487/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
488#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
489#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
490static const uint8_t stm32mp1_mpu_apbx_div[8] = {
491 0, 1, 2, 3, 4, 4, 4, 4
492};
493
494/* div = /1 /2 /3 /4 */
495static const uint8_t stm32mp1_axi_div[8] = {
496 1, 2, 3, 4, 4, 4, 4, 4
497};
498
Yann Gautiere4a3c352019-02-14 10:53:33 +0100499/* RCC clock device driver private */
500static unsigned long stm32mp1_osc[NB_OSC];
501static struct spinlock reg_lock;
502static unsigned int gate_refcounts[NB_GATES];
503static struct spinlock refcount_lock;
504
505static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
506{
507 return &stm32mp1_clk_gate[idx];
508}
Yann Gautier9aea69e2018-07-24 17:13:36 +0200509
Yann Gautiere4a3c352019-02-14 10:53:33 +0100510static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
511{
512 return &stm32mp1_clk_sel[idx];
513}
Yann Gautier9aea69e2018-07-24 17:13:36 +0200514
Yann Gautiere4a3c352019-02-14 10:53:33 +0100515static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
516{
517 return &stm32mp1_clk_pll[idx];
518}
519
520static int stm32mp1_lock_available(void)
521{
522 /* The spinlocks are used only when MMU is enabled */
523 return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT);
524}
525
526static void stm32mp1_clk_lock(struct spinlock *lock)
527{
528 if (stm32mp1_lock_available() == 0U) {
529 return;
530 }
531
532 /* Assume interrupts are masked */
533 spin_lock(lock);
534}
535
536static void stm32mp1_clk_unlock(struct spinlock *lock)
537{
538 if (stm32mp1_lock_available() == 0U) {
539 return;
540 }
541
542 spin_unlock(lock);
543}
544
545bool stm32mp1_rcc_is_secure(void)
546{
547 uintptr_t rcc_base = stm32mp_rcc_base();
548
549 return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0;
550}
551
552void stm32mp1_clk_rcc_regs_lock(void)
553{
554 stm32mp1_clk_lock(&reg_lock);
555}
556
557void stm32mp1_clk_rcc_regs_unlock(void)
558{
559 stm32mp1_clk_unlock(&reg_lock);
560}
561
562static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200563{
564 if (idx >= NB_OSC) {
565 return 0;
566 }
567
Yann Gautiere4a3c352019-02-14 10:53:33 +0100568 return stm32mp1_osc[idx];
Yann Gautier9aea69e2018-07-24 17:13:36 +0200569}
570
Yann Gautiere4a3c352019-02-14 10:53:33 +0100571static int stm32mp1_clk_get_gated_id(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200572{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100573 unsigned int i;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200574
Yann Gautiere4a3c352019-02-14 10:53:33 +0100575 for (i = 0U; i < NB_GATES; i++) {
576 if (gate_ref(i)->index == id) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200577 return i;
578 }
579 }
580
581 ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id);
582
583 return -EINVAL;
584}
585
Yann Gautiere4a3c352019-02-14 10:53:33 +0100586static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200587{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100588 return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200589}
590
Yann Gautiere4a3c352019-02-14 10:53:33 +0100591static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200592{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100593 return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200594}
595
Yann Gautiere4a3c352019-02-14 10:53:33 +0100596static int stm32mp1_clk_get_parent(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200597{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100598 const struct stm32mp1_clk_sel *sel;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200599 uint32_t j, p_sel;
600 int i;
601 enum stm32mp1_parent_id p;
602 enum stm32mp1_parent_sel s;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100603 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200604
Yann Gautiere4a3c352019-02-14 10:53:33 +0100605 for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200606 if (stm32mp1_clks[j][0] == id) {
607 return (int)stm32mp1_clks[j][1];
608 }
609 }
610
Yann Gautiere4a3c352019-02-14 10:53:33 +0100611 i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200612 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100613 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200614 }
615
Yann Gautiere4a3c352019-02-14 10:53:33 +0100616 p = stm32mp1_clk_get_fixed_parent(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200617 if (p < _PARENT_NB) {
618 return (int)p;
619 }
620
Yann Gautiere4a3c352019-02-14 10:53:33 +0100621 s = stm32mp1_clk_get_sel(i);
622 if (s == _UNKNOWN_SEL) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200623 return -EINVAL;
624 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100625 if (s >= _PARENT_SEL_NB) {
626 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200627 }
628
Yann Gautiere4a3c352019-02-14 10:53:33 +0100629 sel = clk_sel_ref(s);
630 p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & sel->msk;
631 if (p_sel < sel->nb_parent) {
632 return (int)sel->parent[p_sel];
633 }
Yann Gautier9aea69e2018-07-24 17:13:36 +0200634
635 return -EINVAL;
636}
637
Yann Gautiere4a3c352019-02-14 10:53:33 +0100638static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200639{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100640 uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
641 uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200642
Yann Gautiere4a3c352019-02-14 10:53:33 +0100643 return stm32mp1_clk_get_fixed(pll->refclk[src]);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200644}
645
646/*
647 * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
648 * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
649 * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1)
650 * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
651 */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100652static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200653{
Yann Gautier9aea69e2018-07-24 17:13:36 +0200654 unsigned long refclk, fvco;
655 uint32_t cfgr1, fracr, divm, divn;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100656 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200657
Yann Gautiere4a3c352019-02-14 10:53:33 +0100658 cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
659 fracr = mmio_read_32(rcc_base + pll->pllxfracr);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200660
661 divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
662 divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
663
Yann Gautiere4a3c352019-02-14 10:53:33 +0100664 refclk = stm32mp1_pll_get_fref(pll);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200665
666 /*
667 * With FRACV :
668 * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
669 * Without FRACV
670 * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
671 */
672 if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100673 uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
674 RCC_PLLNFRACR_FRACV_SHIFT;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200675 unsigned long long numerator, denominator;
676
Yann Gautiere4a3c352019-02-14 10:53:33 +0100677 numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
678 numerator = refclk * numerator;
679 denominator = ((unsigned long long)divm + 1U) << 13;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200680 fvco = (unsigned long)(numerator / denominator);
681 } else {
682 fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
683 }
684
685 return fvco;
686}
687
Yann Gautiere4a3c352019-02-14 10:53:33 +0100688static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200689 enum stm32mp1_div_id div_id)
690{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100691 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200692 unsigned long dfout;
693 uint32_t cfgr2, divy;
694
695 if (div_id >= _DIV_NB) {
696 return 0;
697 }
698
Yann Gautiere4a3c352019-02-14 10:53:33 +0100699 cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200700 divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
701
Yann Gautiere4a3c352019-02-14 10:53:33 +0100702 dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200703
704 return dfout;
705}
706
Yann Gautiere4a3c352019-02-14 10:53:33 +0100707static unsigned long get_clock_rate(int p)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200708{
709 uint32_t reg, clkdiv;
710 unsigned long clock = 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100711 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200712
713 switch (p) {
714 case _CK_MPU:
715 /* MPU sub system */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100716 reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200717 switch (reg & RCC_SELR_SRC_MASK) {
718 case RCC_MPCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100719 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200720 break;
721 case RCC_MPCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100722 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200723 break;
724 case RCC_MPCKSELR_PLL:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100725 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200726 break;
727 case RCC_MPCKSELR_PLL_MPUDIV:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100728 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200729
Yann Gautiere4a3c352019-02-14 10:53:33 +0100730 reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200731 clkdiv = reg & RCC_MPUDIV_MASK;
732 if (clkdiv != 0U) {
733 clock /= stm32mp1_mpu_div[clkdiv];
734 }
Yann Gautier9aea69e2018-07-24 17:13:36 +0200735 break;
736 default:
737 break;
738 }
739 break;
740 /* AXI sub system */
741 case _ACLK:
742 case _HCLK2:
743 case _HCLK6:
744 case _PCLK4:
745 case _PCLK5:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100746 reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200747 switch (reg & RCC_SELR_SRC_MASK) {
748 case RCC_ASSCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100749 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200750 break;
751 case RCC_ASSCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100752 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200753 break;
754 case RCC_ASSCKSELR_PLL:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100755 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200756 break;
757 default:
758 break;
759 }
760
761 /* System clock divider */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100762 reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200763 clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
764
765 switch (p) {
766 case _PCLK4:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100767 reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200768 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
769 break;
770 case _PCLK5:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100771 reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200772 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
773 break;
774 default:
775 break;
776 }
777 break;
778 case _CK_PER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100779 reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200780 switch (reg & RCC_SELR_SRC_MASK) {
781 case RCC_CPERCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100782 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200783 break;
784 case RCC_CPERCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100785 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200786 break;
787 case RCC_CPERCKSELR_CSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100788 clock = stm32mp1_clk_get_fixed(_CSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200789 break;
790 default:
791 break;
792 }
793 break;
794 case _HSI:
795 case _HSI_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100796 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200797 break;
798 case _CSI:
799 case _CSI_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100800 clock = stm32mp1_clk_get_fixed(_CSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200801 break;
802 case _HSE:
803 case _HSE_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100804 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200805 break;
806 case _HSE_KER_DIV2:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100807 clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200808 break;
809 case _LSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100810 clock = stm32mp1_clk_get_fixed(_LSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200811 break;
812 case _LSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100813 clock = stm32mp1_clk_get_fixed(_LSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200814 break;
815 /* PLL */
816 case _PLL1_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100817 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200818 break;
819 case _PLL1_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100820 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200821 break;
822 case _PLL1_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100823 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200824 break;
825 case _PLL2_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100826 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200827 break;
828 case _PLL2_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100829 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200830 break;
831 case _PLL2_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100832 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200833 break;
834 case _PLL3_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100835 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200836 break;
837 case _PLL3_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100838 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200839 break;
840 case _PLL3_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100841 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200842 break;
843 case _PLL4_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100844 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200845 break;
846 case _PLL4_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100847 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200848 break;
849 case _PLL4_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100850 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200851 break;
852 /* Other */
853 case _USB_PHY_48:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100854 clock = USB_PHY_48_MHZ;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200855 break;
856 default:
857 break;
858 }
859
860 return clock;
861}
862
Yann Gautiere4a3c352019-02-14 10:53:33 +0100863static void __clk_enable(struct stm32mp1_clk_gate const *gate)
864{
865 uintptr_t rcc_base = stm32mp_rcc_base();
866
867 if (gate->set_clr != 0U) {
868 mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
869 } else {
870 mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
871 }
872
873 VERBOSE("Clock %d has been enabled", gate->index);
874}
875
876static void __clk_disable(struct stm32mp1_clk_gate const *gate)
877{
878 uintptr_t rcc_base = stm32mp_rcc_base();
879
880 if (gate->set_clr != 0U) {
881 mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
882 BIT(gate->bit));
883 } else {
884 mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
885 }
886
887 VERBOSE("Clock %d has been disabled", gate->index);
888}
889
890static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
891{
892 uintptr_t rcc_base = stm32mp_rcc_base();
893
894 return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
895}
896
897unsigned int stm32mp1_clk_get_refcount(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200898{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100899 int i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200900
901 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100902 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200903 }
904
Yann Gautiere4a3c352019-02-14 10:53:33 +0100905 return gate_refcounts[i];
Yann Gautier9aea69e2018-07-24 17:13:36 +0200906}
907
Yann Gautiere4a3c352019-02-14 10:53:33 +0100908void __stm32mp1_clk_enable(unsigned long id, bool secure)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200909{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100910 const struct stm32mp1_clk_gate *gate;
911 int i = stm32mp1_clk_get_gated_id(id);
912 unsigned int *refcnt;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200913
914 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100915 ERROR("Clock %d can't be enabled\n", (uint32_t)id);
916 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200917 }
918
Yann Gautiere4a3c352019-02-14 10:53:33 +0100919 gate = gate_ref(i);
920 refcnt = &gate_refcounts[i];
921
922 stm32mp1_clk_lock(&refcount_lock);
923
924 if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) {
925 __clk_enable(gate);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200926 }
927
Yann Gautiere4a3c352019-02-14 10:53:33 +0100928 stm32mp1_clk_unlock(&refcount_lock);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200929}
930
Yann Gautiere4a3c352019-02-14 10:53:33 +0100931void __stm32mp1_clk_disable(unsigned long id, bool secure)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200932{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100933 const struct stm32mp1_clk_gate *gate;
934 int i = stm32mp1_clk_get_gated_id(id);
935 unsigned int *refcnt;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200936
937 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100938 ERROR("Clock %d can't be disabled\n", (uint32_t)id);
939 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200940 }
941
Yann Gautiere4a3c352019-02-14 10:53:33 +0100942 gate = gate_ref(i);
943 refcnt = &gate_refcounts[i];
944
945 stm32mp1_clk_lock(&refcount_lock);
946
947 if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) {
948 __clk_disable(gate);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200949 }
950
Yann Gautiere4a3c352019-02-14 10:53:33 +0100951 stm32mp1_clk_unlock(&refcount_lock);
952}
953
954void stm32mp_clk_enable(unsigned long id)
955{
956 __stm32mp1_clk_enable(id, true);
957}
958
959void stm32mp_clk_disable(unsigned long id)
960{
961 __stm32mp1_clk_disable(id, true);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200962}
963
Yann Gautiere4a3c352019-02-14 10:53:33 +0100964bool stm32mp_clk_is_enabled(unsigned long id)
965{
966 int i = stm32mp1_clk_get_gated_id(id);
967
968 if (i < 0) {
969 panic();
970 }
971
972 return __clk_is_enabled(gate_ref(i));
973}
974
Yann Gautiera2e2a302019-02-14 11:13:39 +0100975unsigned long stm32mp_clk_get_rate(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200976{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100977 int p = stm32mp1_clk_get_parent(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200978
979 if (p < 0) {
980 return 0;
981 }
982
Yann Gautiere4a3c352019-02-14 10:53:33 +0100983 return get_clock_rate(p);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200984}
985
Yann Gautiere4a3c352019-02-14 10:53:33 +0100986static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200987{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100988 uintptr_t address = stm32mp_rcc_base() + offset;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200989
Yann Gautiere4a3c352019-02-14 10:53:33 +0100990 if (enable) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200991 mmio_setbits_32(address, mask_on);
992 } else {
993 mmio_clrbits_32(address, mask_on);
994 }
995}
996
Yann Gautiere4a3c352019-02-14 10:53:33 +0100997static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200998{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100999 uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
1000 uintptr_t address = stm32mp_rcc_base() + offset;
1001
1002 mmio_write_32(address, mask_on);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001003}
1004
Yann Gautiere4a3c352019-02-14 10:53:33 +01001005static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001006{
Yann Gautier2299d572019-02-14 11:14:39 +01001007 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001008 uint32_t mask_test;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001009 uintptr_t address = stm32mp_rcc_base() + offset;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001010
Yann Gautiere4a3c352019-02-14 10:53:33 +01001011 if (enable) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001012 mask_test = mask_rdy;
1013 } else {
1014 mask_test = 0;
1015 }
1016
Yann Gautier2299d572019-02-14 11:14:39 +01001017 timeout = timeout_init_us(OSCRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001018 while ((mmio_read_32(address) & mask_rdy) != mask_test) {
Yann Gautier2299d572019-02-14 11:14:39 +01001019 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001020 ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001021 mask_rdy, address, enable, mmio_read_32(address));
1022 return -ETIMEDOUT;
1023 }
1024 }
1025
1026 return 0;
1027}
1028
Yann Gautiere4a3c352019-02-14 10:53:33 +01001029static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001030{
1031 uint32_t value;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001032 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001033
Yann Gautiere4a3c352019-02-14 10:53:33 +01001034 if (digbyp) {
1035 mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001036 }
1037
Yann Gautiere4a3c352019-02-14 10:53:33 +01001038 if (bypass || digbyp) {
1039 mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
1040 }
1041
Yann Gautier9aea69e2018-07-24 17:13:36 +02001042 /*
1043 * Warning: not recommended to switch directly from "high drive"
1044 * to "medium low drive", and vice-versa.
1045 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001046 value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
Yann Gautier9aea69e2018-07-24 17:13:36 +02001047 RCC_BDCR_LSEDRV_SHIFT;
1048
1049 while (value != lsedrv) {
1050 if (value > lsedrv) {
1051 value--;
1052 } else {
1053 value++;
1054 }
1055
Yann Gautiere4a3c352019-02-14 10:53:33 +01001056 mmio_clrsetbits_32(rcc_base + RCC_BDCR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001057 RCC_BDCR_LSEDRV_MASK,
1058 value << RCC_BDCR_LSEDRV_SHIFT);
1059 }
1060
Yann Gautiere4a3c352019-02-14 10:53:33 +01001061 stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001062}
1063
Yann Gautiere4a3c352019-02-14 10:53:33 +01001064static void stm32mp1_lse_wait(void)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001065{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001066 if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001067 VERBOSE("%s: failed\n", __func__);
1068 }
1069}
1070
Yann Gautiere4a3c352019-02-14 10:53:33 +01001071static void stm32mp1_lsi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001072{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001073 stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
1074
1075 if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001076 VERBOSE("%s: failed\n", __func__);
1077 }
1078}
1079
Yann Gautiere4a3c352019-02-14 10:53:33 +01001080static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001081{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001082 uintptr_t rcc_base = stm32mp_rcc_base();
1083
1084 if (digbyp) {
1085 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001086 }
1087
Yann Gautiere4a3c352019-02-14 10:53:33 +01001088 if (bypass || digbyp) {
1089 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
1090 }
1091
1092 stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
1093 if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001094 VERBOSE("%s: failed\n", __func__);
1095 }
1096
1097 if (css) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001098 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001099 }
1100}
1101
Yann Gautiere4a3c352019-02-14 10:53:33 +01001102static void stm32mp1_csi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001103{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001104 stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
1105 if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001106 VERBOSE("%s: failed\n", __func__);
1107 }
1108}
1109
Yann Gautiere4a3c352019-02-14 10:53:33 +01001110static void stm32mp1_hsi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001111{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001112 stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
1113 if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001114 VERBOSE("%s: failed\n", __func__);
1115 }
1116}
1117
Yann Gautiere4a3c352019-02-14 10:53:33 +01001118static int stm32mp1_set_hsidiv(uint8_t hsidiv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001119{
Yann Gautier2299d572019-02-14 11:14:39 +01001120 uint64_t timeout;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001121 uintptr_t rcc_base = stm32mp_rcc_base();
1122 uintptr_t address = rcc_base + RCC_OCRDYR;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001123
Yann Gautiere4a3c352019-02-14 10:53:33 +01001124 mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001125 RCC_HSICFGR_HSIDIV_MASK,
1126 RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
1127
Yann Gautier2299d572019-02-14 11:14:39 +01001128 timeout = timeout_init_us(HSIDIV_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001129 while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001130 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001131 ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001132 address, mmio_read_32(address));
1133 return -ETIMEDOUT;
1134 }
1135 }
1136
1137 return 0;
1138}
1139
Yann Gautiere4a3c352019-02-14 10:53:33 +01001140static int stm32mp1_hsidiv(unsigned long hsifreq)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001141{
1142 uint8_t hsidiv;
1143 uint32_t hsidivfreq = MAX_HSI_HZ;
1144
1145 for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
1146 if (hsidivfreq == hsifreq) {
1147 break;
1148 }
1149
1150 hsidivfreq /= 2U;
1151 }
1152
1153 if (hsidiv == 4U) {
1154 ERROR("Invalid clk-hsi frequency\n");
1155 return -1;
1156 }
1157
1158 if (hsidiv != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001159 return stm32mp1_set_hsidiv(hsidiv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001160 }
1161
1162 return 0;
1163}
1164
Yann Gautiere4a3c352019-02-14 10:53:33 +01001165static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
1166 unsigned int clksrc,
1167 uint32_t *pllcfg, int plloff)
1168{
1169 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1170 uintptr_t rcc_base = stm32mp_rcc_base();
1171 uintptr_t pllxcr = rcc_base + pll->pllxcr;
1172 enum stm32mp1_plltype type = pll->plltype;
1173 uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
1174 unsigned long refclk;
1175 uint32_t ifrge = 0U;
1176 uint32_t src, value, fracv;
1177
1178 /* Check PLL output */
1179 if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
1180 return false;
1181 }
1182
1183 /* Check current clksrc */
1184 src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
1185 if (src != (clksrc & RCC_SELR_SRC_MASK)) {
1186 return false;
1187 }
1188
1189 /* Check Div */
1190 src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
1191
1192 refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
1193 (pllcfg[PLLCFG_M] + 1U);
1194
1195 if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
1196 (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
1197 return false;
1198 }
1199
1200 if ((type == PLL_800) && (refclk >= 8000000U)) {
1201 ifrge = 1U;
1202 }
1203
1204 value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
1205 RCC_PLLNCFGR1_DIVN_MASK;
1206 value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
1207 RCC_PLLNCFGR1_DIVM_MASK;
1208 value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
1209 RCC_PLLNCFGR1_IFRGE_MASK;
1210 if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
1211 return false;
1212 }
1213
1214 /* Fractional configuration */
1215 fracv = fdt_read_uint32_default(plloff, "frac", 0);
1216
1217 value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
1218 value |= RCC_PLLNFRACR_FRACLE;
1219 if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
1220 return false;
1221 }
1222
1223 /* Output config */
1224 value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
1225 RCC_PLLNCFGR2_DIVP_MASK;
1226 value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
1227 RCC_PLLNCFGR2_DIVQ_MASK;
1228 value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
1229 RCC_PLLNCFGR2_DIVR_MASK;
1230 if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
1231 return false;
1232 }
1233
1234 return true;
1235}
1236
1237static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001238{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001239 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1240 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001241
Yann Gautiere4a3c352019-02-14 10:53:33 +01001242 mmio_write_32(pllxcr, RCC_PLLNCR_PLLON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001243}
1244
Yann Gautiere4a3c352019-02-14 10:53:33 +01001245static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001246{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001247 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1248 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier2299d572019-02-14 11:14:39 +01001249 uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001250
Yann Gautier9aea69e2018-07-24 17:13:36 +02001251 /* Wait PLL lock */
1252 while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001253 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001254 ERROR("PLL%d start failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001255 pll_id, pllxcr, mmio_read_32(pllxcr));
1256 return -ETIMEDOUT;
1257 }
1258 }
1259
1260 /* Start the requested output */
1261 mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
1262
1263 return 0;
1264}
1265
Yann Gautiere4a3c352019-02-14 10:53:33 +01001266static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001267{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001268 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1269 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier2299d572019-02-14 11:14:39 +01001270 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001271
1272 /* Stop all output */
1273 mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1274 RCC_PLLNCR_DIVREN);
1275
1276 /* Stop PLL */
1277 mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
1278
Yann Gautier2299d572019-02-14 11:14:39 +01001279 timeout = timeout_init_us(PLLRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001280 /* Wait PLL stopped */
1281 while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001282 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001283 ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001284 pll_id, pllxcr, mmio_read_32(pllxcr));
1285 return -ETIMEDOUT;
1286 }
1287 }
1288
1289 return 0;
1290}
1291
Yann Gautiere4a3c352019-02-14 10:53:33 +01001292static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001293 uint32_t *pllcfg)
1294{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001295 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1296 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001297 uint32_t value;
1298
1299 value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
1300 RCC_PLLNCFGR2_DIVP_MASK;
1301 value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
1302 RCC_PLLNCFGR2_DIVQ_MASK;
1303 value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
1304 RCC_PLLNCFGR2_DIVR_MASK;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001305 mmio_write_32(rcc_base + pll->pllxcfgr2, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001306}
1307
Yann Gautiere4a3c352019-02-14 10:53:33 +01001308static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001309 uint32_t *pllcfg, uint32_t fracv)
1310{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001311 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1312 uintptr_t rcc_base = stm32mp_rcc_base();
1313 enum stm32mp1_plltype type = pll->plltype;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001314 unsigned long refclk;
1315 uint32_t ifrge = 0;
1316 uint32_t src, value;
1317
Yann Gautiere4a3c352019-02-14 10:53:33 +01001318 src = mmio_read_32(rcc_base + pll->rckxselr) &
Yann Gautier9aea69e2018-07-24 17:13:36 +02001319 RCC_SELR_REFCLK_SRC_MASK;
1320
Yann Gautiere4a3c352019-02-14 10:53:33 +01001321 refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
Yann Gautier9aea69e2018-07-24 17:13:36 +02001322 (pllcfg[PLLCFG_M] + 1U);
1323
1324 if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
1325 (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
1326 return -EINVAL;
1327 }
1328
1329 if ((type == PLL_800) && (refclk >= 8000000U)) {
1330 ifrge = 1U;
1331 }
1332
1333 value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
1334 RCC_PLLNCFGR1_DIVN_MASK;
1335 value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
1336 RCC_PLLNCFGR1_DIVM_MASK;
1337 value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
1338 RCC_PLLNCFGR1_IFRGE_MASK;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001339 mmio_write_32(rcc_base + pll->pllxcfgr1, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001340
1341 /* Fractional configuration */
1342 value = 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001343 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001344
1345 value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001346 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001347
1348 value |= RCC_PLLNFRACR_FRACLE;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001349 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001350
Yann Gautiere4a3c352019-02-14 10:53:33 +01001351 stm32mp1_pll_config_output(pll_id, pllcfg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001352
1353 return 0;
1354}
1355
Yann Gautiere4a3c352019-02-14 10:53:33 +01001356static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001357{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001358 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001359 uint32_t pllxcsg = 0;
1360
1361 pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
1362 RCC_PLLNCSGR_MOD_PER_MASK;
1363
1364 pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
1365 RCC_PLLNCSGR_INC_STEP_MASK;
1366
1367 pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
1368 RCC_PLLNCSGR_SSCG_MODE_MASK;
1369
Yann Gautiere4a3c352019-02-14 10:53:33 +01001370 mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001371}
1372
Yann Gautiere4a3c352019-02-14 10:53:33 +01001373static int stm32mp1_set_clksrc(unsigned int clksrc)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001374{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001375 uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
Yann Gautier2299d572019-02-14 11:14:39 +01001376 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001377
Yann Gautiere4a3c352019-02-14 10:53:33 +01001378 mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001379 clksrc & RCC_SELR_SRC_MASK);
1380
Yann Gautier2299d572019-02-14 11:14:39 +01001381 timeout = timeout_init_us(CLKSRC_TIMEOUT);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001382 while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001383 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001384 ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
1385 clksrc_address, mmio_read_32(clksrc_address));
Yann Gautier9aea69e2018-07-24 17:13:36 +02001386 return -ETIMEDOUT;
1387 }
1388 }
1389
1390 return 0;
1391}
1392
Yann Gautiere4a3c352019-02-14 10:53:33 +01001393static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001394{
Yann Gautier2299d572019-02-14 11:14:39 +01001395 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001396
1397 mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
1398 clkdiv & RCC_DIVR_DIV_MASK);
1399
Yann Gautier2299d572019-02-14 11:14:39 +01001400 timeout = timeout_init_us(CLKDIV_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001401 while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001402 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001403 ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001404 clkdiv, address, mmio_read_32(address));
1405 return -ETIMEDOUT;
1406 }
1407 }
1408
1409 return 0;
1410}
1411
Yann Gautiere4a3c352019-02-14 10:53:33 +01001412static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001413{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001414 uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001415
1416 /*
1417 * Binding clksrc :
1418 * bit15-4 offset
1419 * bit3: disable
1420 * bit2-0: MCOSEL[2:0]
1421 */
1422 if ((clksrc & 0x8U) != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001423 mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001424 } else {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001425 mmio_clrsetbits_32(clksrc_address,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001426 RCC_MCOCFG_MCOSRC_MASK,
1427 clksrc & RCC_MCOCFG_MCOSRC_MASK);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001428 mmio_clrsetbits_32(clksrc_address,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001429 RCC_MCOCFG_MCODIV_MASK,
1430 clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001431 mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001432 }
1433}
1434
Yann Gautiere4a3c352019-02-14 10:53:33 +01001435static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001436{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001437 uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001438
1439 if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
1440 (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
1441 mmio_clrsetbits_32(address,
1442 RCC_BDCR_RTCSRC_MASK,
1443 clksrc << RCC_BDCR_RTCSRC_SHIFT);
1444
1445 mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
1446 }
1447
1448 if (lse_css) {
1449 mmio_setbits_32(address, RCC_BDCR_LSECSSON);
1450 }
1451}
1452
1453#define CNTCVL_OFF 0x008
1454#define CNTCVU_OFF 0x00C
1455
Yann Gautiere4a3c352019-02-14 10:53:33 +01001456static void stm32mp1_stgen_config(void)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001457{
1458 uintptr_t stgen;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001459 uint32_t cntfid0;
1460 unsigned long rate;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001461 unsigned long long counter;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001462
1463 stgen = fdt_get_stgen_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001464 cntfid0 = mmio_read_32(stgen + CNTFID_OFF);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001465 rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K));
Yann Gautier9aea69e2018-07-24 17:13:36 +02001466
Yann Gautiere4a3c352019-02-14 10:53:33 +01001467 if (cntfid0 == rate) {
1468 return;
1469 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001470
Yann Gautiere4a3c352019-02-14 10:53:33 +01001471 mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
1472 counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF);
1473 counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32;
1474 counter = (counter * rate / cntfid0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001475
Yann Gautiere4a3c352019-02-14 10:53:33 +01001476 mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter);
1477 mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32));
1478 mmio_write_32(stgen + CNTFID_OFF, rate);
1479 mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001480
Yann Gautiere4a3c352019-02-14 10:53:33 +01001481 write_cntfrq((u_register_t)rate);
1482
1483 /* Need to update timer with new frequency */
1484 generic_delay_timer_init();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001485}
1486
1487void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
1488{
1489 uintptr_t stgen;
1490 unsigned long long cnt;
1491
1492 stgen = fdt_get_stgen_base();
1493
1494 cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
1495 mmio_read_32(stgen + CNTCVL_OFF);
1496
1497 cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U;
1498
1499 mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
1500 mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt);
1501 mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(cnt >> 32));
1502 mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
1503}
1504
Yann Gautiere4a3c352019-02-14 10:53:33 +01001505static void stm32mp1_pkcs_config(uint32_t pkcs)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001506{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001507 uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001508 uint32_t value = pkcs & 0xFU;
1509 uint32_t mask = 0xFU;
1510
1511 if ((pkcs & BIT(31)) != 0U) {
1512 mask <<= 4;
1513 value <<= 4;
1514 }
1515
1516 mmio_clrsetbits_32(address, mask, value);
1517}
1518
1519int stm32mp1_clk_init(void)
1520{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001521 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001522 unsigned int clksrc[CLKSRC_NB];
1523 unsigned int clkdiv[CLKDIV_NB];
1524 unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
1525 int plloff[_PLL_NB];
1526 int ret, len;
1527 enum stm32mp1_pll_id i;
1528 bool lse_css = false;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001529 bool pll3_preserve = false;
1530 bool pll4_preserve = false;
1531 bool pll4_bootrom = false;
Yann Gautierf9af3bc2018-11-09 15:57:18 +01001532 const fdt32_t *pkcs_cell;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001533
1534 /* Check status field to disable security */
1535 if (!fdt_get_rcc_secure_status()) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001536 mmio_write_32(rcc_base + RCC_TZCR, 0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001537 }
1538
1539 ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc,
1540 (uint32_t)CLKSRC_NB);
1541 if (ret < 0) {
1542 return -FDT_ERR_NOTFOUND;
1543 }
1544
1545 ret = fdt_rcc_read_uint32_array("st,clkdiv", clkdiv,
1546 (uint32_t)CLKDIV_NB);
1547 if (ret < 0) {
1548 return -FDT_ERR_NOTFOUND;
1549 }
1550
1551 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1552 char name[12];
1553
Antonio Nino Diaz00086e32018-08-16 16:46:06 +01001554 snprintf(name, sizeof(name), "st,pll@%d", i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001555 plloff[i] = fdt_rcc_subnode_offset(name);
1556
1557 if (!fdt_check_node(plloff[i])) {
1558 continue;
1559 }
1560
1561 ret = fdt_read_uint32_array(plloff[i], "cfg",
1562 pllcfg[i], (int)PLLCFG_NB);
1563 if (ret < 0) {
1564 return -FDT_ERR_NOTFOUND;
1565 }
1566 }
1567
Yann Gautiere4a3c352019-02-14 10:53:33 +01001568 stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
1569 stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001570
1571 /*
1572 * Switch ON oscillator found in device-tree.
1573 * Note: HSI already ON after BootROM stage.
1574 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001575 if (stm32mp1_osc[_LSI] != 0U) {
1576 stm32mp1_lsi_set(true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001577 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001578 if (stm32mp1_osc[_LSE] != 0U) {
1579 bool bypass, digbyp;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001580 uint32_t lsedrv;
1581
1582 bypass = fdt_osc_read_bool(_LSE, "st,bypass");
Yann Gautiere4a3c352019-02-14 10:53:33 +01001583 digbyp = fdt_osc_read_bool(_LSE, "st,digbypass");
Yann Gautier9aea69e2018-07-24 17:13:36 +02001584 lse_css = fdt_osc_read_bool(_LSE, "st,css");
1585 lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive",
1586 LSEDRV_MEDIUM_HIGH);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001587 stm32mp1_lse_enable(bypass, digbyp, lsedrv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001588 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001589 if (stm32mp1_osc[_HSE] != 0U) {
1590 bool bypass, digbyp, css;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001591
Yann Gautiere4a3c352019-02-14 10:53:33 +01001592 bypass = fdt_osc_read_bool(_HSE, "st,bypass");
1593 digbyp = fdt_osc_read_bool(_HSE, "st,digbypass");
1594 css = fdt_osc_read_bool(_HSE, "st,css");
1595 stm32mp1_hse_enable(bypass, digbyp, css);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001596 }
1597 /*
1598 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
1599 * => switch on CSI even if node is not present in device tree
1600 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001601 stm32mp1_csi_set(true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001602
1603 /* Come back to HSI */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001604 ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001605 if (ret != 0) {
1606 return ret;
1607 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001608 ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001609 if (ret != 0) {
1610 return ret;
1611 }
1612
Yann Gautiere4a3c352019-02-14 10:53:33 +01001613 if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
1614 RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
1615 pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
1616 clksrc[CLKSRC_PLL3],
1617 pllcfg[_PLL3],
1618 plloff[_PLL3]);
1619 pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
1620 clksrc[CLKSRC_PLL4],
1621 pllcfg[_PLL4],
1622 plloff[_PLL4]);
1623 }
1624
Yann Gautier9aea69e2018-07-24 17:13:36 +02001625 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001626 if (((i == _PLL3) && pll3_preserve) ||
1627 ((i == _PLL4) && pll4_preserve)) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001628 continue;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001629 }
1630
1631 ret = stm32mp1_pll_stop(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001632 if (ret != 0) {
1633 return ret;
1634 }
1635 }
1636
1637 /* Configure HSIDIV */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001638 if (stm32mp1_osc[_HSI] != 0U) {
1639 ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001640 if (ret != 0) {
1641 return ret;
1642 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001643 stm32mp1_stgen_config();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001644 }
1645
1646 /* Select DIV */
1647 /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001648 mmio_write_32(rcc_base + RCC_MPCKDIVR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001649 clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001650 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001651 if (ret != 0) {
1652 return ret;
1653 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001654 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001655 if (ret != 0) {
1656 return ret;
1657 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001658 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001659 if (ret != 0) {
1660 return ret;
1661 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001662 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001663 if (ret != 0) {
1664 return ret;
1665 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001666 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001667 if (ret != 0) {
1668 return ret;
1669 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001670 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001671 if (ret != 0) {
1672 return ret;
1673 }
1674
1675 /* No ready bit for RTC */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001676 mmio_write_32(rcc_base + RCC_RTCDIVR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001677 clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
1678
1679 /* Configure PLLs source */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001680 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001681 if (ret != 0) {
1682 return ret;
1683 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001684
1685 if (!pll3_preserve) {
1686 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
1687 if (ret != 0) {
1688 return ret;
1689 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001690 }
1691
Yann Gautiere4a3c352019-02-14 10:53:33 +01001692 if (!pll4_preserve) {
1693 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
1694 if (ret != 0) {
1695 return ret;
1696 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001697 }
1698
1699 /* Configure and start PLLs */
1700 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1701 uint32_t fracv;
1702 uint32_t csg[PLLCSG_NB];
1703
Yann Gautiere4a3c352019-02-14 10:53:33 +01001704 if (((i == _PLL3) && pll3_preserve) ||
1705 ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
1706 continue;
1707 }
1708
Yann Gautier9aea69e2018-07-24 17:13:36 +02001709 if (!fdt_check_node(plloff[i])) {
1710 continue;
1711 }
1712
Yann Gautiere4a3c352019-02-14 10:53:33 +01001713 if ((i == _PLL4) && pll4_bootrom) {
1714 /* Set output divider if not done by the Bootrom */
1715 stm32mp1_pll_config_output(i, pllcfg[i]);
1716 continue;
1717 }
1718
Yann Gautier9aea69e2018-07-24 17:13:36 +02001719 fracv = fdt_read_uint32_default(plloff[i], "frac", 0);
1720
Yann Gautiere4a3c352019-02-14 10:53:33 +01001721 ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001722 if (ret != 0) {
1723 return ret;
1724 }
1725 ret = fdt_read_uint32_array(plloff[i], "csg", csg,
1726 (uint32_t)PLLCSG_NB);
1727 if (ret == 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001728 stm32mp1_pll_csg(i, csg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001729 } else if (ret != -FDT_ERR_NOTFOUND) {
1730 return ret;
1731 }
1732
Yann Gautiere4a3c352019-02-14 10:53:33 +01001733 stm32mp1_pll_start(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001734 }
1735 /* Wait and start PLLs ouptut when ready */
1736 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1737 if (!fdt_check_node(plloff[i])) {
1738 continue;
1739 }
1740
Yann Gautiere4a3c352019-02-14 10:53:33 +01001741 ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001742 if (ret != 0) {
1743 return ret;
1744 }
1745 }
1746 /* Wait LSE ready before to use it */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001747 if (stm32mp1_osc[_LSE] != 0U) {
1748 stm32mp1_lse_wait();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001749 }
1750
1751 /* Configure with expected clock source */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001752 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001753 if (ret != 0) {
1754 return ret;
1755 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001756 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001757 if (ret != 0) {
1758 return ret;
1759 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001760 stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001761
1762 /* Configure PKCK */
1763 pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
1764 if (pkcs_cell != NULL) {
1765 bool ckper_disabled = false;
1766 uint32_t j;
1767
Yann Gautier9aea69e2018-07-24 17:13:36 +02001768 for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
Yann Gautierf9af3bc2018-11-09 15:57:18 +01001769 uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001770
1771 if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
1772 ckper_disabled = true;
1773 continue;
1774 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001775 stm32mp1_pkcs_config(pkcs);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001776 }
1777
1778 /*
1779 * CKPER is source for some peripheral clocks
1780 * (FMC-NAND / QPSI-NOR) and switching source is allowed
1781 * only if previous clock is still ON
1782 * => deactivated CKPER only after switching clock
1783 */
1784 if (ckper_disabled) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001785 stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001786 }
1787 }
1788
1789 /* Switch OFF HSI if not found in device-tree */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001790 if (stm32mp1_osc[_HSI] == 0U) {
1791 stm32mp1_hsi_set(false);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001792 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001793 stm32mp1_stgen_config();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001794
1795 /* Software Self-Refresh mode (SSR) during DDR initilialization */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001796 mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001797 RCC_DDRITFCR_DDRCKMOD_MASK,
1798 RCC_DDRITFCR_DDRCKMOD_SSR <<
1799 RCC_DDRITFCR_DDRCKMOD_SHIFT);
1800
1801 return 0;
1802}
1803
1804static void stm32mp1_osc_clk_init(const char *name,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001805 enum stm32mp_osc_id index)
1806{
1807 uint32_t frequency;
1808
Yann Gautiere4a3c352019-02-14 10:53:33 +01001809 if (fdt_osc_read_freq(name, &frequency) == 0) {
1810 stm32mp1_osc[index] = frequency;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001811 }
1812}
1813
1814static void stm32mp1_osc_init(void)
1815{
Yann Gautier9aea69e2018-07-24 17:13:36 +02001816 enum stm32mp_osc_id i;
1817
1818 for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001819 stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001820 }
1821}
1822
1823int stm32mp1_clk_probe(void)
1824{
Yann Gautier9aea69e2018-07-24 17:13:36 +02001825 stm32mp1_osc_init();
1826
1827 return 0;
1828}