blob: 684ab1ab1f71492ce6043b5ff8d2e71ac9d28bae [file] [log] [blame]
Yann Gautier9aea69e2018-07-24 17:13:36 +02001/*
Yann Gautier360e0e92020-09-16 16:40:34 +02002 * Copyright (C) 2018-2021, 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>
Yann Gautiera205a5c2021-08-30 15:06:54 +020020#include <drivers/clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000021#include <drivers/delay_timer.h>
22#include <drivers/generic_delay_timer.h>
Yann Gautier4d429472019-02-14 11:15:20 +010023#include <drivers/st/stm32mp_clkfunc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000024#include <drivers/st/stm32mp1_clk.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000025#include <drivers/st/stm32mp1_rcc.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000026#include <dt-bindings/clock/stm32mp1-clksrc.h>
27#include <lib/mmio.h>
Yann Gautiere4a3c352019-02-14 10:53:33 +010028#include <lib/spinlock.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000029#include <lib/utils_def.h>
30#include <plat/common/platform.h>
31
Yann Gautier2299d572019-02-14 11:14:39 +010032#define MAX_HSI_HZ 64000000
Yann Gautiere4a3c352019-02-14 10:53:33 +010033#define USB_PHY_48_MHZ 48000000
Yann Gautier9aea69e2018-07-24 17:13:36 +020034
Yann Gautier2299d572019-02-14 11:14:39 +010035#define TIMEOUT_US_200MS U(200000)
36#define TIMEOUT_US_1S U(1000000)
Yann Gautier9aea69e2018-07-24 17:13:36 +020037
Yann Gautier2299d572019-02-14 11:14:39 +010038#define PLLRDY_TIMEOUT TIMEOUT_US_200MS
39#define CLKSRC_TIMEOUT TIMEOUT_US_200MS
40#define CLKDIV_TIMEOUT TIMEOUT_US_200MS
41#define HSIDIV_TIMEOUT TIMEOUT_US_200MS
42#define OSCRDY_TIMEOUT TIMEOUT_US_1S
Yann Gautier9aea69e2018-07-24 17:13:36 +020043
Yann Gautier5f2e8742019-05-17 15:57:56 +020044const char *stm32mp_osc_node_label[NB_OSC] = {
45 [_LSI] = "clk-lsi",
46 [_LSE] = "clk-lse",
47 [_HSI] = "clk-hsi",
48 [_HSE] = "clk-hse",
49 [_CSI] = "clk-csi",
50 [_I2S_CKIN] = "i2s_ckin",
51};
52
Yann Gautier9aea69e2018-07-24 17:13:36 +020053enum stm32mp1_parent_id {
54/* Oscillators are defined in enum stm32mp_osc_id */
55
56/* Other parent source */
57 _HSI_KER = NB_OSC,
58 _HSE_KER,
59 _HSE_KER_DIV2,
Gabriel Fernandez4e3a51a2021-07-27 15:39:16 +020060 _HSE_RTC,
Yann Gautier9aea69e2018-07-24 17:13:36 +020061 _CSI_KER,
62 _PLL1_P,
63 _PLL1_Q,
64 _PLL1_R,
65 _PLL2_P,
66 _PLL2_Q,
67 _PLL2_R,
68 _PLL3_P,
69 _PLL3_Q,
70 _PLL3_R,
71 _PLL4_P,
72 _PLL4_Q,
73 _PLL4_R,
74 _ACLK,
75 _PCLK1,
76 _PCLK2,
77 _PCLK3,
78 _PCLK4,
79 _PCLK5,
80 _HCLK6,
81 _HCLK2,
82 _CK_PER,
83 _CK_MPU,
Yann Gautiered342322019-02-15 17:33:27 +010084 _CK_MCU,
Yann Gautiere4a3c352019-02-14 10:53:33 +010085 _USB_PHY_48,
Yann Gautier9aea69e2018-07-24 17:13:36 +020086 _PARENT_NB,
87 _UNKNOWN_ID = 0xff,
88};
89
Yann Gautiere4a3c352019-02-14 10:53:33 +010090/* Lists only the parent clock we are interested in */
Yann Gautier9aea69e2018-07-24 17:13:36 +020091enum stm32mp1_parent_sel {
Yann Gautiere4a3c352019-02-14 10:53:33 +010092 _I2C12_SEL,
93 _I2C35_SEL,
94 _STGEN_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020095 _I2C46_SEL,
Yann Gautiere4a3c352019-02-14 10:53:33 +010096 _SPI6_SEL,
Yann Gautier9d8bbcd2019-05-07 18:49:33 +020097 _UART1_SEL,
Yann Gautiere4a3c352019-02-14 10:53:33 +010098 _RNG1_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +020099 _UART6_SEL,
100 _UART24_SEL,
101 _UART35_SEL,
102 _UART78_SEL,
103 _SDMMC12_SEL,
104 _SDMMC3_SEL,
105 _QSPI_SEL,
106 _FMC_SEL,
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200107 _AXIS_SEL,
108 _MCUS_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200109 _USBPHY_SEL,
110 _USBO_SEL,
Etienne Carriere04132612019-12-08 08:20:12 +0100111 _MPU_SEL,
Yann Gautierfaa9bcf2021-08-31 18:23:13 +0200112 _CKPER_SEL,
Etienne Carrierebccc7d02019-12-08 08:22:31 +0100113 _RTC_SEL,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200114 _PARENT_SEL_NB,
115 _UNKNOWN_SEL = 0xff,
116};
117
Etienne Carriere04132612019-12-08 08:20:12 +0100118/* State the parent clock ID straight related to a clock */
119static const uint8_t parent_id_clock_id[_PARENT_NB] = {
120 [_HSE] = CK_HSE,
121 [_HSI] = CK_HSI,
122 [_CSI] = CK_CSI,
123 [_LSE] = CK_LSE,
124 [_LSI] = CK_LSI,
125 [_I2S_CKIN] = _UNKNOWN_ID,
126 [_USB_PHY_48] = _UNKNOWN_ID,
127 [_HSI_KER] = CK_HSI,
128 [_HSE_KER] = CK_HSE,
129 [_HSE_KER_DIV2] = CK_HSE_DIV2,
Gabriel Fernandez4e3a51a2021-07-27 15:39:16 +0200130 [_HSE_RTC] = _UNKNOWN_ID,
Etienne Carriere04132612019-12-08 08:20:12 +0100131 [_CSI_KER] = CK_CSI,
132 [_PLL1_P] = PLL1_P,
133 [_PLL1_Q] = PLL1_Q,
134 [_PLL1_R] = PLL1_R,
135 [_PLL2_P] = PLL2_P,
136 [_PLL2_Q] = PLL2_Q,
137 [_PLL2_R] = PLL2_R,
138 [_PLL3_P] = PLL3_P,
139 [_PLL3_Q] = PLL3_Q,
140 [_PLL3_R] = PLL3_R,
141 [_PLL4_P] = PLL4_P,
142 [_PLL4_Q] = PLL4_Q,
143 [_PLL4_R] = PLL4_R,
144 [_ACLK] = CK_AXI,
145 [_PCLK1] = CK_AXI,
146 [_PCLK2] = CK_AXI,
147 [_PCLK3] = CK_AXI,
148 [_PCLK4] = CK_AXI,
149 [_PCLK5] = CK_AXI,
150 [_CK_PER] = CK_PER,
151 [_CK_MPU] = CK_MPU,
152 [_CK_MCU] = CK_MCU,
153};
154
155static unsigned int clock_id2parent_id(unsigned long id)
156{
157 unsigned int n;
158
159 for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
160 if (parent_id_clock_id[n] == id) {
161 return n;
162 }
163 }
164
165 return _UNKNOWN_ID;
166}
167
Yann Gautier9aea69e2018-07-24 17:13:36 +0200168enum stm32mp1_pll_id {
169 _PLL1,
170 _PLL2,
171 _PLL3,
172 _PLL4,
173 _PLL_NB
174};
175
176enum stm32mp1_div_id {
177 _DIV_P,
178 _DIV_Q,
179 _DIV_R,
180 _DIV_NB,
181};
182
183enum stm32mp1_clksrc_id {
184 CLKSRC_MPU,
185 CLKSRC_AXI,
Yann Gautiered342322019-02-15 17:33:27 +0100186 CLKSRC_MCU,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200187 CLKSRC_PLL12,
188 CLKSRC_PLL3,
189 CLKSRC_PLL4,
190 CLKSRC_RTC,
191 CLKSRC_MCO1,
192 CLKSRC_MCO2,
193 CLKSRC_NB
194};
195
196enum stm32mp1_clkdiv_id {
197 CLKDIV_MPU,
198 CLKDIV_AXI,
Yann Gautiered342322019-02-15 17:33:27 +0100199 CLKDIV_MCU,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200200 CLKDIV_APB1,
201 CLKDIV_APB2,
202 CLKDIV_APB3,
203 CLKDIV_APB4,
204 CLKDIV_APB5,
205 CLKDIV_RTC,
206 CLKDIV_MCO1,
207 CLKDIV_MCO2,
208 CLKDIV_NB
209};
210
211enum stm32mp1_pllcfg {
212 PLLCFG_M,
213 PLLCFG_N,
214 PLLCFG_P,
215 PLLCFG_Q,
216 PLLCFG_R,
217 PLLCFG_O,
218 PLLCFG_NB
219};
220
221enum stm32mp1_pllcsg {
222 PLLCSG_MOD_PER,
223 PLLCSG_INC_STEP,
224 PLLCSG_SSCG_MODE,
225 PLLCSG_NB
226};
227
228enum stm32mp1_plltype {
229 PLL_800,
230 PLL_1600,
231 PLL_TYPE_NB
232};
233
234struct stm32mp1_pll {
235 uint8_t refclk_min;
236 uint8_t refclk_max;
237 uint8_t divn_max;
238};
239
240struct stm32mp1_clk_gate {
241 uint16_t offset;
242 uint8_t bit;
243 uint8_t index;
244 uint8_t set_clr;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100245 uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
246 uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
Yann Gautier9aea69e2018-07-24 17:13:36 +0200247};
248
249struct stm32mp1_clk_sel {
250 uint16_t offset;
251 uint8_t src;
252 uint8_t msk;
253 uint8_t nb_parent;
254 const uint8_t *parent;
255};
256
257#define REFCLK_SIZE 4
258struct stm32mp1_clk_pll {
259 enum stm32mp1_plltype plltype;
260 uint16_t rckxselr;
261 uint16_t pllxcfgr1;
262 uint16_t pllxcfgr2;
263 uint16_t pllxfracr;
264 uint16_t pllxcr;
265 uint16_t pllxcsgr;
266 enum stm32mp_osc_id refclk[REFCLK_SIZE];
267};
268
Yann Gautiere4a3c352019-02-14 10:53:33 +0100269/* Clocks with selectable source and non set/clr register access */
270#define _CLK_SELEC(off, b, idx, s) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200271 { \
272 .offset = (off), \
273 .bit = (b), \
274 .index = (idx), \
275 .set_clr = 0, \
276 .sel = (s), \
277 .fixed = _UNKNOWN_ID, \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200278 }
279
Yann Gautiere4a3c352019-02-14 10:53:33 +0100280/* Clocks with fixed source and non set/clr register access */
281#define _CLK_FIXED(off, b, idx, f) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200282 { \
283 .offset = (off), \
284 .bit = (b), \
285 .index = (idx), \
286 .set_clr = 0, \
287 .sel = _UNKNOWN_SEL, \
288 .fixed = (f), \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200289 }
290
Yann Gautiere4a3c352019-02-14 10:53:33 +0100291/* Clocks with selectable source and set/clr register access */
292#define _CLK_SC_SELEC(off, b, idx, s) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200293 { \
294 .offset = (off), \
295 .bit = (b), \
296 .index = (idx), \
297 .set_clr = 1, \
298 .sel = (s), \
299 .fixed = _UNKNOWN_ID, \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200300 }
301
Yann Gautiere4a3c352019-02-14 10:53:33 +0100302/* Clocks with fixed source and set/clr register access */
303#define _CLK_SC_FIXED(off, b, idx, f) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200304 { \
305 .offset = (off), \
306 .bit = (b), \
307 .index = (idx), \
308 .set_clr = 1, \
309 .sel = _UNKNOWN_SEL, \
310 .fixed = (f), \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200311 }
312
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200313#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \
314 [_ ## _label ## _SEL] = { \
315 .offset = _rcc_selr, \
316 .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \
Etienne Carrierec164ce22019-12-08 08:20:40 +0100317 .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \
318 (_rcc_selr ## _ ## _label ## SRC_SHIFT), \
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200319 .parent = (_parents), \
320 .nb_parent = ARRAY_SIZE(_parents) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200321 }
322
Yann Gautiere4a3c352019-02-14 10:53:33 +0100323#define _CLK_PLL(idx, type, off1, off2, off3, \
324 off4, off5, off6, \
325 p1, p2, p3, p4) \
Yann Gautier9aea69e2018-07-24 17:13:36 +0200326 [(idx)] = { \
327 .plltype = (type), \
328 .rckxselr = (off1), \
329 .pllxcfgr1 = (off2), \
330 .pllxcfgr2 = (off3), \
331 .pllxfracr = (off4), \
332 .pllxcr = (off5), \
333 .pllxcsgr = (off6), \
334 .refclk[0] = (p1), \
335 .refclk[1] = (p2), \
336 .refclk[2] = (p3), \
337 .refclk[3] = (p4), \
338 }
339
Yann Gautiere4a3c352019-02-14 10:53:33 +0100340#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate)
341
Yann Gautier9aea69e2018-07-24 17:13:36 +0200342static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100343 _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK),
344 _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
345 _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK),
346 _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
347 _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
348 _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
349 _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
350 _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
351 _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK),
352 _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
353 _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
354
355 _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
356 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
357 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
358 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
359 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
360 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
361 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
362 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
363 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
364 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
365 _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
366
367 _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
368 _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
369
Yann Gautier3edc7c32019-05-20 19:17:08 +0200370 _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
371
Yann Gautiere4a3c352019-02-14 10:53:33 +0100372 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
373 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
374 _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
375
376 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
377 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
378 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200379 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
Yann Gautiere4a3c352019-02-14 10:53:33 +0100380 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
381 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
382 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
383 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
384 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
385 _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
386 _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
387
388 _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
389 _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
390
391 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
392 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
393 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
394 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
395 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
396 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
397 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
398 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
399 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
400 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
401 _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
402
403 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
404 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
405 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
406 _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
407 _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
408
409 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
410 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
411 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
412 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
413 _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
414
Etienne Carrierebccc7d02019-12-08 08:22:31 +0100415 _CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL),
Yann Gautiere4a3c352019-02-14 10:53:33 +0100416 _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
417};
418
419static const uint8_t i2c12_parents[] = {
420 _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
421};
422
423static const uint8_t i2c35_parents[] = {
424 _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
425};
426
427static const uint8_t stgen_parents[] = {
428 _HSI_KER, _HSE_KER
429};
430
431static const uint8_t i2c46_parents[] = {
432 _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
433};
434
435static const uint8_t spi6_parents[] = {
436 _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
437};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200438
Yann Gautiere4a3c352019-02-14 10:53:33 +0100439static const uint8_t usart1_parents[] = {
440 _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
441};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200442
Yann Gautiere4a3c352019-02-14 10:53:33 +0100443static const uint8_t rng1_parents[] = {
444 _CSI, _PLL4_R, _LSE, _LSI
445};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200446
Yann Gautiere4a3c352019-02-14 10:53:33 +0100447static const uint8_t uart6_parents[] = {
448 _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
449};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200450
Yann Gautiere4a3c352019-02-14 10:53:33 +0100451static const uint8_t uart234578_parents[] = {
452 _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
453};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200454
Yann Gautiere4a3c352019-02-14 10:53:33 +0100455static const uint8_t sdmmc12_parents[] = {
456 _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
457};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200458
Yann Gautiere4a3c352019-02-14 10:53:33 +0100459static const uint8_t sdmmc3_parents[] = {
460 _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
461};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200462
Yann Gautiere4a3c352019-02-14 10:53:33 +0100463static const uint8_t qspi_parents[] = {
464 _ACLK, _PLL3_R, _PLL4_P, _CK_PER
465};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200466
Yann Gautiere4a3c352019-02-14 10:53:33 +0100467static const uint8_t fmc_parents[] = {
468 _ACLK, _PLL3_R, _PLL4_P, _CK_PER
469};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200470
Etienne Carriere40c28e82019-12-19 10:03:23 +0100471static const uint8_t axiss_parents[] = {
472 _HSI, _HSE, _PLL2_P
Yann Gautier9aea69e2018-07-24 17:13:36 +0200473};
474
Etienne Carriere40c28e82019-12-19 10:03:23 +0100475static const uint8_t mcuss_parents[] = {
476 _HSI, _HSE, _CSI, _PLL3_P
Yann Gautiered342322019-02-15 17:33:27 +0100477};
478
Yann Gautiere4a3c352019-02-14 10:53:33 +0100479static const uint8_t usbphy_parents[] = {
480 _HSE_KER, _PLL4_R, _HSE_KER_DIV2
481};
482
483static const uint8_t usbo_parents[] = {
484 _PLL4_R, _USB_PHY_48
485};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200486
Etienne Carriere04132612019-12-08 08:20:12 +0100487static const uint8_t mpu_parents[] = {
488 _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
489};
490
491static const uint8_t per_parents[] = {
492 _HSI, _HSE, _CSI,
493};
494
Etienne Carrierebccc7d02019-12-08 08:22:31 +0100495static const uint8_t rtc_parents[] = {
Gabriel Fernandez4e3a51a2021-07-27 15:39:16 +0200496 _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
Etienne Carrierebccc7d02019-12-08 08:22:31 +0100497};
498
Yann Gautier9aea69e2018-07-24 17:13:36 +0200499static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200500 _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
501 _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
502 _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
503 _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
504 _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
505 _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
506 _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
Etienne Carriere04132612019-12-08 08:20:12 +0100507 _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
Yann Gautierfaa9bcf2021-08-31 18:23:13 +0200508 _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents),
Etienne Carrierebccc7d02019-12-08 08:22:31 +0100509 _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200510 _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
511 _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
512 _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
513 _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
514 _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
515 _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
516 _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
517 _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
Etienne Carriere40c28e82019-12-19 10:03:23 +0100518 _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents),
519 _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents),
Yann Gautier9d8bbcd2019-05-07 18:49:33 +0200520 _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
521 _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
Yann Gautier9aea69e2018-07-24 17:13:36 +0200522};
523
524/* Define characteristic of PLL according type */
525#define DIVN_MIN 24
526static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
527 [PLL_800] = {
528 .refclk_min = 4,
529 .refclk_max = 16,
530 .divn_max = 99,
531 },
532 [PLL_1600] = {
533 .refclk_min = 8,
534 .refclk_max = 16,
535 .divn_max = 199,
536 },
537};
538
539/* PLLNCFGR2 register divider by output */
540static const uint8_t pllncfgr2[_DIV_NB] = {
541 [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
542 [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
Yann Gautiere4a3c352019-02-14 10:53:33 +0100543 [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200544};
545
546static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100547 _CLK_PLL(_PLL1, PLL_1600,
548 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
549 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
550 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
551 _CLK_PLL(_PLL2, PLL_1600,
552 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
553 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
554 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
555 _CLK_PLL(_PLL3, PLL_800,
556 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
557 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
558 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
559 _CLK_PLL(_PLL4, PLL_800,
560 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
561 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
562 _HSI, _HSE, _CSI, _I2S_CKIN),
Yann Gautier9aea69e2018-07-24 17:13:36 +0200563};
564
565/* Prescaler table lookups for clock computation */
Yann Gautiered342322019-02-15 17:33:27 +0100566/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
567static const uint8_t stm32mp1_mcu_div[16] = {
568 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
569};
Yann Gautier9aea69e2018-07-24 17:13:36 +0200570
571/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
572#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
573#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
574static const uint8_t stm32mp1_mpu_apbx_div[8] = {
575 0, 1, 2, 3, 4, 4, 4, 4
576};
577
578/* div = /1 /2 /3 /4 */
579static const uint8_t stm32mp1_axi_div[8] = {
580 1, 2, 3, 4, 4, 4, 4, 4
581};
582
Etienne Carriere1368ada2020-05-13 11:49:49 +0200583static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
584 [_HSI] = "HSI",
585 [_HSE] = "HSE",
586 [_CSI] = "CSI",
587 [_LSI] = "LSI",
588 [_LSE] = "LSE",
589 [_I2S_CKIN] = "I2S_CKIN",
590 [_HSI_KER] = "HSI_KER",
591 [_HSE_KER] = "HSE_KER",
592 [_HSE_KER_DIV2] = "HSE_KER_DIV2",
Gabriel Fernandez4e3a51a2021-07-27 15:39:16 +0200593 [_HSE_RTC] = "HSE_RTC",
Etienne Carriere1368ada2020-05-13 11:49:49 +0200594 [_CSI_KER] = "CSI_KER",
595 [_PLL1_P] = "PLL1_P",
596 [_PLL1_Q] = "PLL1_Q",
597 [_PLL1_R] = "PLL1_R",
598 [_PLL2_P] = "PLL2_P",
599 [_PLL2_Q] = "PLL2_Q",
600 [_PLL2_R] = "PLL2_R",
601 [_PLL3_P] = "PLL3_P",
602 [_PLL3_Q] = "PLL3_Q",
603 [_PLL3_R] = "PLL3_R",
604 [_PLL4_P] = "PLL4_P",
605 [_PLL4_Q] = "PLL4_Q",
606 [_PLL4_R] = "PLL4_R",
607 [_ACLK] = "ACLK",
608 [_PCLK1] = "PCLK1",
609 [_PCLK2] = "PCLK2",
610 [_PCLK3] = "PCLK3",
611 [_PCLK4] = "PCLK4",
612 [_PCLK5] = "PCLK5",
613 [_HCLK6] = "KCLK6",
614 [_HCLK2] = "HCLK2",
615 [_CK_PER] = "CK_PER",
616 [_CK_MPU] = "CK_MPU",
617 [_CK_MCU] = "CK_MCU",
618 [_USB_PHY_48] = "USB_PHY_48",
619};
620
Yann Gautiere4a3c352019-02-14 10:53:33 +0100621/* RCC clock device driver private */
622static unsigned long stm32mp1_osc[NB_OSC];
623static struct spinlock reg_lock;
624static unsigned int gate_refcounts[NB_GATES];
625static struct spinlock refcount_lock;
626
627static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
628{
629 return &stm32mp1_clk_gate[idx];
630}
Yann Gautier9aea69e2018-07-24 17:13:36 +0200631
Yann Gautiere4a3c352019-02-14 10:53:33 +0100632static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
633{
634 return &stm32mp1_clk_sel[idx];
635}
Yann Gautier9aea69e2018-07-24 17:13:36 +0200636
Yann Gautiere4a3c352019-02-14 10:53:33 +0100637static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
638{
639 return &stm32mp1_clk_pll[idx];
640}
641
Yann Gautiere4a3c352019-02-14 10:53:33 +0100642static void stm32mp1_clk_lock(struct spinlock *lock)
643{
Yann Gautierf540a592019-05-22 19:13:51 +0200644 if (stm32mp_lock_available()) {
645 /* Assume interrupts are masked */
646 spin_lock(lock);
Yann Gautiere4a3c352019-02-14 10:53:33 +0100647 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100648}
649
650static void stm32mp1_clk_unlock(struct spinlock *lock)
651{
Yann Gautierf540a592019-05-22 19:13:51 +0200652 if (stm32mp_lock_available()) {
653 spin_unlock(lock);
Yann Gautiere4a3c352019-02-14 10:53:33 +0100654 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100655}
656
657bool stm32mp1_rcc_is_secure(void)
658{
659 uintptr_t rcc_base = stm32mp_rcc_base();
Etienne Carriere5e68f6b2020-02-05 10:03:27 +0100660 uint32_t mask = RCC_TZCR_TZEN;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100661
Etienne Carriere5e68f6b2020-02-05 10:03:27 +0100662 return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100663}
664
Yann Gautiered342322019-02-15 17:33:27 +0100665bool stm32mp1_rcc_is_mckprot(void)
666{
667 uintptr_t rcc_base = stm32mp_rcc_base();
Etienne Carriere5e68f6b2020-02-05 10:03:27 +0100668 uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT;
Yann Gautiered342322019-02-15 17:33:27 +0100669
Etienne Carriere5e68f6b2020-02-05 10:03:27 +0100670 return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
Yann Gautiered342322019-02-15 17:33:27 +0100671}
672
Yann Gautiere4a3c352019-02-14 10:53:33 +0100673void stm32mp1_clk_rcc_regs_lock(void)
674{
675 stm32mp1_clk_lock(&reg_lock);
676}
677
678void stm32mp1_clk_rcc_regs_unlock(void)
679{
680 stm32mp1_clk_unlock(&reg_lock);
681}
682
683static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200684{
685 if (idx >= NB_OSC) {
686 return 0;
687 }
688
Yann Gautiere4a3c352019-02-14 10:53:33 +0100689 return stm32mp1_osc[idx];
Yann Gautier9aea69e2018-07-24 17:13:36 +0200690}
691
Yann Gautiere4a3c352019-02-14 10:53:33 +0100692static int stm32mp1_clk_get_gated_id(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200693{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100694 unsigned int i;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200695
Yann Gautiere4a3c352019-02-14 10:53:33 +0100696 for (i = 0U; i < NB_GATES; i++) {
697 if (gate_ref(i)->index == id) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200698 return i;
699 }
700 }
701
702 ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id);
703
704 return -EINVAL;
705}
706
Yann Gautiere4a3c352019-02-14 10:53:33 +0100707static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200708{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100709 return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200710}
711
Yann Gautiere4a3c352019-02-14 10:53:33 +0100712static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200713{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100714 return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200715}
716
Yann Gautiere4a3c352019-02-14 10:53:33 +0100717static int stm32mp1_clk_get_parent(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200718{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100719 const struct stm32mp1_clk_sel *sel;
Etienne Carriere04132612019-12-08 08:20:12 +0100720 uint32_t p_sel;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200721 int i;
722 enum stm32mp1_parent_id p;
723 enum stm32mp1_parent_sel s;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100724 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200725
Etienne Carriere04132612019-12-08 08:20:12 +0100726 /* Few non gateable clock have a static parent ID, find them */
727 i = (int)clock_id2parent_id(id);
728 if (i != _UNKNOWN_ID) {
729 return i;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200730 }
731
Yann Gautiere4a3c352019-02-14 10:53:33 +0100732 i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200733 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100734 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200735 }
736
Yann Gautiere4a3c352019-02-14 10:53:33 +0100737 p = stm32mp1_clk_get_fixed_parent(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200738 if (p < _PARENT_NB) {
739 return (int)p;
740 }
741
Yann Gautiere4a3c352019-02-14 10:53:33 +0100742 s = stm32mp1_clk_get_sel(i);
743 if (s == _UNKNOWN_SEL) {
Yann Gautier9aea69e2018-07-24 17:13:36 +0200744 return -EINVAL;
745 }
Yann Gautiere4a3c352019-02-14 10:53:33 +0100746 if (s >= _PARENT_SEL_NB) {
747 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200748 }
749
Yann Gautiere4a3c352019-02-14 10:53:33 +0100750 sel = clk_sel_ref(s);
Etienne Carrierec164ce22019-12-08 08:20:40 +0100751 p_sel = (mmio_read_32(rcc_base + sel->offset) &
752 (sel->msk << sel->src)) >> sel->src;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100753 if (p_sel < sel->nb_parent) {
754 return (int)sel->parent[p_sel];
755 }
Yann Gautier9aea69e2018-07-24 17:13:36 +0200756
757 return -EINVAL;
758}
759
Yann Gautiere4a3c352019-02-14 10:53:33 +0100760static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200761{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100762 uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
763 uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200764
Yann Gautiere4a3c352019-02-14 10:53:33 +0100765 return stm32mp1_clk_get_fixed(pll->refclk[src]);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200766}
767
768/*
769 * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
770 * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
771 * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1)
772 * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
773 */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100774static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200775{
Yann Gautier9aea69e2018-07-24 17:13:36 +0200776 unsigned long refclk, fvco;
777 uint32_t cfgr1, fracr, divm, divn;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100778 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200779
Yann Gautiere4a3c352019-02-14 10:53:33 +0100780 cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
781 fracr = mmio_read_32(rcc_base + pll->pllxfracr);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200782
783 divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
784 divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
785
Yann Gautiere4a3c352019-02-14 10:53:33 +0100786 refclk = stm32mp1_pll_get_fref(pll);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200787
788 /*
789 * With FRACV :
790 * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
791 * Without FRACV
792 * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
793 */
794 if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +0100795 uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
796 RCC_PLLNFRACR_FRACV_SHIFT;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200797 unsigned long long numerator, denominator;
798
Yann Gautiere4a3c352019-02-14 10:53:33 +0100799 numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
800 numerator = refclk * numerator;
801 denominator = ((unsigned long long)divm + 1U) << 13;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200802 fvco = (unsigned long)(numerator / denominator);
803 } else {
804 fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
805 }
806
807 return fvco;
808}
809
Yann Gautiere4a3c352019-02-14 10:53:33 +0100810static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +0200811 enum stm32mp1_div_id div_id)
812{
Yann Gautiere4a3c352019-02-14 10:53:33 +0100813 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200814 unsigned long dfout;
815 uint32_t cfgr2, divy;
816
817 if (div_id >= _DIV_NB) {
818 return 0;
819 }
820
Yann Gautiere4a3c352019-02-14 10:53:33 +0100821 cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200822 divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
823
Yann Gautiere4a3c352019-02-14 10:53:33 +0100824 dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200825
826 return dfout;
827}
828
Yann Gautiere4a3c352019-02-14 10:53:33 +0100829static unsigned long get_clock_rate(int p)
Yann Gautier9aea69e2018-07-24 17:13:36 +0200830{
831 uint32_t reg, clkdiv;
832 unsigned long clock = 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +0100833 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +0200834
835 switch (p) {
836 case _CK_MPU:
837 /* MPU sub system */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100838 reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200839 switch (reg & RCC_SELR_SRC_MASK) {
840 case RCC_MPCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100841 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200842 break;
843 case RCC_MPCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100844 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200845 break;
846 case RCC_MPCKSELR_PLL:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100847 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200848 break;
849 case RCC_MPCKSELR_PLL_MPUDIV:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100850 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200851
Yann Gautiere4a3c352019-02-14 10:53:33 +0100852 reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200853 clkdiv = reg & RCC_MPUDIV_MASK;
Gabriel Fernandez4d198742020-02-28 09:09:06 +0100854 clock >>= stm32mp1_mpu_div[clkdiv];
Yann Gautier9aea69e2018-07-24 17:13:36 +0200855 break;
856 default:
857 break;
858 }
859 break;
860 /* AXI sub system */
861 case _ACLK:
862 case _HCLK2:
863 case _HCLK6:
864 case _PCLK4:
865 case _PCLK5:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100866 reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200867 switch (reg & RCC_SELR_SRC_MASK) {
868 case RCC_ASSCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100869 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200870 break;
871 case RCC_ASSCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100872 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200873 break;
874 case RCC_ASSCKSELR_PLL:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100875 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200876 break;
877 default:
878 break;
879 }
880
881 /* System clock divider */
Yann Gautiere4a3c352019-02-14 10:53:33 +0100882 reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200883 clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
884
885 switch (p) {
886 case _PCLK4:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100887 reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200888 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
889 break;
890 case _PCLK5:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100891 reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200892 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
893 break;
894 default:
895 break;
896 }
897 break;
Yann Gautiered342322019-02-15 17:33:27 +0100898 /* MCU sub system */
899 case _CK_MCU:
900 case _PCLK1:
901 case _PCLK2:
902 case _PCLK3:
903 reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
904 switch (reg & RCC_SELR_SRC_MASK) {
905 case RCC_MSSCKSELR_HSI:
906 clock = stm32mp1_clk_get_fixed(_HSI);
907 break;
908 case RCC_MSSCKSELR_HSE:
909 clock = stm32mp1_clk_get_fixed(_HSE);
910 break;
911 case RCC_MSSCKSELR_CSI:
912 clock = stm32mp1_clk_get_fixed(_CSI);
913 break;
914 case RCC_MSSCKSELR_PLL:
915 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
916 break;
917 default:
918 break;
919 }
920
921 /* MCU clock divider */
922 reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
923 clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
924
925 switch (p) {
926 case _PCLK1:
927 reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
928 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
929 break;
930 case _PCLK2:
931 reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
932 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
933 break;
934 case _PCLK3:
935 reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
936 clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
937 break;
938 case _CK_MCU:
939 default:
940 break;
941 }
942 break;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200943 case _CK_PER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100944 reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200945 switch (reg & RCC_SELR_SRC_MASK) {
946 case RCC_CPERCKSELR_HSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100947 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200948 break;
949 case RCC_CPERCKSELR_HSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100950 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200951 break;
952 case RCC_CPERCKSELR_CSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100953 clock = stm32mp1_clk_get_fixed(_CSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200954 break;
955 default:
956 break;
957 }
958 break;
959 case _HSI:
960 case _HSI_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100961 clock = stm32mp1_clk_get_fixed(_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200962 break;
963 case _CSI:
964 case _CSI_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100965 clock = stm32mp1_clk_get_fixed(_CSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200966 break;
967 case _HSE:
968 case _HSE_KER:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100969 clock = stm32mp1_clk_get_fixed(_HSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200970 break;
971 case _HSE_KER_DIV2:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100972 clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200973 break;
Gabriel Fernandez4e3a51a2021-07-27 15:39:16 +0200974 case _HSE_RTC:
975 clock = stm32mp1_clk_get_fixed(_HSE);
976 clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
977 break;
Yann Gautier9aea69e2018-07-24 17:13:36 +0200978 case _LSI:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100979 clock = stm32mp1_clk_get_fixed(_LSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200980 break;
981 case _LSE:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100982 clock = stm32mp1_clk_get_fixed(_LSE);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200983 break;
984 /* PLL */
985 case _PLL1_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100986 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200987 break;
988 case _PLL1_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100989 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200990 break;
991 case _PLL1_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100992 clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200993 break;
994 case _PLL2_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100995 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200996 break;
997 case _PLL2_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +0100998 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +0200999 break;
1000 case _PLL2_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001001 clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001002 break;
1003 case _PLL3_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001004 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001005 break;
1006 case _PLL3_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001007 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001008 break;
1009 case _PLL3_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001010 clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001011 break;
1012 case _PLL4_P:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001013 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001014 break;
1015 case _PLL4_Q:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001016 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001017 break;
1018 case _PLL4_R:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001019 clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001020 break;
1021 /* Other */
1022 case _USB_PHY_48:
Yann Gautiere4a3c352019-02-14 10:53:33 +01001023 clock = USB_PHY_48_MHZ;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001024 break;
1025 default:
1026 break;
1027 }
1028
1029 return clock;
1030}
1031
Yann Gautiere4a3c352019-02-14 10:53:33 +01001032static void __clk_enable(struct stm32mp1_clk_gate const *gate)
1033{
1034 uintptr_t rcc_base = stm32mp_rcc_base();
1035
Etienne Carriere8a668892019-12-08 08:21:08 +01001036 VERBOSE("Enable clock %u\n", gate->index);
1037
Yann Gautiere4a3c352019-02-14 10:53:33 +01001038 if (gate->set_clr != 0U) {
1039 mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
1040 } else {
1041 mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
1042 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001043}
1044
1045static void __clk_disable(struct stm32mp1_clk_gate const *gate)
1046{
1047 uintptr_t rcc_base = stm32mp_rcc_base();
1048
Etienne Carriere8a668892019-12-08 08:21:08 +01001049 VERBOSE("Disable clock %u\n", gate->index);
1050
Yann Gautiere4a3c352019-02-14 10:53:33 +01001051 if (gate->set_clr != 0U) {
1052 mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
1053 BIT(gate->bit));
1054 } else {
1055 mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
1056 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001057}
1058
1059static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
1060{
1061 uintptr_t rcc_base = stm32mp_rcc_base();
1062
1063 return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
1064}
1065
1066unsigned int stm32mp1_clk_get_refcount(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001067{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001068 int i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001069
1070 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001071 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001072 }
1073
Yann Gautiere4a3c352019-02-14 10:53:33 +01001074 return gate_refcounts[i];
Yann Gautier9aea69e2018-07-24 17:13:36 +02001075}
1076
Etienne Carriere481aa002019-12-08 08:21:44 +01001077/* Oscillators and PLLs are not gated at runtime */
1078static bool clock_is_always_on(unsigned long id)
1079{
1080 switch (id) {
1081 case CK_HSE:
1082 case CK_CSI:
1083 case CK_LSI:
1084 case CK_LSE:
1085 case CK_HSI:
1086 case CK_HSE_DIV2:
1087 case PLL1_Q:
1088 case PLL1_R:
1089 case PLL2_P:
1090 case PLL2_Q:
1091 case PLL2_R:
1092 case PLL3_P:
1093 case PLL3_Q:
1094 case PLL3_R:
Yann Gautierb39a1522020-09-16 16:41:55 +02001095 case CK_AXI:
1096 case CK_MPU:
1097 case CK_MCU:
HE Shushanc47c8162021-07-12 23:04:10 +02001098 case RTC:
Etienne Carriere481aa002019-12-08 08:21:44 +01001099 return true;
1100 default:
1101 return false;
1102 }
1103}
1104
Yann Gautiere4a3c352019-02-14 10:53:33 +01001105void __stm32mp1_clk_enable(unsigned long id, bool secure)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001106{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001107 const struct stm32mp1_clk_gate *gate;
Etienne Carriere481aa002019-12-08 08:21:44 +01001108 int i;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001109 unsigned int *refcnt;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001110
Etienne Carriere481aa002019-12-08 08:21:44 +01001111 if (clock_is_always_on(id)) {
1112 return;
1113 }
1114
1115 i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001116 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001117 ERROR("Clock %d can't be enabled\n", (uint32_t)id);
1118 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001119 }
1120
Yann Gautiere4a3c352019-02-14 10:53:33 +01001121 gate = gate_ref(i);
1122 refcnt = &gate_refcounts[i];
1123
1124 stm32mp1_clk_lock(&refcount_lock);
1125
1126 if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) {
1127 __clk_enable(gate);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001128 }
1129
Yann Gautiere4a3c352019-02-14 10:53:33 +01001130 stm32mp1_clk_unlock(&refcount_lock);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001131}
1132
Yann Gautiere4a3c352019-02-14 10:53:33 +01001133void __stm32mp1_clk_disable(unsigned long id, bool secure)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001134{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001135 const struct stm32mp1_clk_gate *gate;
Etienne Carriere481aa002019-12-08 08:21:44 +01001136 int i;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001137 unsigned int *refcnt;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001138
Etienne Carriere481aa002019-12-08 08:21:44 +01001139 if (clock_is_always_on(id)) {
1140 return;
1141 }
1142
1143 i = stm32mp1_clk_get_gated_id(id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001144 if (i < 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001145 ERROR("Clock %d can't be disabled\n", (uint32_t)id);
1146 panic();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001147 }
1148
Yann Gautiere4a3c352019-02-14 10:53:33 +01001149 gate = gate_ref(i);
1150 refcnt = &gate_refcounts[i];
1151
1152 stm32mp1_clk_lock(&refcount_lock);
1153
1154 if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) {
1155 __clk_disable(gate);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001156 }
1157
Yann Gautiere4a3c352019-02-14 10:53:33 +01001158 stm32mp1_clk_unlock(&refcount_lock);
1159}
1160
Yann Gautiera205a5c2021-08-30 15:06:54 +02001161static int stm32mp_clk_enable(unsigned long id)
Yann Gautiere4a3c352019-02-14 10:53:33 +01001162{
1163 __stm32mp1_clk_enable(id, true);
Yann Gautiera205a5c2021-08-30 15:06:54 +02001164
1165 return 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001166}
1167
Yann Gautiera205a5c2021-08-30 15:06:54 +02001168static void stm32mp_clk_disable(unsigned long id)
Yann Gautiere4a3c352019-02-14 10:53:33 +01001169{
1170 __stm32mp1_clk_disable(id, true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001171}
1172
Yann Gautiera205a5c2021-08-30 15:06:54 +02001173static bool stm32mp_clk_is_enabled(unsigned long id)
Yann Gautiere4a3c352019-02-14 10:53:33 +01001174{
Etienne Carriere481aa002019-12-08 08:21:44 +01001175 int i;
1176
1177 if (clock_is_always_on(id)) {
1178 return true;
1179 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001180
Etienne Carriere481aa002019-12-08 08:21:44 +01001181 i = stm32mp1_clk_get_gated_id(id);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001182 if (i < 0) {
1183 panic();
1184 }
1185
1186 return __clk_is_enabled(gate_ref(i));
1187}
1188
Yann Gautiera205a5c2021-08-30 15:06:54 +02001189static unsigned long stm32mp_clk_get_rate(unsigned long id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001190{
Yann Gautiera205a5c2021-08-30 15:06:54 +02001191 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautiere4a3c352019-02-14 10:53:33 +01001192 int p = stm32mp1_clk_get_parent(id);
Yann Gautiera205a5c2021-08-30 15:06:54 +02001193 uint32_t prescaler, timpre;
1194 unsigned long parent_rate;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001195
1196 if (p < 0) {
1197 return 0;
1198 }
1199
Yann Gautiera205a5c2021-08-30 15:06:54 +02001200 parent_rate = get_clock_rate(p);
1201
1202 switch (id) {
1203 case TIM2_K:
1204 case TIM3_K:
1205 case TIM4_K:
1206 case TIM5_K:
1207 case TIM6_K:
1208 case TIM7_K:
1209 case TIM12_K:
1210 case TIM13_K:
1211 case TIM14_K:
1212 prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) &
1213 RCC_APBXDIV_MASK;
1214 timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) &
1215 RCC_TIMGXPRER_TIMGXPRE;
1216 break;
1217
1218 case TIM1_K:
1219 case TIM8_K:
1220 case TIM15_K:
1221 case TIM16_K:
1222 case TIM17_K:
1223 prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) &
1224 RCC_APBXDIV_MASK;
1225 timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) &
1226 RCC_TIMGXPRER_TIMGXPRE;
1227 break;
1228
1229 default:
1230 return parent_rate;
1231 }
1232
1233 if (prescaler == 0U) {
1234 return parent_rate;
1235 }
1236
1237 return parent_rate * (timpre + 1U) * 2U;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001238}
1239
Yann Gautiere4a3c352019-02-14 10:53:33 +01001240static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001241{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001242 uintptr_t address = stm32mp_rcc_base() + offset;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001243
Yann Gautiere4a3c352019-02-14 10:53:33 +01001244 if (enable) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001245 mmio_setbits_32(address, mask_on);
1246 } else {
1247 mmio_clrbits_32(address, mask_on);
1248 }
1249}
1250
Yann Gautiere4a3c352019-02-14 10:53:33 +01001251static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001252{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001253 uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
1254 uintptr_t address = stm32mp_rcc_base() + offset;
1255
1256 mmio_write_32(address, mask_on);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001257}
1258
Yann Gautiere4a3c352019-02-14 10:53:33 +01001259static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001260{
Yann Gautier2299d572019-02-14 11:14:39 +01001261 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001262 uint32_t mask_test;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001263 uintptr_t address = stm32mp_rcc_base() + offset;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001264
Yann Gautiere4a3c352019-02-14 10:53:33 +01001265 if (enable) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001266 mask_test = mask_rdy;
1267 } else {
1268 mask_test = 0;
1269 }
1270
Yann Gautier2299d572019-02-14 11:14:39 +01001271 timeout = timeout_init_us(OSCRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001272 while ((mmio_read_32(address) & mask_rdy) != mask_test) {
Yann Gautier2299d572019-02-14 11:14:39 +01001273 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001274 ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001275 mask_rdy, address, enable, mmio_read_32(address));
1276 return -ETIMEDOUT;
1277 }
1278 }
1279
1280 return 0;
1281}
1282
Yann Gautiere4a3c352019-02-14 10:53:33 +01001283static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001284{
1285 uint32_t value;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001286 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001287
Yann Gautiere4a3c352019-02-14 10:53:33 +01001288 if (digbyp) {
1289 mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001290 }
1291
Yann Gautiere4a3c352019-02-14 10:53:33 +01001292 if (bypass || digbyp) {
1293 mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
1294 }
1295
Yann Gautier9aea69e2018-07-24 17:13:36 +02001296 /*
1297 * Warning: not recommended to switch directly from "high drive"
1298 * to "medium low drive", and vice-versa.
1299 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001300 value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
Yann Gautier9aea69e2018-07-24 17:13:36 +02001301 RCC_BDCR_LSEDRV_SHIFT;
1302
1303 while (value != lsedrv) {
1304 if (value > lsedrv) {
1305 value--;
1306 } else {
1307 value++;
1308 }
1309
Yann Gautiere4a3c352019-02-14 10:53:33 +01001310 mmio_clrsetbits_32(rcc_base + RCC_BDCR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001311 RCC_BDCR_LSEDRV_MASK,
1312 value << RCC_BDCR_LSEDRV_SHIFT);
1313 }
1314
Yann Gautiere4a3c352019-02-14 10:53:33 +01001315 stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001316}
1317
Yann Gautiere4a3c352019-02-14 10:53:33 +01001318static void stm32mp1_lse_wait(void)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001319{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001320 if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001321 VERBOSE("%s: failed\n", __func__);
1322 }
1323}
1324
Yann Gautiere4a3c352019-02-14 10:53:33 +01001325static void stm32mp1_lsi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001326{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001327 stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
1328
1329 if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001330 VERBOSE("%s: failed\n", __func__);
1331 }
1332}
1333
Yann Gautiere4a3c352019-02-14 10:53:33 +01001334static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001335{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001336 uintptr_t rcc_base = stm32mp_rcc_base();
1337
1338 if (digbyp) {
1339 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001340 }
1341
Yann Gautiere4a3c352019-02-14 10:53:33 +01001342 if (bypass || digbyp) {
1343 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
1344 }
1345
1346 stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
1347 if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001348 VERBOSE("%s: failed\n", __func__);
1349 }
1350
1351 if (css) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001352 mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001353 }
1354}
1355
Yann Gautiere4a3c352019-02-14 10:53:33 +01001356static void stm32mp1_csi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001357{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001358 stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
1359 if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001360 VERBOSE("%s: failed\n", __func__);
1361 }
1362}
1363
Yann Gautiere4a3c352019-02-14 10:53:33 +01001364static void stm32mp1_hsi_set(bool enable)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001365{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001366 stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
1367 if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001368 VERBOSE("%s: failed\n", __func__);
1369 }
1370}
1371
Yann Gautiere4a3c352019-02-14 10:53:33 +01001372static int stm32mp1_set_hsidiv(uint8_t hsidiv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001373{
Yann Gautier2299d572019-02-14 11:14:39 +01001374 uint64_t timeout;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001375 uintptr_t rcc_base = stm32mp_rcc_base();
1376 uintptr_t address = rcc_base + RCC_OCRDYR;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001377
Yann Gautiere4a3c352019-02-14 10:53:33 +01001378 mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001379 RCC_HSICFGR_HSIDIV_MASK,
1380 RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
1381
Yann Gautier2299d572019-02-14 11:14:39 +01001382 timeout = timeout_init_us(HSIDIV_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001383 while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001384 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001385 ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001386 address, mmio_read_32(address));
1387 return -ETIMEDOUT;
1388 }
1389 }
1390
1391 return 0;
1392}
1393
Yann Gautiere4a3c352019-02-14 10:53:33 +01001394static int stm32mp1_hsidiv(unsigned long hsifreq)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001395{
1396 uint8_t hsidiv;
1397 uint32_t hsidivfreq = MAX_HSI_HZ;
1398
1399 for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
1400 if (hsidivfreq == hsifreq) {
1401 break;
1402 }
1403
1404 hsidivfreq /= 2U;
1405 }
1406
1407 if (hsidiv == 4U) {
1408 ERROR("Invalid clk-hsi frequency\n");
1409 return -1;
1410 }
1411
1412 if (hsidiv != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001413 return stm32mp1_set_hsidiv(hsidiv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001414 }
1415
1416 return 0;
1417}
1418
Yann Gautiere4a3c352019-02-14 10:53:33 +01001419static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
1420 unsigned int clksrc,
1421 uint32_t *pllcfg, int plloff)
1422{
1423 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1424 uintptr_t rcc_base = stm32mp_rcc_base();
1425 uintptr_t pllxcr = rcc_base + pll->pllxcr;
1426 enum stm32mp1_plltype type = pll->plltype;
1427 uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
1428 unsigned long refclk;
1429 uint32_t ifrge = 0U;
Andre Przywara2d5690c2020-03-26 11:50:33 +00001430 uint32_t src, value, fracv = 0;
1431 void *fdt;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001432
1433 /* Check PLL output */
1434 if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
1435 return false;
1436 }
1437
1438 /* Check current clksrc */
1439 src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
1440 if (src != (clksrc & RCC_SELR_SRC_MASK)) {
1441 return false;
1442 }
1443
1444 /* Check Div */
1445 src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
1446
1447 refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
1448 (pllcfg[PLLCFG_M] + 1U);
1449
1450 if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
1451 (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
1452 return false;
1453 }
1454
1455 if ((type == PLL_800) && (refclk >= 8000000U)) {
1456 ifrge = 1U;
1457 }
1458
1459 value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
1460 RCC_PLLNCFGR1_DIVN_MASK;
1461 value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
1462 RCC_PLLNCFGR1_DIVM_MASK;
1463 value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
1464 RCC_PLLNCFGR1_IFRGE_MASK;
1465 if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
1466 return false;
1467 }
1468
1469 /* Fractional configuration */
Andre Przywara2d5690c2020-03-26 11:50:33 +00001470 if (fdt_get_address(&fdt) == 1) {
1471 fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1472 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001473
1474 value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
1475 value |= RCC_PLLNFRACR_FRACLE;
1476 if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
1477 return false;
1478 }
1479
1480 /* Output config */
1481 value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
1482 RCC_PLLNCFGR2_DIVP_MASK;
1483 value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
1484 RCC_PLLNCFGR2_DIVQ_MASK;
1485 value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
1486 RCC_PLLNCFGR2_DIVR_MASK;
1487 if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
1488 return false;
1489 }
1490
1491 return true;
1492}
1493
1494static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001495{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001496 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1497 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001498
Yann Gautierd0dcbaa2019-06-04 15:55:37 +02001499 /* Preserve RCC_PLLNCR_SSCG_CTRL value */
1500 mmio_clrsetbits_32(pllxcr,
1501 RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1502 RCC_PLLNCR_DIVREN,
1503 RCC_PLLNCR_PLLON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001504}
1505
Yann Gautiere4a3c352019-02-14 10:53:33 +01001506static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001507{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001508 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1509 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier2299d572019-02-14 11:14:39 +01001510 uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001511
Yann Gautier9aea69e2018-07-24 17:13:36 +02001512 /* Wait PLL lock */
1513 while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001514 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001515 ERROR("PLL%d start failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001516 pll_id, pllxcr, mmio_read_32(pllxcr));
1517 return -ETIMEDOUT;
1518 }
1519 }
1520
1521 /* Start the requested output */
1522 mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
1523
1524 return 0;
1525}
1526
Yann Gautiere4a3c352019-02-14 10:53:33 +01001527static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001528{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001529 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1530 uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
Yann Gautier2299d572019-02-14 11:14:39 +01001531 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001532
1533 /* Stop all output */
1534 mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1535 RCC_PLLNCR_DIVREN);
1536
1537 /* Stop PLL */
1538 mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
1539
Yann Gautier2299d572019-02-14 11:14:39 +01001540 timeout = timeout_init_us(PLLRDY_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001541 /* Wait PLL stopped */
1542 while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001543 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001544 ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001545 pll_id, pllxcr, mmio_read_32(pllxcr));
1546 return -ETIMEDOUT;
1547 }
1548 }
1549
1550 return 0;
1551}
1552
Yann Gautiere4a3c352019-02-14 10:53:33 +01001553static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001554 uint32_t *pllcfg)
1555{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001556 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1557 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001558 uint32_t value;
1559
1560 value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
1561 RCC_PLLNCFGR2_DIVP_MASK;
1562 value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
1563 RCC_PLLNCFGR2_DIVQ_MASK;
1564 value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
1565 RCC_PLLNCFGR2_DIVR_MASK;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001566 mmio_write_32(rcc_base + pll->pllxcfgr2, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001567}
1568
Yann Gautiere4a3c352019-02-14 10:53:33 +01001569static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001570 uint32_t *pllcfg, uint32_t fracv)
1571{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001572 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
1573 uintptr_t rcc_base = stm32mp_rcc_base();
1574 enum stm32mp1_plltype type = pll->plltype;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001575 unsigned long refclk;
1576 uint32_t ifrge = 0;
1577 uint32_t src, value;
1578
Yann Gautiere4a3c352019-02-14 10:53:33 +01001579 src = mmio_read_32(rcc_base + pll->rckxselr) &
Yann Gautier9aea69e2018-07-24 17:13:36 +02001580 RCC_SELR_REFCLK_SRC_MASK;
1581
Yann Gautiere4a3c352019-02-14 10:53:33 +01001582 refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
Yann Gautier9aea69e2018-07-24 17:13:36 +02001583 (pllcfg[PLLCFG_M] + 1U);
1584
1585 if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
1586 (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
1587 return -EINVAL;
1588 }
1589
1590 if ((type == PLL_800) && (refclk >= 8000000U)) {
1591 ifrge = 1U;
1592 }
1593
1594 value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
1595 RCC_PLLNCFGR1_DIVN_MASK;
1596 value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
1597 RCC_PLLNCFGR1_DIVM_MASK;
1598 value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
1599 RCC_PLLNCFGR1_IFRGE_MASK;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001600 mmio_write_32(rcc_base + pll->pllxcfgr1, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001601
1602 /* Fractional configuration */
1603 value = 0;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001604 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001605
1606 value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001607 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001608
1609 value |= RCC_PLLNFRACR_FRACLE;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001610 mmio_write_32(rcc_base + pll->pllxfracr, value);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001611
Yann Gautiere4a3c352019-02-14 10:53:33 +01001612 stm32mp1_pll_config_output(pll_id, pllcfg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001613
1614 return 0;
1615}
1616
Yann Gautiere4a3c352019-02-14 10:53:33 +01001617static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001618{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001619 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001620 uint32_t pllxcsg = 0;
1621
1622 pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
1623 RCC_PLLNCSGR_MOD_PER_MASK;
1624
1625 pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
1626 RCC_PLLNCSGR_INC_STEP_MASK;
1627
1628 pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
1629 RCC_PLLNCSGR_SSCG_MODE_MASK;
1630
Yann Gautiere4a3c352019-02-14 10:53:33 +01001631 mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
Yann Gautierd0dcbaa2019-06-04 15:55:37 +02001632
1633 mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
1634 RCC_PLLNCR_SSCG_CTRL);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001635}
1636
Yann Gautiere4a3c352019-02-14 10:53:33 +01001637static int stm32mp1_set_clksrc(unsigned int clksrc)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001638{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001639 uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
Yann Gautier2299d572019-02-14 11:14:39 +01001640 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001641
Yann Gautiere4a3c352019-02-14 10:53:33 +01001642 mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001643 clksrc & RCC_SELR_SRC_MASK);
1644
Yann Gautier2299d572019-02-14 11:14:39 +01001645 timeout = timeout_init_us(CLKSRC_TIMEOUT);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001646 while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001647 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001648 ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
1649 clksrc_address, mmio_read_32(clksrc_address));
Yann Gautier9aea69e2018-07-24 17:13:36 +02001650 return -ETIMEDOUT;
1651 }
1652 }
1653
1654 return 0;
1655}
1656
Yann Gautiere4a3c352019-02-14 10:53:33 +01001657static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001658{
Yann Gautier2299d572019-02-14 11:14:39 +01001659 uint64_t timeout;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001660
1661 mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
1662 clkdiv & RCC_DIVR_DIV_MASK);
1663
Yann Gautier2299d572019-02-14 11:14:39 +01001664 timeout = timeout_init_us(CLKDIV_TIMEOUT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001665 while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
Yann Gautier2299d572019-02-14 11:14:39 +01001666 if (timeout_elapsed(timeout)) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001667 ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
Yann Gautier9aea69e2018-07-24 17:13:36 +02001668 clkdiv, address, mmio_read_32(address));
1669 return -ETIMEDOUT;
1670 }
1671 }
1672
1673 return 0;
1674}
1675
Yann Gautiere4a3c352019-02-14 10:53:33 +01001676static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001677{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001678 uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001679
1680 /*
1681 * Binding clksrc :
1682 * bit15-4 offset
1683 * bit3: disable
1684 * bit2-0: MCOSEL[2:0]
1685 */
1686 if ((clksrc & 0x8U) != 0U) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001687 mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001688 } else {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001689 mmio_clrsetbits_32(clksrc_address,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001690 RCC_MCOCFG_MCOSRC_MASK,
1691 clksrc & RCC_MCOCFG_MCOSRC_MASK);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001692 mmio_clrsetbits_32(clksrc_address,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001693 RCC_MCOCFG_MCODIV_MASK,
1694 clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001695 mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001696 }
1697}
1698
Yann Gautiere4a3c352019-02-14 10:53:33 +01001699static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001700{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001701 uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001702
1703 if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
1704 (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
1705 mmio_clrsetbits_32(address,
1706 RCC_BDCR_RTCSRC_MASK,
Yann Gautier74aa83a2021-04-06 13:41:19 +02001707 (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001708
1709 mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
1710 }
1711
1712 if (lse_css) {
1713 mmio_setbits_32(address, RCC_BDCR_LSECSSON);
1714 }
1715}
1716
Yann Gautiere4a3c352019-02-14 10:53:33 +01001717static void stm32mp1_stgen_config(void)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001718{
Yann Gautier9aea69e2018-07-24 17:13:36 +02001719 uint32_t cntfid0;
1720 unsigned long rate;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001721 unsigned long long counter;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001722
Yann Gautiera18f61b2020-05-05 17:58:40 +02001723 cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001724 rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K));
Yann Gautier9aea69e2018-07-24 17:13:36 +02001725
Yann Gautiere4a3c352019-02-14 10:53:33 +01001726 if (cntfid0 == rate) {
1727 return;
1728 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001729
Yann Gautiera18f61b2020-05-05 17:58:40 +02001730 mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
1731 counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF);
1732 counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001733 counter = (counter * rate / cntfid0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001734
Yann Gautiera18f61b2020-05-05 17:58:40 +02001735 mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter);
1736 mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32));
1737 mmio_write_32(STGEN_BASE + CNTFID_OFF, rate);
1738 mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001739
Yann Gautiere4a3c352019-02-14 10:53:33 +01001740 write_cntfrq((u_register_t)rate);
1741
1742 /* Need to update timer with new frequency */
1743 generic_delay_timer_init();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001744}
1745
1746void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
1747{
Yann Gautier9aea69e2018-07-24 17:13:36 +02001748 unsigned long long cnt;
1749
Yann Gautiera18f61b2020-05-05 17:58:40 +02001750 cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) |
1751 mmio_read_32(STGEN_BASE + CNTCVL_OFF);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001752
Yann Gautiera18f61b2020-05-05 17:58:40 +02001753 cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001754
Yann Gautiera18f61b2020-05-05 17:58:40 +02001755 mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
1756 mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt);
1757 mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32));
1758 mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001759}
1760
Yann Gautiere4a3c352019-02-14 10:53:33 +01001761static void stm32mp1_pkcs_config(uint32_t pkcs)
Yann Gautier9aea69e2018-07-24 17:13:36 +02001762{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001763 uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001764 uint32_t value = pkcs & 0xFU;
1765 uint32_t mask = 0xFU;
1766
1767 if ((pkcs & BIT(31)) != 0U) {
1768 mask <<= 4;
1769 value <<= 4;
1770 }
1771
1772 mmio_clrsetbits_32(address, mask, value);
1773}
1774
1775int stm32mp1_clk_init(void)
1776{
Yann Gautiere4a3c352019-02-14 10:53:33 +01001777 uintptr_t rcc_base = stm32mp_rcc_base();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001778 unsigned int clksrc[CLKSRC_NB];
1779 unsigned int clkdiv[CLKDIV_NB];
1780 unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
1781 int plloff[_PLL_NB];
1782 int ret, len;
1783 enum stm32mp1_pll_id i;
1784 bool lse_css = false;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001785 bool pll3_preserve = false;
1786 bool pll4_preserve = false;
1787 bool pll4_bootrom = false;
Yann Gautierf9af3bc2018-11-09 15:57:18 +01001788 const fdt32_t *pkcs_cell;
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001789 void *fdt;
Patrick Delaunay64e1b2c2020-09-04 17:39:12 +02001790 int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
1791 int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001792
1793 if (fdt_get_address(&fdt) == 0) {
Yann Gautier360e0e92020-09-16 16:40:34 +02001794 return -FDT_ERR_NOTFOUND;
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001795 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001796
1797 /* Check status field to disable security */
1798 if (!fdt_get_rcc_secure_status()) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001799 mmio_write_32(rcc_base + RCC_TZCR, 0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001800 }
1801
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001802 ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
1803 clksrc);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001804 if (ret < 0) {
1805 return -FDT_ERR_NOTFOUND;
1806 }
1807
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001808 ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
1809 clkdiv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001810 if (ret < 0) {
1811 return -FDT_ERR_NOTFOUND;
1812 }
1813
1814 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1815 char name[12];
1816
Antonio Nino Diaz00086e32018-08-16 16:46:06 +01001817 snprintf(name, sizeof(name), "st,pll@%d", i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001818 plloff[i] = fdt_rcc_subnode_offset(name);
1819
1820 if (!fdt_check_node(plloff[i])) {
1821 continue;
1822 }
1823
Andre Przywaracc99f3f2020-03-26 12:51:21 +00001824 ret = fdt_read_uint32_array(fdt, plloff[i], "cfg",
1825 (int)PLLCFG_NB, pllcfg[i]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001826 if (ret < 0) {
1827 return -FDT_ERR_NOTFOUND;
1828 }
1829 }
1830
Yann Gautiere4a3c352019-02-14 10:53:33 +01001831 stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
1832 stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001833
1834 /*
1835 * Switch ON oscillator found in device-tree.
1836 * Note: HSI already ON after BootROM stage.
1837 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001838 if (stm32mp1_osc[_LSI] != 0U) {
1839 stm32mp1_lsi_set(true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001840 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001841 if (stm32mp1_osc[_LSE] != 0U) {
1842 bool bypass, digbyp;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001843 uint32_t lsedrv;
1844
1845 bypass = fdt_osc_read_bool(_LSE, "st,bypass");
Yann Gautiere4a3c352019-02-14 10:53:33 +01001846 digbyp = fdt_osc_read_bool(_LSE, "st,digbypass");
Yann Gautier9aea69e2018-07-24 17:13:36 +02001847 lse_css = fdt_osc_read_bool(_LSE, "st,css");
1848 lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive",
1849 LSEDRV_MEDIUM_HIGH);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001850 stm32mp1_lse_enable(bypass, digbyp, lsedrv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001851 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001852 if (stm32mp1_osc[_HSE] != 0U) {
1853 bool bypass, digbyp, css;
Yann Gautier9aea69e2018-07-24 17:13:36 +02001854
Yann Gautiere4a3c352019-02-14 10:53:33 +01001855 bypass = fdt_osc_read_bool(_HSE, "st,bypass");
1856 digbyp = fdt_osc_read_bool(_HSE, "st,digbypass");
1857 css = fdt_osc_read_bool(_HSE, "st,css");
1858 stm32mp1_hse_enable(bypass, digbyp, css);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001859 }
1860 /*
1861 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
1862 * => switch on CSI even if node is not present in device tree
1863 */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001864 stm32mp1_csi_set(true);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001865
1866 /* Come back to HSI */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001867 ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001868 if (ret != 0) {
1869 return ret;
1870 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001871 ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001872 if (ret != 0) {
1873 return ret;
1874 }
Yann Gautiered342322019-02-15 17:33:27 +01001875 ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
1876 if (ret != 0) {
1877 return ret;
1878 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001879
Yann Gautiere4a3c352019-02-14 10:53:33 +01001880 if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
1881 RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
1882 pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
1883 clksrc[CLKSRC_PLL3],
1884 pllcfg[_PLL3],
1885 plloff[_PLL3]);
1886 pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
1887 clksrc[CLKSRC_PLL4],
1888 pllcfg[_PLL4],
1889 plloff[_PLL4]);
1890 }
Patrick Delaunay64e1b2c2020-09-04 17:39:12 +02001891 /* Don't initialize PLL4, when used by BOOTROM */
1892 if ((stm32mp_get_boot_itf_selected() ==
1893 BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) &&
1894 ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
1895 pll4_bootrom = true;
1896 pll4_preserve = true;
1897 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001898
Yann Gautier9aea69e2018-07-24 17:13:36 +02001899 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01001900 if (((i == _PLL3) && pll3_preserve) ||
1901 ((i == _PLL4) && pll4_preserve)) {
Yann Gautier9aea69e2018-07-24 17:13:36 +02001902 continue;
Yann Gautiere4a3c352019-02-14 10:53:33 +01001903 }
1904
1905 ret = stm32mp1_pll_stop(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001906 if (ret != 0) {
1907 return ret;
1908 }
1909 }
1910
1911 /* Configure HSIDIV */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001912 if (stm32mp1_osc[_HSI] != 0U) {
1913 ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001914 if (ret != 0) {
1915 return ret;
1916 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001917 stm32mp1_stgen_config();
Yann Gautier9aea69e2018-07-24 17:13:36 +02001918 }
1919
1920 /* Select DIV */
1921 /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001922 mmio_write_32(rcc_base + RCC_MPCKDIVR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001923 clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
Yann Gautiere4a3c352019-02-14 10:53:33 +01001924 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001925 if (ret != 0) {
1926 return ret;
1927 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001928 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001929 if (ret != 0) {
1930 return ret;
1931 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001932 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001933 if (ret != 0) {
1934 return ret;
1935 }
Yann Gautiered342322019-02-15 17:33:27 +01001936 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
1937 if (ret != 0) {
1938 return ret;
1939 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001940 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001941 if (ret != 0) {
1942 return ret;
1943 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001944 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001945 if (ret != 0) {
1946 return ret;
1947 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001948 ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001949 if (ret != 0) {
1950 return ret;
1951 }
1952
1953 /* No ready bit for RTC */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001954 mmio_write_32(rcc_base + RCC_RTCDIVR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02001955 clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
1956
1957 /* Configure PLLs source */
Yann Gautiere4a3c352019-02-14 10:53:33 +01001958 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001959 if (ret != 0) {
1960 return ret;
1961 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01001962
1963 if (!pll3_preserve) {
1964 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
1965 if (ret != 0) {
1966 return ret;
1967 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001968 }
1969
Yann Gautiere4a3c352019-02-14 10:53:33 +01001970 if (!pll4_preserve) {
1971 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
1972 if (ret != 0) {
1973 return ret;
1974 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02001975 }
1976
1977 /* Configure and start PLLs */
1978 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
1979 uint32_t fracv;
1980 uint32_t csg[PLLCSG_NB];
1981
Yann Gautiere4a3c352019-02-14 10:53:33 +01001982 if (((i == _PLL3) && pll3_preserve) ||
1983 ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
1984 continue;
1985 }
1986
Yann Gautier9aea69e2018-07-24 17:13:36 +02001987 if (!fdt_check_node(plloff[i])) {
1988 continue;
1989 }
1990
Yann Gautiere4a3c352019-02-14 10:53:33 +01001991 if ((i == _PLL4) && pll4_bootrom) {
1992 /* Set output divider if not done by the Bootrom */
1993 stm32mp1_pll_config_output(i, pllcfg[i]);
1994 continue;
1995 }
1996
Andre Przywara2d5690c2020-03-26 11:50:33 +00001997 fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0);
Yann Gautier9aea69e2018-07-24 17:13:36 +02001998
Yann Gautiere4a3c352019-02-14 10:53:33 +01001999 ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002000 if (ret != 0) {
2001 return ret;
2002 }
Andre Przywaracc99f3f2020-03-26 12:51:21 +00002003 ret = fdt_read_uint32_array(fdt, plloff[i], "csg",
2004 (uint32_t)PLLCSG_NB, csg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002005 if (ret == 0) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01002006 stm32mp1_pll_csg(i, csg);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002007 } else if (ret != -FDT_ERR_NOTFOUND) {
2008 return ret;
2009 }
2010
Yann Gautiere4a3c352019-02-14 10:53:33 +01002011 stm32mp1_pll_start(i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002012 }
2013 /* Wait and start PLLs ouptut when ready */
2014 for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
2015 if (!fdt_check_node(plloff[i])) {
2016 continue;
2017 }
2018
Yann Gautiere4a3c352019-02-14 10:53:33 +01002019 ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002020 if (ret != 0) {
2021 return ret;
2022 }
2023 }
2024 /* Wait LSE ready before to use it */
Yann Gautiere4a3c352019-02-14 10:53:33 +01002025 if (stm32mp1_osc[_LSE] != 0U) {
2026 stm32mp1_lse_wait();
Yann Gautier9aea69e2018-07-24 17:13:36 +02002027 }
2028
2029 /* Configure with expected clock source */
Yann Gautiere4a3c352019-02-14 10:53:33 +01002030 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002031 if (ret != 0) {
2032 return ret;
2033 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01002034 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002035 if (ret != 0) {
2036 return ret;
2037 }
Yann Gautiered342322019-02-15 17:33:27 +01002038 ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
2039 if (ret != 0) {
2040 return ret;
2041 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01002042 stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002043
2044 /* Configure PKCK */
2045 pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
2046 if (pkcs_cell != NULL) {
2047 bool ckper_disabled = false;
2048 uint32_t j;
Patrick Delaunay64e1b2c2020-09-04 17:39:12 +02002049 uint32_t usbreg_bootrom = 0U;
2050
2051 if (pll4_bootrom) {
2052 usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
2053 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02002054
Yann Gautier9aea69e2018-07-24 17:13:36 +02002055 for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
Yann Gautierf9af3bc2018-11-09 15:57:18 +01002056 uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002057
2058 if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
2059 ckper_disabled = true;
2060 continue;
2061 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01002062 stm32mp1_pkcs_config(pkcs);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002063 }
2064
2065 /*
2066 * CKPER is source for some peripheral clocks
2067 * (FMC-NAND / QPSI-NOR) and switching source is allowed
2068 * only if previous clock is still ON
2069 * => deactivated CKPER only after switching clock
2070 */
2071 if (ckper_disabled) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01002072 stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002073 }
Patrick Delaunay64e1b2c2020-09-04 17:39:12 +02002074
2075 if (pll4_bootrom) {
2076 uint32_t usbreg_value, usbreg_mask;
2077 const struct stm32mp1_clk_sel *sel;
2078
2079 sel = clk_sel_ref(_USBPHY_SEL);
2080 usbreg_mask = (uint32_t)sel->msk << sel->src;
2081 sel = clk_sel_ref(_USBO_SEL);
2082 usbreg_mask |= (uint32_t)sel->msk << sel->src;
2083
2084 usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
2085 usbreg_mask;
2086 usbreg_bootrom &= usbreg_mask;
2087 if (usbreg_bootrom != usbreg_value) {
2088 VERBOSE("forbidden new USB clk path\n");
2089 VERBOSE("vs bootrom on USB boot\n");
2090 return -FDT_ERR_BADVALUE;
2091 }
2092 }
Yann Gautier9aea69e2018-07-24 17:13:36 +02002093 }
2094
2095 /* Switch OFF HSI if not found in device-tree */
Yann Gautiere4a3c352019-02-14 10:53:33 +01002096 if (stm32mp1_osc[_HSI] == 0U) {
2097 stm32mp1_hsi_set(false);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002098 }
Yann Gautiere4a3c352019-02-14 10:53:33 +01002099 stm32mp1_stgen_config();
Yann Gautier9aea69e2018-07-24 17:13:36 +02002100
2101 /* Software Self-Refresh mode (SSR) during DDR initilialization */
Yann Gautiere4a3c352019-02-14 10:53:33 +01002102 mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
Yann Gautier9aea69e2018-07-24 17:13:36 +02002103 RCC_DDRITFCR_DDRCKMOD_MASK,
2104 RCC_DDRITFCR_DDRCKMOD_SSR <<
2105 RCC_DDRITFCR_DDRCKMOD_SHIFT);
2106
2107 return 0;
2108}
2109
2110static void stm32mp1_osc_clk_init(const char *name,
Yann Gautier9aea69e2018-07-24 17:13:36 +02002111 enum stm32mp_osc_id index)
2112{
2113 uint32_t frequency;
2114
Yann Gautiere4a3c352019-02-14 10:53:33 +01002115 if (fdt_osc_read_freq(name, &frequency) == 0) {
2116 stm32mp1_osc[index] = frequency;
Yann Gautier9aea69e2018-07-24 17:13:36 +02002117 }
2118}
2119
2120static void stm32mp1_osc_init(void)
2121{
Yann Gautier9aea69e2018-07-24 17:13:36 +02002122 enum stm32mp_osc_id i;
2123
2124 for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
Yann Gautiere4a3c352019-02-14 10:53:33 +01002125 stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
Yann Gautier9aea69e2018-07-24 17:13:36 +02002126 }
2127}
Etienne Carriere1368ada2020-05-13 11:49:49 +02002128
2129#ifdef STM32MP_SHARED_RESOURCES
2130/*
2131 * Get the parent ID of the target parent clock, for tagging as secure
2132 * shared clock dependencies.
2133 */
2134static int get_parent_id_parent(unsigned int parent_id)
2135{
2136 enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
2137 enum stm32mp1_pll_id pll_id;
2138 uint32_t p_sel;
2139 uintptr_t rcc_base = stm32mp_rcc_base();
2140
2141 switch (parent_id) {
2142 case _ACLK:
2143 case _PCLK4:
2144 case _PCLK5:
2145 s = _AXIS_SEL;
2146 break;
2147 case _PLL1_P:
2148 case _PLL1_Q:
2149 case _PLL1_R:
2150 pll_id = _PLL1;
2151 break;
2152 case _PLL2_P:
2153 case _PLL2_Q:
2154 case _PLL2_R:
2155 pll_id = _PLL2;
2156 break;
2157 case _PLL3_P:
2158 case _PLL3_Q:
2159 case _PLL3_R:
2160 pll_id = _PLL3;
2161 break;
2162 case _PLL4_P:
2163 case _PLL4_Q:
2164 case _PLL4_R:
2165 pll_id = _PLL4;
2166 break;
2167 case _PCLK1:
2168 case _PCLK2:
2169 case _HCLK2:
2170 case _HCLK6:
2171 case _CK_PER:
2172 case _CK_MPU:
2173 case _CK_MCU:
2174 case _USB_PHY_48:
2175 /* We do not expect to access these */
2176 panic();
2177 break;
2178 default:
2179 /* Other parents have no parent */
2180 return -1;
2181 }
2182
2183 if (s != _UNKNOWN_SEL) {
2184 const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
2185
2186 p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
2187 sel->msk;
2188
2189 if (p_sel < sel->nb_parent) {
2190 return (int)sel->parent[p_sel];
2191 }
2192 } else {
2193 const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
2194
2195 p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
2196 RCC_SELR_REFCLK_SRC_MASK;
2197
2198 if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
2199 return (int)pll->refclk[p_sel];
2200 }
2201 }
2202
2203 VERBOSE("No parent selected for %s\n",
2204 stm32mp1_clk_parent_name[parent_id]);
2205
2206 return -1;
2207}
2208
2209static void secure_parent_clocks(unsigned long parent_id)
2210{
2211 int grandparent_id;
2212
2213 switch (parent_id) {
2214 case _PLL3_P:
2215 case _PLL3_Q:
2216 case _PLL3_R:
2217 stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
2218 break;
2219
2220 /* These clocks are always secure when RCC is secure */
2221 case _ACLK:
2222 case _HCLK2:
2223 case _HCLK6:
2224 case _PCLK4:
2225 case _PCLK5:
2226 case _PLL1_P:
2227 case _PLL1_Q:
2228 case _PLL1_R:
2229 case _PLL2_P:
2230 case _PLL2_Q:
2231 case _PLL2_R:
2232 case _HSI:
2233 case _HSI_KER:
2234 case _LSI:
2235 case _CSI:
2236 case _CSI_KER:
2237 case _HSE:
2238 case _HSE_KER:
2239 case _HSE_KER_DIV2:
Gabriel Fernandez4e3a51a2021-07-27 15:39:16 +02002240 case _HSE_RTC:
Etienne Carriere1368ada2020-05-13 11:49:49 +02002241 case _LSE:
2242 break;
2243
2244 default:
2245 VERBOSE("Cannot secure parent clock %s\n",
2246 stm32mp1_clk_parent_name[parent_id]);
2247 panic();
2248 }
2249
2250 grandparent_id = get_parent_id_parent(parent_id);
2251 if (grandparent_id >= 0) {
2252 secure_parent_clocks(grandparent_id);
2253 }
2254}
2255
2256void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
2257{
2258 int parent_id;
2259
2260 if (!stm32mp1_rcc_is_secure()) {
2261 return;
2262 }
2263
2264 switch (clock_id) {
2265 case PLL1:
2266 case PLL2:
2267 /* PLL1/PLL2 are always secure: nothing to do */
2268 break;
2269 case PLL3:
2270 stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
2271 break;
2272 case PLL4:
2273 ERROR("PLL4 cannot be secured\n");
2274 panic();
2275 break;
2276 default:
2277 /* Others are expected gateable clock */
2278 parent_id = stm32mp1_clk_get_parent(clock_id);
2279 if (parent_id < 0) {
2280 INFO("No parent found for clock %lu\n", clock_id);
2281 } else {
2282 secure_parent_clocks(parent_id);
2283 }
2284 break;
2285 }
2286}
2287#endif /* STM32MP_SHARED_RESOURCES */
Yann Gautier9aea69e2018-07-24 17:13:36 +02002288
Yann Gautierc7f9e962019-05-20 14:39:26 +02002289static void sync_earlyboot_clocks_state(void)
2290{
Etienne Carriere2a756c22019-12-08 08:23:35 +01002291 unsigned int idx;
2292 const unsigned long secure_enable[] = {
2293 AXIDCG,
2294 BSEC,
2295 DDRC1, DDRC1LP,
2296 DDRC2, DDRC2LP,
2297 DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
2298 DDRPHYC, DDRPHYCLP,
Lionel Debievecfa88cc2019-09-02 18:15:45 +02002299 RTCAPB,
Etienne Carriere2a756c22019-12-08 08:23:35 +01002300 TZC1, TZC2,
2301 TZPC,
2302 STGEN_K,
2303 };
2304
2305 for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
2306 stm32mp_clk_enable(secure_enable[idx]);
2307 }
Yann Gautierc7f9e962019-05-20 14:39:26 +02002308}
2309
Yann Gautiera205a5c2021-08-30 15:06:54 +02002310static const struct clk_ops stm32mp_clk_ops = {
2311 .enable = stm32mp_clk_enable,
2312 .disable = stm32mp_clk_disable,
2313 .is_enabled = stm32mp_clk_is_enabled,
2314 .get_rate = stm32mp_clk_get_rate,
2315 .get_parent = stm32mp1_clk_get_parent,
2316};
2317
Yann Gautier9aea69e2018-07-24 17:13:36 +02002318int stm32mp1_clk_probe(void)
2319{
Yann Gautier9aea69e2018-07-24 17:13:36 +02002320 stm32mp1_osc_init();
2321
Yann Gautierc7f9e962019-05-20 14:39:26 +02002322 sync_earlyboot_clocks_state();
2323
Yann Gautiera205a5c2021-08-30 15:06:54 +02002324 clk_register(&stm32mp_clk_ops);
2325
Yann Gautier9aea69e2018-07-24 17:13:36 +02002326 return 0;
2327}