1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu #include <stdio.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <arch.h> 13*91f16700Schasinglulu #include <arch_helpers.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <common/fdt_wrappers.h> 16*91f16700Schasinglulu #include <drivers/clk.h> 17*91f16700Schasinglulu #include <drivers/delay_timer.h> 18*91f16700Schasinglulu #include <drivers/st/stm32mp_clkfunc.h> 19*91f16700Schasinglulu #include <drivers/st/stm32mp1_clk.h> 20*91f16700Schasinglulu #include <drivers/st/stm32mp1_rcc.h> 21*91f16700Schasinglulu #include <dt-bindings/clock/stm32mp1-clksrc.h> 22*91f16700Schasinglulu #include <lib/mmio.h> 23*91f16700Schasinglulu #include <lib/spinlock.h> 24*91f16700Schasinglulu #include <lib/utils_def.h> 25*91f16700Schasinglulu #include <libfdt.h> 26*91f16700Schasinglulu #include <plat/common/platform.h> 27*91f16700Schasinglulu 28*91f16700Schasinglulu #include <platform_def.h> 29*91f16700Schasinglulu 30*91f16700Schasinglulu #define MAX_HSI_HZ 64000000 31*91f16700Schasinglulu #define USB_PHY_48_MHZ 48000000 32*91f16700Schasinglulu 33*91f16700Schasinglulu #define TIMEOUT_US_200MS U(200000) 34*91f16700Schasinglulu #define TIMEOUT_US_1S U(1000000) 35*91f16700Schasinglulu 36*91f16700Schasinglulu #define PLLRDY_TIMEOUT TIMEOUT_US_200MS 37*91f16700Schasinglulu #define CLKSRC_TIMEOUT TIMEOUT_US_200MS 38*91f16700Schasinglulu #define CLKDIV_TIMEOUT TIMEOUT_US_200MS 39*91f16700Schasinglulu #define HSIDIV_TIMEOUT TIMEOUT_US_200MS 40*91f16700Schasinglulu #define OSCRDY_TIMEOUT TIMEOUT_US_1S 41*91f16700Schasinglulu 42*91f16700Schasinglulu const char *stm32mp_osc_node_label[NB_OSC] = { 43*91f16700Schasinglulu [_LSI] = "clk-lsi", 44*91f16700Schasinglulu [_LSE] = "clk-lse", 45*91f16700Schasinglulu [_HSI] = "clk-hsi", 46*91f16700Schasinglulu [_HSE] = "clk-hse", 47*91f16700Schasinglulu [_CSI] = "clk-csi", 48*91f16700Schasinglulu [_I2S_CKIN] = "i2s_ckin", 49*91f16700Schasinglulu }; 50*91f16700Schasinglulu 51*91f16700Schasinglulu enum stm32mp1_parent_id { 52*91f16700Schasinglulu /* Oscillators are defined in enum stm32mp_osc_id */ 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* Other parent source */ 55*91f16700Schasinglulu _HSI_KER = NB_OSC, 56*91f16700Schasinglulu _HSE_KER, 57*91f16700Schasinglulu _HSE_KER_DIV2, 58*91f16700Schasinglulu _HSE_RTC, 59*91f16700Schasinglulu _CSI_KER, 60*91f16700Schasinglulu _PLL1_P, 61*91f16700Schasinglulu _PLL1_Q, 62*91f16700Schasinglulu _PLL1_R, 63*91f16700Schasinglulu _PLL2_P, 64*91f16700Schasinglulu _PLL2_Q, 65*91f16700Schasinglulu _PLL2_R, 66*91f16700Schasinglulu _PLL3_P, 67*91f16700Schasinglulu _PLL3_Q, 68*91f16700Schasinglulu _PLL3_R, 69*91f16700Schasinglulu _PLL4_P, 70*91f16700Schasinglulu _PLL4_Q, 71*91f16700Schasinglulu _PLL4_R, 72*91f16700Schasinglulu _ACLK, 73*91f16700Schasinglulu _PCLK1, 74*91f16700Schasinglulu _PCLK2, 75*91f16700Schasinglulu _PCLK3, 76*91f16700Schasinglulu _PCLK4, 77*91f16700Schasinglulu _PCLK5, 78*91f16700Schasinglulu _HCLK6, 79*91f16700Schasinglulu _HCLK2, 80*91f16700Schasinglulu _CK_PER, 81*91f16700Schasinglulu _CK_MPU, 82*91f16700Schasinglulu _CK_MCU, 83*91f16700Schasinglulu _USB_PHY_48, 84*91f16700Schasinglulu _PARENT_NB, 85*91f16700Schasinglulu _UNKNOWN_ID = 0xff, 86*91f16700Schasinglulu }; 87*91f16700Schasinglulu 88*91f16700Schasinglulu /* Lists only the parent clock we are interested in */ 89*91f16700Schasinglulu enum stm32mp1_parent_sel { 90*91f16700Schasinglulu _I2C12_SEL, 91*91f16700Schasinglulu _I2C35_SEL, 92*91f16700Schasinglulu _STGEN_SEL, 93*91f16700Schasinglulu _I2C46_SEL, 94*91f16700Schasinglulu _SPI6_SEL, 95*91f16700Schasinglulu _UART1_SEL, 96*91f16700Schasinglulu _RNG1_SEL, 97*91f16700Schasinglulu _UART6_SEL, 98*91f16700Schasinglulu _UART24_SEL, 99*91f16700Schasinglulu _UART35_SEL, 100*91f16700Schasinglulu _UART78_SEL, 101*91f16700Schasinglulu _SDMMC12_SEL, 102*91f16700Schasinglulu _SDMMC3_SEL, 103*91f16700Schasinglulu _QSPI_SEL, 104*91f16700Schasinglulu _FMC_SEL, 105*91f16700Schasinglulu _AXIS_SEL, 106*91f16700Schasinglulu _MCUS_SEL, 107*91f16700Schasinglulu _USBPHY_SEL, 108*91f16700Schasinglulu _USBO_SEL, 109*91f16700Schasinglulu _MPU_SEL, 110*91f16700Schasinglulu _CKPER_SEL, 111*91f16700Schasinglulu _RTC_SEL, 112*91f16700Schasinglulu _PARENT_SEL_NB, 113*91f16700Schasinglulu _UNKNOWN_SEL = 0xff, 114*91f16700Schasinglulu }; 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* State the parent clock ID straight related to a clock */ 117*91f16700Schasinglulu static const uint8_t parent_id_clock_id[_PARENT_NB] = { 118*91f16700Schasinglulu [_HSE] = CK_HSE, 119*91f16700Schasinglulu [_HSI] = CK_HSI, 120*91f16700Schasinglulu [_CSI] = CK_CSI, 121*91f16700Schasinglulu [_LSE] = CK_LSE, 122*91f16700Schasinglulu [_LSI] = CK_LSI, 123*91f16700Schasinglulu [_I2S_CKIN] = _UNKNOWN_ID, 124*91f16700Schasinglulu [_USB_PHY_48] = _UNKNOWN_ID, 125*91f16700Schasinglulu [_HSI_KER] = CK_HSI, 126*91f16700Schasinglulu [_HSE_KER] = CK_HSE, 127*91f16700Schasinglulu [_HSE_KER_DIV2] = CK_HSE_DIV2, 128*91f16700Schasinglulu [_HSE_RTC] = _UNKNOWN_ID, 129*91f16700Schasinglulu [_CSI_KER] = CK_CSI, 130*91f16700Schasinglulu [_PLL1_P] = PLL1_P, 131*91f16700Schasinglulu [_PLL1_Q] = PLL1_Q, 132*91f16700Schasinglulu [_PLL1_R] = PLL1_R, 133*91f16700Schasinglulu [_PLL2_P] = PLL2_P, 134*91f16700Schasinglulu [_PLL2_Q] = PLL2_Q, 135*91f16700Schasinglulu [_PLL2_R] = PLL2_R, 136*91f16700Schasinglulu [_PLL3_P] = PLL3_P, 137*91f16700Schasinglulu [_PLL3_Q] = PLL3_Q, 138*91f16700Schasinglulu [_PLL3_R] = PLL3_R, 139*91f16700Schasinglulu [_PLL4_P] = PLL4_P, 140*91f16700Schasinglulu [_PLL4_Q] = PLL4_Q, 141*91f16700Schasinglulu [_PLL4_R] = PLL4_R, 142*91f16700Schasinglulu [_ACLK] = CK_AXI, 143*91f16700Schasinglulu [_PCLK1] = CK_AXI, 144*91f16700Schasinglulu [_PCLK2] = CK_AXI, 145*91f16700Schasinglulu [_PCLK3] = CK_AXI, 146*91f16700Schasinglulu [_PCLK4] = CK_AXI, 147*91f16700Schasinglulu [_PCLK5] = CK_AXI, 148*91f16700Schasinglulu [_CK_PER] = CK_PER, 149*91f16700Schasinglulu [_CK_MPU] = CK_MPU, 150*91f16700Schasinglulu [_CK_MCU] = CK_MCU, 151*91f16700Schasinglulu }; 152*91f16700Schasinglulu 153*91f16700Schasinglulu static unsigned int clock_id2parent_id(unsigned long id) 154*91f16700Schasinglulu { 155*91f16700Schasinglulu unsigned int n; 156*91f16700Schasinglulu 157*91f16700Schasinglulu for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { 158*91f16700Schasinglulu if (parent_id_clock_id[n] == id) { 159*91f16700Schasinglulu return n; 160*91f16700Schasinglulu } 161*91f16700Schasinglulu } 162*91f16700Schasinglulu 163*91f16700Schasinglulu return _UNKNOWN_ID; 164*91f16700Schasinglulu } 165*91f16700Schasinglulu 166*91f16700Schasinglulu enum stm32mp1_pll_id { 167*91f16700Schasinglulu _PLL1, 168*91f16700Schasinglulu _PLL2, 169*91f16700Schasinglulu _PLL3, 170*91f16700Schasinglulu _PLL4, 171*91f16700Schasinglulu _PLL_NB 172*91f16700Schasinglulu }; 173*91f16700Schasinglulu 174*91f16700Schasinglulu enum stm32mp1_div_id { 175*91f16700Schasinglulu _DIV_P, 176*91f16700Schasinglulu _DIV_Q, 177*91f16700Schasinglulu _DIV_R, 178*91f16700Schasinglulu _DIV_NB, 179*91f16700Schasinglulu }; 180*91f16700Schasinglulu 181*91f16700Schasinglulu enum stm32mp1_clksrc_id { 182*91f16700Schasinglulu CLKSRC_MPU, 183*91f16700Schasinglulu CLKSRC_AXI, 184*91f16700Schasinglulu CLKSRC_MCU, 185*91f16700Schasinglulu CLKSRC_PLL12, 186*91f16700Schasinglulu CLKSRC_PLL3, 187*91f16700Schasinglulu CLKSRC_PLL4, 188*91f16700Schasinglulu CLKSRC_RTC, 189*91f16700Schasinglulu CLKSRC_MCO1, 190*91f16700Schasinglulu CLKSRC_MCO2, 191*91f16700Schasinglulu CLKSRC_NB 192*91f16700Schasinglulu }; 193*91f16700Schasinglulu 194*91f16700Schasinglulu enum stm32mp1_clkdiv_id { 195*91f16700Schasinglulu CLKDIV_MPU, 196*91f16700Schasinglulu CLKDIV_AXI, 197*91f16700Schasinglulu CLKDIV_MCU, 198*91f16700Schasinglulu CLKDIV_APB1, 199*91f16700Schasinglulu CLKDIV_APB2, 200*91f16700Schasinglulu CLKDIV_APB3, 201*91f16700Schasinglulu CLKDIV_APB4, 202*91f16700Schasinglulu CLKDIV_APB5, 203*91f16700Schasinglulu CLKDIV_RTC, 204*91f16700Schasinglulu CLKDIV_MCO1, 205*91f16700Schasinglulu CLKDIV_MCO2, 206*91f16700Schasinglulu CLKDIV_NB 207*91f16700Schasinglulu }; 208*91f16700Schasinglulu 209*91f16700Schasinglulu enum stm32mp1_pllcfg { 210*91f16700Schasinglulu PLLCFG_M, 211*91f16700Schasinglulu PLLCFG_N, 212*91f16700Schasinglulu PLLCFG_P, 213*91f16700Schasinglulu PLLCFG_Q, 214*91f16700Schasinglulu PLLCFG_R, 215*91f16700Schasinglulu PLLCFG_O, 216*91f16700Schasinglulu PLLCFG_NB 217*91f16700Schasinglulu }; 218*91f16700Schasinglulu 219*91f16700Schasinglulu enum stm32mp1_pllcsg { 220*91f16700Schasinglulu PLLCSG_MOD_PER, 221*91f16700Schasinglulu PLLCSG_INC_STEP, 222*91f16700Schasinglulu PLLCSG_SSCG_MODE, 223*91f16700Schasinglulu PLLCSG_NB 224*91f16700Schasinglulu }; 225*91f16700Schasinglulu 226*91f16700Schasinglulu enum stm32mp1_plltype { 227*91f16700Schasinglulu PLL_800, 228*91f16700Schasinglulu PLL_1600, 229*91f16700Schasinglulu PLL_TYPE_NB 230*91f16700Schasinglulu }; 231*91f16700Schasinglulu 232*91f16700Schasinglulu struct stm32mp1_pll { 233*91f16700Schasinglulu uint8_t refclk_min; 234*91f16700Schasinglulu uint8_t refclk_max; 235*91f16700Schasinglulu }; 236*91f16700Schasinglulu 237*91f16700Schasinglulu struct stm32mp1_clk_gate { 238*91f16700Schasinglulu uint16_t offset; 239*91f16700Schasinglulu uint8_t bit; 240*91f16700Schasinglulu uint8_t index; 241*91f16700Schasinglulu uint8_t set_clr; 242*91f16700Schasinglulu uint8_t secure; 243*91f16700Schasinglulu uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ 244*91f16700Schasinglulu uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ 245*91f16700Schasinglulu }; 246*91f16700Schasinglulu 247*91f16700Schasinglulu struct stm32mp1_clk_sel { 248*91f16700Schasinglulu uint16_t offset; 249*91f16700Schasinglulu uint8_t src; 250*91f16700Schasinglulu uint8_t msk; 251*91f16700Schasinglulu uint8_t nb_parent; 252*91f16700Schasinglulu const uint8_t *parent; 253*91f16700Schasinglulu }; 254*91f16700Schasinglulu 255*91f16700Schasinglulu #define REFCLK_SIZE 4 256*91f16700Schasinglulu struct stm32mp1_clk_pll { 257*91f16700Schasinglulu enum stm32mp1_plltype plltype; 258*91f16700Schasinglulu uint16_t rckxselr; 259*91f16700Schasinglulu uint16_t pllxcfgr1; 260*91f16700Schasinglulu uint16_t pllxcfgr2; 261*91f16700Schasinglulu uint16_t pllxfracr; 262*91f16700Schasinglulu uint16_t pllxcr; 263*91f16700Schasinglulu uint16_t pllxcsgr; 264*91f16700Schasinglulu enum stm32mp_osc_id refclk[REFCLK_SIZE]; 265*91f16700Schasinglulu }; 266*91f16700Schasinglulu 267*91f16700Schasinglulu /* Clocks with selectable source and non set/clr register access */ 268*91f16700Schasinglulu #define _CLK_SELEC(sec, off, b, idx, s) \ 269*91f16700Schasinglulu { \ 270*91f16700Schasinglulu .offset = (off), \ 271*91f16700Schasinglulu .bit = (b), \ 272*91f16700Schasinglulu .index = (idx), \ 273*91f16700Schasinglulu .set_clr = 0, \ 274*91f16700Schasinglulu .secure = (sec), \ 275*91f16700Schasinglulu .sel = (s), \ 276*91f16700Schasinglulu .fixed = _UNKNOWN_ID, \ 277*91f16700Schasinglulu } 278*91f16700Schasinglulu 279*91f16700Schasinglulu /* Clocks with fixed source and non set/clr register access */ 280*91f16700Schasinglulu #define _CLK_FIXED(sec, off, b, idx, f) \ 281*91f16700Schasinglulu { \ 282*91f16700Schasinglulu .offset = (off), \ 283*91f16700Schasinglulu .bit = (b), \ 284*91f16700Schasinglulu .index = (idx), \ 285*91f16700Schasinglulu .set_clr = 0, \ 286*91f16700Schasinglulu .secure = (sec), \ 287*91f16700Schasinglulu .sel = _UNKNOWN_SEL, \ 288*91f16700Schasinglulu .fixed = (f), \ 289*91f16700Schasinglulu } 290*91f16700Schasinglulu 291*91f16700Schasinglulu /* Clocks with selectable source and set/clr register access */ 292*91f16700Schasinglulu #define _CLK_SC_SELEC(sec, off, b, idx, s) \ 293*91f16700Schasinglulu { \ 294*91f16700Schasinglulu .offset = (off), \ 295*91f16700Schasinglulu .bit = (b), \ 296*91f16700Schasinglulu .index = (idx), \ 297*91f16700Schasinglulu .set_clr = 1, \ 298*91f16700Schasinglulu .secure = (sec), \ 299*91f16700Schasinglulu .sel = (s), \ 300*91f16700Schasinglulu .fixed = _UNKNOWN_ID, \ 301*91f16700Schasinglulu } 302*91f16700Schasinglulu 303*91f16700Schasinglulu /* Clocks with fixed source and set/clr register access */ 304*91f16700Schasinglulu #define _CLK_SC_FIXED(sec, off, b, idx, f) \ 305*91f16700Schasinglulu { \ 306*91f16700Schasinglulu .offset = (off), \ 307*91f16700Schasinglulu .bit = (b), \ 308*91f16700Schasinglulu .index = (idx), \ 309*91f16700Schasinglulu .set_clr = 1, \ 310*91f16700Schasinglulu .secure = (sec), \ 311*91f16700Schasinglulu .sel = _UNKNOWN_SEL, \ 312*91f16700Schasinglulu .fixed = (f), \ 313*91f16700Schasinglulu } 314*91f16700Schasinglulu 315*91f16700Schasinglulu #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ 316*91f16700Schasinglulu [_ ## _label ## _SEL] = { \ 317*91f16700Schasinglulu .offset = _rcc_selr, \ 318*91f16700Schasinglulu .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ 319*91f16700Schasinglulu .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ 320*91f16700Schasinglulu (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ 321*91f16700Schasinglulu .parent = (_parents), \ 322*91f16700Schasinglulu .nb_parent = ARRAY_SIZE(_parents) \ 323*91f16700Schasinglulu } 324*91f16700Schasinglulu 325*91f16700Schasinglulu #define _CLK_PLL(idx, type, off1, off2, off3, \ 326*91f16700Schasinglulu off4, off5, off6, \ 327*91f16700Schasinglulu p1, p2, p3, p4) \ 328*91f16700Schasinglulu [(idx)] = { \ 329*91f16700Schasinglulu .plltype = (type), \ 330*91f16700Schasinglulu .rckxselr = (off1), \ 331*91f16700Schasinglulu .pllxcfgr1 = (off2), \ 332*91f16700Schasinglulu .pllxcfgr2 = (off3), \ 333*91f16700Schasinglulu .pllxfracr = (off4), \ 334*91f16700Schasinglulu .pllxcr = (off5), \ 335*91f16700Schasinglulu .pllxcsgr = (off6), \ 336*91f16700Schasinglulu .refclk[0] = (p1), \ 337*91f16700Schasinglulu .refclk[1] = (p2), \ 338*91f16700Schasinglulu .refclk[2] = (p3), \ 339*91f16700Schasinglulu .refclk[3] = (p4), \ 340*91f16700Schasinglulu } 341*91f16700Schasinglulu 342*91f16700Schasinglulu #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) 343*91f16700Schasinglulu 344*91f16700Schasinglulu #define SEC 1 345*91f16700Schasinglulu #define N_S 0 346*91f16700Schasinglulu 347*91f16700Schasinglulu static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { 348*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), 349*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), 350*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), 351*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), 352*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), 353*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), 354*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), 355*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), 356*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), 357*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), 358*91f16700Schasinglulu _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), 359*91f16700Schasinglulu 360*91f16700Schasinglulu #if defined(IMAGE_BL32) 361*91f16700Schasinglulu _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), 362*91f16700Schasinglulu #endif 363*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), 364*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), 365*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), 366*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), 367*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), 368*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), 369*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), 370*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), 371*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), 372*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), 373*91f16700Schasinglulu 374*91f16700Schasinglulu #if defined(IMAGE_BL32) 375*91f16700Schasinglulu _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), 376*91f16700Schasinglulu #endif 377*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), 378*91f16700Schasinglulu 379*91f16700Schasinglulu _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), 380*91f16700Schasinglulu 381*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), 382*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), 383*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), 384*91f16700Schasinglulu 385*91f16700Schasinglulu _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), 386*91f16700Schasinglulu _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), 387*91f16700Schasinglulu _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), 388*91f16700Schasinglulu _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), 389*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), 390*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), 391*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), 392*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), 393*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), 394*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), 395*91f16700Schasinglulu _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), 396*91f16700Schasinglulu 397*91f16700Schasinglulu #if defined(IMAGE_BL32) 398*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), 399*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), 400*91f16700Schasinglulu #endif 401*91f16700Schasinglulu 402*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), 403*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), 404*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), 405*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), 406*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), 407*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), 408*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), 409*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), 410*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), 411*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), 412*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), 413*91f16700Schasinglulu 414*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), 415*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), 416*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), 417*91f16700Schasinglulu _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), 418*91f16700Schasinglulu _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), 419*91f16700Schasinglulu 420*91f16700Schasinglulu #if defined(IMAGE_BL2) 421*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), 422*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), 423*91f16700Schasinglulu #endif 424*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), 425*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), 426*91f16700Schasinglulu #if defined(IMAGE_BL32) 427*91f16700Schasinglulu _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), 428*91f16700Schasinglulu #endif 429*91f16700Schasinglulu 430*91f16700Schasinglulu _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), 431*91f16700Schasinglulu _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), 432*91f16700Schasinglulu }; 433*91f16700Schasinglulu 434*91f16700Schasinglulu static const uint8_t i2c12_parents[] = { 435*91f16700Schasinglulu _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 436*91f16700Schasinglulu }; 437*91f16700Schasinglulu 438*91f16700Schasinglulu static const uint8_t i2c35_parents[] = { 439*91f16700Schasinglulu _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 440*91f16700Schasinglulu }; 441*91f16700Schasinglulu 442*91f16700Schasinglulu static const uint8_t stgen_parents[] = { 443*91f16700Schasinglulu _HSI_KER, _HSE_KER 444*91f16700Schasinglulu }; 445*91f16700Schasinglulu 446*91f16700Schasinglulu static const uint8_t i2c46_parents[] = { 447*91f16700Schasinglulu _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER 448*91f16700Schasinglulu }; 449*91f16700Schasinglulu 450*91f16700Schasinglulu static const uint8_t spi6_parents[] = { 451*91f16700Schasinglulu _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q 452*91f16700Schasinglulu }; 453*91f16700Schasinglulu 454*91f16700Schasinglulu static const uint8_t usart1_parents[] = { 455*91f16700Schasinglulu _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER 456*91f16700Schasinglulu }; 457*91f16700Schasinglulu 458*91f16700Schasinglulu static const uint8_t rng1_parents[] = { 459*91f16700Schasinglulu _CSI, _PLL4_R, _LSE, _LSI 460*91f16700Schasinglulu }; 461*91f16700Schasinglulu 462*91f16700Schasinglulu static const uint8_t uart6_parents[] = { 463*91f16700Schasinglulu _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 464*91f16700Schasinglulu }; 465*91f16700Schasinglulu 466*91f16700Schasinglulu static const uint8_t uart234578_parents[] = { 467*91f16700Schasinglulu _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 468*91f16700Schasinglulu }; 469*91f16700Schasinglulu 470*91f16700Schasinglulu static const uint8_t sdmmc12_parents[] = { 471*91f16700Schasinglulu _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER 472*91f16700Schasinglulu }; 473*91f16700Schasinglulu 474*91f16700Schasinglulu static const uint8_t sdmmc3_parents[] = { 475*91f16700Schasinglulu _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER 476*91f16700Schasinglulu }; 477*91f16700Schasinglulu 478*91f16700Schasinglulu static const uint8_t qspi_parents[] = { 479*91f16700Schasinglulu _ACLK, _PLL3_R, _PLL4_P, _CK_PER 480*91f16700Schasinglulu }; 481*91f16700Schasinglulu 482*91f16700Schasinglulu static const uint8_t fmc_parents[] = { 483*91f16700Schasinglulu _ACLK, _PLL3_R, _PLL4_P, _CK_PER 484*91f16700Schasinglulu }; 485*91f16700Schasinglulu 486*91f16700Schasinglulu static const uint8_t axiss_parents[] = { 487*91f16700Schasinglulu _HSI, _HSE, _PLL2_P 488*91f16700Schasinglulu }; 489*91f16700Schasinglulu 490*91f16700Schasinglulu static const uint8_t mcuss_parents[] = { 491*91f16700Schasinglulu _HSI, _HSE, _CSI, _PLL3_P 492*91f16700Schasinglulu }; 493*91f16700Schasinglulu 494*91f16700Schasinglulu static const uint8_t usbphy_parents[] = { 495*91f16700Schasinglulu _HSE_KER, _PLL4_R, _HSE_KER_DIV2 496*91f16700Schasinglulu }; 497*91f16700Schasinglulu 498*91f16700Schasinglulu static const uint8_t usbo_parents[] = { 499*91f16700Schasinglulu _PLL4_R, _USB_PHY_48 500*91f16700Schasinglulu }; 501*91f16700Schasinglulu 502*91f16700Schasinglulu static const uint8_t mpu_parents[] = { 503*91f16700Schasinglulu _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ 504*91f16700Schasinglulu }; 505*91f16700Schasinglulu 506*91f16700Schasinglulu static const uint8_t per_parents[] = { 507*91f16700Schasinglulu _HSI, _HSE, _CSI, 508*91f16700Schasinglulu }; 509*91f16700Schasinglulu 510*91f16700Schasinglulu static const uint8_t rtc_parents[] = { 511*91f16700Schasinglulu _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC 512*91f16700Schasinglulu }; 513*91f16700Schasinglulu 514*91f16700Schasinglulu static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { 515*91f16700Schasinglulu _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), 516*91f16700Schasinglulu _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), 517*91f16700Schasinglulu _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), 518*91f16700Schasinglulu _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), 519*91f16700Schasinglulu _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), 520*91f16700Schasinglulu _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), 521*91f16700Schasinglulu _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), 522*91f16700Schasinglulu _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), 523*91f16700Schasinglulu _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents), 524*91f16700Schasinglulu _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), 525*91f16700Schasinglulu _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), 526*91f16700Schasinglulu _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), 527*91f16700Schasinglulu _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), 528*91f16700Schasinglulu _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), 529*91f16700Schasinglulu _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), 530*91f16700Schasinglulu _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), 531*91f16700Schasinglulu _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), 532*91f16700Schasinglulu _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), 533*91f16700Schasinglulu _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents), 534*91f16700Schasinglulu _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), 535*91f16700Schasinglulu _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), 536*91f16700Schasinglulu _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), 537*91f16700Schasinglulu }; 538*91f16700Schasinglulu 539*91f16700Schasinglulu /* Define characteristic of PLL according type */ 540*91f16700Schasinglulu #define DIVN_MIN 24 541*91f16700Schasinglulu static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { 542*91f16700Schasinglulu [PLL_800] = { 543*91f16700Schasinglulu .refclk_min = 4, 544*91f16700Schasinglulu .refclk_max = 16, 545*91f16700Schasinglulu }, 546*91f16700Schasinglulu [PLL_1600] = { 547*91f16700Schasinglulu .refclk_min = 8, 548*91f16700Schasinglulu .refclk_max = 16, 549*91f16700Schasinglulu }, 550*91f16700Schasinglulu }; 551*91f16700Schasinglulu 552*91f16700Schasinglulu /* PLLNCFGR2 register divider by output */ 553*91f16700Schasinglulu static const uint8_t pllncfgr2[_DIV_NB] = { 554*91f16700Schasinglulu [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, 555*91f16700Schasinglulu [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, 556*91f16700Schasinglulu [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, 557*91f16700Schasinglulu }; 558*91f16700Schasinglulu 559*91f16700Schasinglulu static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { 560*91f16700Schasinglulu _CLK_PLL(_PLL1, PLL_1600, 561*91f16700Schasinglulu RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, 562*91f16700Schasinglulu RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, 563*91f16700Schasinglulu _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 564*91f16700Schasinglulu _CLK_PLL(_PLL2, PLL_1600, 565*91f16700Schasinglulu RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, 566*91f16700Schasinglulu RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, 567*91f16700Schasinglulu _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 568*91f16700Schasinglulu _CLK_PLL(_PLL3, PLL_800, 569*91f16700Schasinglulu RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, 570*91f16700Schasinglulu RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, 571*91f16700Schasinglulu _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), 572*91f16700Schasinglulu _CLK_PLL(_PLL4, PLL_800, 573*91f16700Schasinglulu RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, 574*91f16700Schasinglulu RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, 575*91f16700Schasinglulu _HSI, _HSE, _CSI, _I2S_CKIN), 576*91f16700Schasinglulu }; 577*91f16700Schasinglulu 578*91f16700Schasinglulu /* Prescaler table lookups for clock computation */ 579*91f16700Schasinglulu /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ 580*91f16700Schasinglulu static const uint8_t stm32mp1_mcu_div[16] = { 581*91f16700Schasinglulu 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 582*91f16700Schasinglulu }; 583*91f16700Schasinglulu 584*91f16700Schasinglulu /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ 585*91f16700Schasinglulu #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div 586*91f16700Schasinglulu #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div 587*91f16700Schasinglulu static const uint8_t stm32mp1_mpu_apbx_div[8] = { 588*91f16700Schasinglulu 0, 1, 2, 3, 4, 4, 4, 4 589*91f16700Schasinglulu }; 590*91f16700Schasinglulu 591*91f16700Schasinglulu /* div = /1 /2 /3 /4 */ 592*91f16700Schasinglulu static const uint8_t stm32mp1_axi_div[8] = { 593*91f16700Schasinglulu 1, 2, 3, 4, 4, 4, 4, 4 594*91f16700Schasinglulu }; 595*91f16700Schasinglulu 596*91f16700Schasinglulu static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { 597*91f16700Schasinglulu [_HSI] = "HSI", 598*91f16700Schasinglulu [_HSE] = "HSE", 599*91f16700Schasinglulu [_CSI] = "CSI", 600*91f16700Schasinglulu [_LSI] = "LSI", 601*91f16700Schasinglulu [_LSE] = "LSE", 602*91f16700Schasinglulu [_I2S_CKIN] = "I2S_CKIN", 603*91f16700Schasinglulu [_HSI_KER] = "HSI_KER", 604*91f16700Schasinglulu [_HSE_KER] = "HSE_KER", 605*91f16700Schasinglulu [_HSE_KER_DIV2] = "HSE_KER_DIV2", 606*91f16700Schasinglulu [_HSE_RTC] = "HSE_RTC", 607*91f16700Schasinglulu [_CSI_KER] = "CSI_KER", 608*91f16700Schasinglulu [_PLL1_P] = "PLL1_P", 609*91f16700Schasinglulu [_PLL1_Q] = "PLL1_Q", 610*91f16700Schasinglulu [_PLL1_R] = "PLL1_R", 611*91f16700Schasinglulu [_PLL2_P] = "PLL2_P", 612*91f16700Schasinglulu [_PLL2_Q] = "PLL2_Q", 613*91f16700Schasinglulu [_PLL2_R] = "PLL2_R", 614*91f16700Schasinglulu [_PLL3_P] = "PLL3_P", 615*91f16700Schasinglulu [_PLL3_Q] = "PLL3_Q", 616*91f16700Schasinglulu [_PLL3_R] = "PLL3_R", 617*91f16700Schasinglulu [_PLL4_P] = "PLL4_P", 618*91f16700Schasinglulu [_PLL4_Q] = "PLL4_Q", 619*91f16700Schasinglulu [_PLL4_R] = "PLL4_R", 620*91f16700Schasinglulu [_ACLK] = "ACLK", 621*91f16700Schasinglulu [_PCLK1] = "PCLK1", 622*91f16700Schasinglulu [_PCLK2] = "PCLK2", 623*91f16700Schasinglulu [_PCLK3] = "PCLK3", 624*91f16700Schasinglulu [_PCLK4] = "PCLK4", 625*91f16700Schasinglulu [_PCLK5] = "PCLK5", 626*91f16700Schasinglulu [_HCLK6] = "KCLK6", 627*91f16700Schasinglulu [_HCLK2] = "HCLK2", 628*91f16700Schasinglulu [_CK_PER] = "CK_PER", 629*91f16700Schasinglulu [_CK_MPU] = "CK_MPU", 630*91f16700Schasinglulu [_CK_MCU] = "CK_MCU", 631*91f16700Schasinglulu [_USB_PHY_48] = "USB_PHY_48", 632*91f16700Schasinglulu }; 633*91f16700Schasinglulu 634*91f16700Schasinglulu /* RCC clock device driver private */ 635*91f16700Schasinglulu static unsigned long stm32mp1_osc[NB_OSC]; 636*91f16700Schasinglulu static struct spinlock reg_lock; 637*91f16700Schasinglulu static unsigned int gate_refcounts[NB_GATES]; 638*91f16700Schasinglulu static struct spinlock refcount_lock; 639*91f16700Schasinglulu 640*91f16700Schasinglulu static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) 641*91f16700Schasinglulu { 642*91f16700Schasinglulu return &stm32mp1_clk_gate[idx]; 643*91f16700Schasinglulu } 644*91f16700Schasinglulu 645*91f16700Schasinglulu #if defined(IMAGE_BL32) 646*91f16700Schasinglulu static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) 647*91f16700Schasinglulu { 648*91f16700Schasinglulu return gate->secure == N_S; 649*91f16700Schasinglulu } 650*91f16700Schasinglulu #endif 651*91f16700Schasinglulu 652*91f16700Schasinglulu static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) 653*91f16700Schasinglulu { 654*91f16700Schasinglulu return &stm32mp1_clk_sel[idx]; 655*91f16700Schasinglulu } 656*91f16700Schasinglulu 657*91f16700Schasinglulu static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) 658*91f16700Schasinglulu { 659*91f16700Schasinglulu return &stm32mp1_clk_pll[idx]; 660*91f16700Schasinglulu } 661*91f16700Schasinglulu 662*91f16700Schasinglulu static void stm32mp1_clk_lock(struct spinlock *lock) 663*91f16700Schasinglulu { 664*91f16700Schasinglulu if (stm32mp_lock_available()) { 665*91f16700Schasinglulu /* Assume interrupts are masked */ 666*91f16700Schasinglulu spin_lock(lock); 667*91f16700Schasinglulu } 668*91f16700Schasinglulu } 669*91f16700Schasinglulu 670*91f16700Schasinglulu static void stm32mp1_clk_unlock(struct spinlock *lock) 671*91f16700Schasinglulu { 672*91f16700Schasinglulu if (stm32mp_lock_available()) { 673*91f16700Schasinglulu spin_unlock(lock); 674*91f16700Schasinglulu } 675*91f16700Schasinglulu } 676*91f16700Schasinglulu 677*91f16700Schasinglulu bool stm32mp1_rcc_is_secure(void) 678*91f16700Schasinglulu { 679*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 680*91f16700Schasinglulu uint32_t mask = RCC_TZCR_TZEN; 681*91f16700Schasinglulu 682*91f16700Schasinglulu return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 683*91f16700Schasinglulu } 684*91f16700Schasinglulu 685*91f16700Schasinglulu bool stm32mp1_rcc_is_mckprot(void) 686*91f16700Schasinglulu { 687*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 688*91f16700Schasinglulu uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; 689*91f16700Schasinglulu 690*91f16700Schasinglulu return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 691*91f16700Schasinglulu } 692*91f16700Schasinglulu 693*91f16700Schasinglulu void stm32mp1_clk_rcc_regs_lock(void) 694*91f16700Schasinglulu { 695*91f16700Schasinglulu stm32mp1_clk_lock(®_lock); 696*91f16700Schasinglulu } 697*91f16700Schasinglulu 698*91f16700Schasinglulu void stm32mp1_clk_rcc_regs_unlock(void) 699*91f16700Schasinglulu { 700*91f16700Schasinglulu stm32mp1_clk_unlock(®_lock); 701*91f16700Schasinglulu } 702*91f16700Schasinglulu 703*91f16700Schasinglulu static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) 704*91f16700Schasinglulu { 705*91f16700Schasinglulu if (idx >= NB_OSC) { 706*91f16700Schasinglulu return 0; 707*91f16700Schasinglulu } 708*91f16700Schasinglulu 709*91f16700Schasinglulu return stm32mp1_osc[idx]; 710*91f16700Schasinglulu } 711*91f16700Schasinglulu 712*91f16700Schasinglulu static int stm32mp1_clk_get_gated_id(unsigned long id) 713*91f16700Schasinglulu { 714*91f16700Schasinglulu unsigned int i; 715*91f16700Schasinglulu 716*91f16700Schasinglulu for (i = 0U; i < NB_GATES; i++) { 717*91f16700Schasinglulu if (gate_ref(i)->index == id) { 718*91f16700Schasinglulu return i; 719*91f16700Schasinglulu } 720*91f16700Schasinglulu } 721*91f16700Schasinglulu 722*91f16700Schasinglulu ERROR("%s: clk id %lu not found\n", __func__, id); 723*91f16700Schasinglulu 724*91f16700Schasinglulu return -EINVAL; 725*91f16700Schasinglulu } 726*91f16700Schasinglulu 727*91f16700Schasinglulu static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) 728*91f16700Schasinglulu { 729*91f16700Schasinglulu return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); 730*91f16700Schasinglulu } 731*91f16700Schasinglulu 732*91f16700Schasinglulu static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) 733*91f16700Schasinglulu { 734*91f16700Schasinglulu return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); 735*91f16700Schasinglulu } 736*91f16700Schasinglulu 737*91f16700Schasinglulu static int stm32mp1_clk_get_parent(unsigned long id) 738*91f16700Schasinglulu { 739*91f16700Schasinglulu const struct stm32mp1_clk_sel *sel; 740*91f16700Schasinglulu uint32_t p_sel; 741*91f16700Schasinglulu int i; 742*91f16700Schasinglulu enum stm32mp1_parent_id p; 743*91f16700Schasinglulu enum stm32mp1_parent_sel s; 744*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 745*91f16700Schasinglulu 746*91f16700Schasinglulu /* Few non gateable clock have a static parent ID, find them */ 747*91f16700Schasinglulu i = (int)clock_id2parent_id(id); 748*91f16700Schasinglulu if (i != _UNKNOWN_ID) { 749*91f16700Schasinglulu return i; 750*91f16700Schasinglulu } 751*91f16700Schasinglulu 752*91f16700Schasinglulu i = stm32mp1_clk_get_gated_id(id); 753*91f16700Schasinglulu if (i < 0) { 754*91f16700Schasinglulu panic(); 755*91f16700Schasinglulu } 756*91f16700Schasinglulu 757*91f16700Schasinglulu p = stm32mp1_clk_get_fixed_parent(i); 758*91f16700Schasinglulu if (p < _PARENT_NB) { 759*91f16700Schasinglulu return (int)p; 760*91f16700Schasinglulu } 761*91f16700Schasinglulu 762*91f16700Schasinglulu s = stm32mp1_clk_get_sel(i); 763*91f16700Schasinglulu if (s == _UNKNOWN_SEL) { 764*91f16700Schasinglulu return -EINVAL; 765*91f16700Schasinglulu } 766*91f16700Schasinglulu if (s >= _PARENT_SEL_NB) { 767*91f16700Schasinglulu panic(); 768*91f16700Schasinglulu } 769*91f16700Schasinglulu 770*91f16700Schasinglulu sel = clk_sel_ref(s); 771*91f16700Schasinglulu p_sel = (mmio_read_32(rcc_base + sel->offset) & 772*91f16700Schasinglulu (sel->msk << sel->src)) >> sel->src; 773*91f16700Schasinglulu if (p_sel < sel->nb_parent) { 774*91f16700Schasinglulu return (int)sel->parent[p_sel]; 775*91f16700Schasinglulu } 776*91f16700Schasinglulu 777*91f16700Schasinglulu return -EINVAL; 778*91f16700Schasinglulu } 779*91f16700Schasinglulu 780*91f16700Schasinglulu static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) 781*91f16700Schasinglulu { 782*91f16700Schasinglulu uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); 783*91f16700Schasinglulu uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; 784*91f16700Schasinglulu 785*91f16700Schasinglulu return stm32mp1_clk_get_fixed(pll->refclk[src]); 786*91f16700Schasinglulu } 787*91f16700Schasinglulu 788*91f16700Schasinglulu /* 789*91f16700Schasinglulu * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL 790*91f16700Schasinglulu * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) 791*91f16700Schasinglulu * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) 792*91f16700Schasinglulu * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) 793*91f16700Schasinglulu */ 794*91f16700Schasinglulu static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) 795*91f16700Schasinglulu { 796*91f16700Schasinglulu unsigned long refclk, fvco; 797*91f16700Schasinglulu uint32_t cfgr1, fracr, divm, divn; 798*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 799*91f16700Schasinglulu 800*91f16700Schasinglulu cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); 801*91f16700Schasinglulu fracr = mmio_read_32(rcc_base + pll->pllxfracr); 802*91f16700Schasinglulu 803*91f16700Schasinglulu divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; 804*91f16700Schasinglulu divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; 805*91f16700Schasinglulu 806*91f16700Schasinglulu refclk = stm32mp1_pll_get_fref(pll); 807*91f16700Schasinglulu 808*91f16700Schasinglulu /* 809*91f16700Schasinglulu * With FRACV : 810*91f16700Schasinglulu * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) 811*91f16700Schasinglulu * Without FRACV 812*91f16700Schasinglulu * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) 813*91f16700Schasinglulu */ 814*91f16700Schasinglulu if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { 815*91f16700Schasinglulu uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> 816*91f16700Schasinglulu RCC_PLLNFRACR_FRACV_SHIFT; 817*91f16700Schasinglulu unsigned long long numerator, denominator; 818*91f16700Schasinglulu 819*91f16700Schasinglulu numerator = (((unsigned long long)divn + 1U) << 13) + fracv; 820*91f16700Schasinglulu numerator = refclk * numerator; 821*91f16700Schasinglulu denominator = ((unsigned long long)divm + 1U) << 13; 822*91f16700Schasinglulu fvco = (unsigned long)(numerator / denominator); 823*91f16700Schasinglulu } else { 824*91f16700Schasinglulu fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); 825*91f16700Schasinglulu } 826*91f16700Schasinglulu 827*91f16700Schasinglulu return fvco; 828*91f16700Schasinglulu } 829*91f16700Schasinglulu 830*91f16700Schasinglulu static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, 831*91f16700Schasinglulu enum stm32mp1_div_id div_id) 832*91f16700Schasinglulu { 833*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 834*91f16700Schasinglulu unsigned long dfout; 835*91f16700Schasinglulu uint32_t cfgr2, divy; 836*91f16700Schasinglulu 837*91f16700Schasinglulu if (div_id >= _DIV_NB) { 838*91f16700Schasinglulu return 0; 839*91f16700Schasinglulu } 840*91f16700Schasinglulu 841*91f16700Schasinglulu cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); 842*91f16700Schasinglulu divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; 843*91f16700Schasinglulu 844*91f16700Schasinglulu dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); 845*91f16700Schasinglulu 846*91f16700Schasinglulu return dfout; 847*91f16700Schasinglulu } 848*91f16700Schasinglulu 849*91f16700Schasinglulu static unsigned long get_clock_rate(int p) 850*91f16700Schasinglulu { 851*91f16700Schasinglulu uint32_t reg, clkdiv; 852*91f16700Schasinglulu unsigned long clock = 0; 853*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 854*91f16700Schasinglulu 855*91f16700Schasinglulu switch (p) { 856*91f16700Schasinglulu case _CK_MPU: 857*91f16700Schasinglulu /* MPU sub system */ 858*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_MPCKSELR); 859*91f16700Schasinglulu switch (reg & RCC_SELR_SRC_MASK) { 860*91f16700Schasinglulu case RCC_MPCKSELR_HSI: 861*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSI); 862*91f16700Schasinglulu break; 863*91f16700Schasinglulu case RCC_MPCKSELR_HSE: 864*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE); 865*91f16700Schasinglulu break; 866*91f16700Schasinglulu case RCC_MPCKSELR_PLL: 867*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 868*91f16700Schasinglulu break; 869*91f16700Schasinglulu case RCC_MPCKSELR_PLL_MPUDIV: 870*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 871*91f16700Schasinglulu 872*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); 873*91f16700Schasinglulu clkdiv = reg & RCC_MPUDIV_MASK; 874*91f16700Schasinglulu clock >>= stm32mp1_mpu_div[clkdiv]; 875*91f16700Schasinglulu break; 876*91f16700Schasinglulu default: 877*91f16700Schasinglulu break; 878*91f16700Schasinglulu } 879*91f16700Schasinglulu break; 880*91f16700Schasinglulu /* AXI sub system */ 881*91f16700Schasinglulu case _ACLK: 882*91f16700Schasinglulu case _HCLK2: 883*91f16700Schasinglulu case _HCLK6: 884*91f16700Schasinglulu case _PCLK4: 885*91f16700Schasinglulu case _PCLK5: 886*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); 887*91f16700Schasinglulu switch (reg & RCC_SELR_SRC_MASK) { 888*91f16700Schasinglulu case RCC_ASSCKSELR_HSI: 889*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSI); 890*91f16700Schasinglulu break; 891*91f16700Schasinglulu case RCC_ASSCKSELR_HSE: 892*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE); 893*91f16700Schasinglulu break; 894*91f16700Schasinglulu case RCC_ASSCKSELR_PLL: 895*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 896*91f16700Schasinglulu break; 897*91f16700Schasinglulu default: 898*91f16700Schasinglulu break; 899*91f16700Schasinglulu } 900*91f16700Schasinglulu 901*91f16700Schasinglulu /* System clock divider */ 902*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_AXIDIVR); 903*91f16700Schasinglulu clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; 904*91f16700Schasinglulu 905*91f16700Schasinglulu switch (p) { 906*91f16700Schasinglulu case _PCLK4: 907*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_APB4DIVR); 908*91f16700Schasinglulu clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 909*91f16700Schasinglulu break; 910*91f16700Schasinglulu case _PCLK5: 911*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_APB5DIVR); 912*91f16700Schasinglulu clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 913*91f16700Schasinglulu break; 914*91f16700Schasinglulu default: 915*91f16700Schasinglulu break; 916*91f16700Schasinglulu } 917*91f16700Schasinglulu break; 918*91f16700Schasinglulu /* MCU sub system */ 919*91f16700Schasinglulu case _CK_MCU: 920*91f16700Schasinglulu case _PCLK1: 921*91f16700Schasinglulu case _PCLK2: 922*91f16700Schasinglulu case _PCLK3: 923*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); 924*91f16700Schasinglulu switch (reg & RCC_SELR_SRC_MASK) { 925*91f16700Schasinglulu case RCC_MSSCKSELR_HSI: 926*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSI); 927*91f16700Schasinglulu break; 928*91f16700Schasinglulu case RCC_MSSCKSELR_HSE: 929*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE); 930*91f16700Schasinglulu break; 931*91f16700Schasinglulu case RCC_MSSCKSELR_CSI: 932*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_CSI); 933*91f16700Schasinglulu break; 934*91f16700Schasinglulu case RCC_MSSCKSELR_PLL: 935*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 936*91f16700Schasinglulu break; 937*91f16700Schasinglulu default: 938*91f16700Schasinglulu break; 939*91f16700Schasinglulu } 940*91f16700Schasinglulu 941*91f16700Schasinglulu /* MCU clock divider */ 942*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_MCUDIVR); 943*91f16700Schasinglulu clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; 944*91f16700Schasinglulu 945*91f16700Schasinglulu switch (p) { 946*91f16700Schasinglulu case _PCLK1: 947*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_APB1DIVR); 948*91f16700Schasinglulu clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 949*91f16700Schasinglulu break; 950*91f16700Schasinglulu case _PCLK2: 951*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_APB2DIVR); 952*91f16700Schasinglulu clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 953*91f16700Schasinglulu break; 954*91f16700Schasinglulu case _PCLK3: 955*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_APB3DIVR); 956*91f16700Schasinglulu clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 957*91f16700Schasinglulu break; 958*91f16700Schasinglulu case _CK_MCU: 959*91f16700Schasinglulu default: 960*91f16700Schasinglulu break; 961*91f16700Schasinglulu } 962*91f16700Schasinglulu break; 963*91f16700Schasinglulu case _CK_PER: 964*91f16700Schasinglulu reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); 965*91f16700Schasinglulu switch (reg & RCC_SELR_SRC_MASK) { 966*91f16700Schasinglulu case RCC_CPERCKSELR_HSI: 967*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSI); 968*91f16700Schasinglulu break; 969*91f16700Schasinglulu case RCC_CPERCKSELR_HSE: 970*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE); 971*91f16700Schasinglulu break; 972*91f16700Schasinglulu case RCC_CPERCKSELR_CSI: 973*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_CSI); 974*91f16700Schasinglulu break; 975*91f16700Schasinglulu default: 976*91f16700Schasinglulu break; 977*91f16700Schasinglulu } 978*91f16700Schasinglulu break; 979*91f16700Schasinglulu case _HSI: 980*91f16700Schasinglulu case _HSI_KER: 981*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSI); 982*91f16700Schasinglulu break; 983*91f16700Schasinglulu case _CSI: 984*91f16700Schasinglulu case _CSI_KER: 985*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_CSI); 986*91f16700Schasinglulu break; 987*91f16700Schasinglulu case _HSE: 988*91f16700Schasinglulu case _HSE_KER: 989*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE); 990*91f16700Schasinglulu break; 991*91f16700Schasinglulu case _HSE_KER_DIV2: 992*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE) >> 1; 993*91f16700Schasinglulu break; 994*91f16700Schasinglulu case _HSE_RTC: 995*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_HSE); 996*91f16700Schasinglulu clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; 997*91f16700Schasinglulu break; 998*91f16700Schasinglulu case _LSI: 999*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_LSI); 1000*91f16700Schasinglulu break; 1001*91f16700Schasinglulu case _LSE: 1002*91f16700Schasinglulu clock = stm32mp1_clk_get_fixed(_LSE); 1003*91f16700Schasinglulu break; 1004*91f16700Schasinglulu /* PLL */ 1005*91f16700Schasinglulu case _PLL1_P: 1006*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 1007*91f16700Schasinglulu break; 1008*91f16700Schasinglulu case _PLL1_Q: 1009*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); 1010*91f16700Schasinglulu break; 1011*91f16700Schasinglulu case _PLL1_R: 1012*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); 1013*91f16700Schasinglulu break; 1014*91f16700Schasinglulu case _PLL2_P: 1015*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 1016*91f16700Schasinglulu break; 1017*91f16700Schasinglulu case _PLL2_Q: 1018*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); 1019*91f16700Schasinglulu break; 1020*91f16700Schasinglulu case _PLL2_R: 1021*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); 1022*91f16700Schasinglulu break; 1023*91f16700Schasinglulu case _PLL3_P: 1024*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 1025*91f16700Schasinglulu break; 1026*91f16700Schasinglulu case _PLL3_Q: 1027*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); 1028*91f16700Schasinglulu break; 1029*91f16700Schasinglulu case _PLL3_R: 1030*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); 1031*91f16700Schasinglulu break; 1032*91f16700Schasinglulu case _PLL4_P: 1033*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); 1034*91f16700Schasinglulu break; 1035*91f16700Schasinglulu case _PLL4_Q: 1036*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); 1037*91f16700Schasinglulu break; 1038*91f16700Schasinglulu case _PLL4_R: 1039*91f16700Schasinglulu clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); 1040*91f16700Schasinglulu break; 1041*91f16700Schasinglulu /* Other */ 1042*91f16700Schasinglulu case _USB_PHY_48: 1043*91f16700Schasinglulu clock = USB_PHY_48_MHZ; 1044*91f16700Schasinglulu break; 1045*91f16700Schasinglulu default: 1046*91f16700Schasinglulu break; 1047*91f16700Schasinglulu } 1048*91f16700Schasinglulu 1049*91f16700Schasinglulu return clock; 1050*91f16700Schasinglulu } 1051*91f16700Schasinglulu 1052*91f16700Schasinglulu static void __clk_enable(struct stm32mp1_clk_gate const *gate) 1053*91f16700Schasinglulu { 1054*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1055*91f16700Schasinglulu 1056*91f16700Schasinglulu VERBOSE("Enable clock %u\n", gate->index); 1057*91f16700Schasinglulu 1058*91f16700Schasinglulu if (gate->set_clr != 0U) { 1059*91f16700Schasinglulu mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); 1060*91f16700Schasinglulu } else { 1061*91f16700Schasinglulu mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); 1062*91f16700Schasinglulu } 1063*91f16700Schasinglulu } 1064*91f16700Schasinglulu 1065*91f16700Schasinglulu static void __clk_disable(struct stm32mp1_clk_gate const *gate) 1066*91f16700Schasinglulu { 1067*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1068*91f16700Schasinglulu 1069*91f16700Schasinglulu VERBOSE("Disable clock %u\n", gate->index); 1070*91f16700Schasinglulu 1071*91f16700Schasinglulu if (gate->set_clr != 0U) { 1072*91f16700Schasinglulu mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, 1073*91f16700Schasinglulu BIT(gate->bit)); 1074*91f16700Schasinglulu } else { 1075*91f16700Schasinglulu mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); 1076*91f16700Schasinglulu } 1077*91f16700Schasinglulu } 1078*91f16700Schasinglulu 1079*91f16700Schasinglulu static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) 1080*91f16700Schasinglulu { 1081*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1082*91f16700Schasinglulu 1083*91f16700Schasinglulu return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); 1084*91f16700Schasinglulu } 1085*91f16700Schasinglulu 1086*91f16700Schasinglulu /* Oscillators and PLLs are not gated at runtime */ 1087*91f16700Schasinglulu static bool clock_is_always_on(unsigned long id) 1088*91f16700Schasinglulu { 1089*91f16700Schasinglulu switch (id) { 1090*91f16700Schasinglulu case CK_HSE: 1091*91f16700Schasinglulu case CK_CSI: 1092*91f16700Schasinglulu case CK_LSI: 1093*91f16700Schasinglulu case CK_LSE: 1094*91f16700Schasinglulu case CK_HSI: 1095*91f16700Schasinglulu case CK_HSE_DIV2: 1096*91f16700Schasinglulu case PLL1_Q: 1097*91f16700Schasinglulu case PLL1_R: 1098*91f16700Schasinglulu case PLL2_P: 1099*91f16700Schasinglulu case PLL2_Q: 1100*91f16700Schasinglulu case PLL2_R: 1101*91f16700Schasinglulu case PLL3_P: 1102*91f16700Schasinglulu case PLL3_Q: 1103*91f16700Schasinglulu case PLL3_R: 1104*91f16700Schasinglulu case CK_AXI: 1105*91f16700Schasinglulu case CK_MPU: 1106*91f16700Schasinglulu case CK_MCU: 1107*91f16700Schasinglulu case RTC: 1108*91f16700Schasinglulu return true; 1109*91f16700Schasinglulu default: 1110*91f16700Schasinglulu return false; 1111*91f16700Schasinglulu } 1112*91f16700Schasinglulu } 1113*91f16700Schasinglulu 1114*91f16700Schasinglulu static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) 1115*91f16700Schasinglulu { 1116*91f16700Schasinglulu const struct stm32mp1_clk_gate *gate; 1117*91f16700Schasinglulu int i; 1118*91f16700Schasinglulu 1119*91f16700Schasinglulu if (clock_is_always_on(id)) { 1120*91f16700Schasinglulu return; 1121*91f16700Schasinglulu } 1122*91f16700Schasinglulu 1123*91f16700Schasinglulu i = stm32mp1_clk_get_gated_id(id); 1124*91f16700Schasinglulu if (i < 0) { 1125*91f16700Schasinglulu ERROR("Clock %lu can't be enabled\n", id); 1126*91f16700Schasinglulu panic(); 1127*91f16700Schasinglulu } 1128*91f16700Schasinglulu 1129*91f16700Schasinglulu gate = gate_ref(i); 1130*91f16700Schasinglulu 1131*91f16700Schasinglulu if (!with_refcnt) { 1132*91f16700Schasinglulu __clk_enable(gate); 1133*91f16700Schasinglulu return; 1134*91f16700Schasinglulu } 1135*91f16700Schasinglulu 1136*91f16700Schasinglulu #if defined(IMAGE_BL32) 1137*91f16700Schasinglulu if (gate_is_non_secure(gate)) { 1138*91f16700Schasinglulu /* Enable non-secure clock w/o any refcounting */ 1139*91f16700Schasinglulu __clk_enable(gate); 1140*91f16700Schasinglulu return; 1141*91f16700Schasinglulu } 1142*91f16700Schasinglulu #endif 1143*91f16700Schasinglulu 1144*91f16700Schasinglulu stm32mp1_clk_lock(&refcount_lock); 1145*91f16700Schasinglulu 1146*91f16700Schasinglulu if (gate_refcounts[i] == 0U) { 1147*91f16700Schasinglulu __clk_enable(gate); 1148*91f16700Schasinglulu } 1149*91f16700Schasinglulu 1150*91f16700Schasinglulu gate_refcounts[i]++; 1151*91f16700Schasinglulu if (gate_refcounts[i] == UINT_MAX) { 1152*91f16700Schasinglulu ERROR("Clock %lu refcount reached max value\n", id); 1153*91f16700Schasinglulu panic(); 1154*91f16700Schasinglulu } 1155*91f16700Schasinglulu 1156*91f16700Schasinglulu stm32mp1_clk_unlock(&refcount_lock); 1157*91f16700Schasinglulu } 1158*91f16700Schasinglulu 1159*91f16700Schasinglulu static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) 1160*91f16700Schasinglulu { 1161*91f16700Schasinglulu const struct stm32mp1_clk_gate *gate; 1162*91f16700Schasinglulu int i; 1163*91f16700Schasinglulu 1164*91f16700Schasinglulu if (clock_is_always_on(id)) { 1165*91f16700Schasinglulu return; 1166*91f16700Schasinglulu } 1167*91f16700Schasinglulu 1168*91f16700Schasinglulu i = stm32mp1_clk_get_gated_id(id); 1169*91f16700Schasinglulu if (i < 0) { 1170*91f16700Schasinglulu ERROR("Clock %lu can't be disabled\n", id); 1171*91f16700Schasinglulu panic(); 1172*91f16700Schasinglulu } 1173*91f16700Schasinglulu 1174*91f16700Schasinglulu gate = gate_ref(i); 1175*91f16700Schasinglulu 1176*91f16700Schasinglulu if (!with_refcnt) { 1177*91f16700Schasinglulu __clk_disable(gate); 1178*91f16700Schasinglulu return; 1179*91f16700Schasinglulu } 1180*91f16700Schasinglulu 1181*91f16700Schasinglulu #if defined(IMAGE_BL32) 1182*91f16700Schasinglulu if (gate_is_non_secure(gate)) { 1183*91f16700Schasinglulu /* Don't disable non-secure clocks */ 1184*91f16700Schasinglulu return; 1185*91f16700Schasinglulu } 1186*91f16700Schasinglulu #endif 1187*91f16700Schasinglulu 1188*91f16700Schasinglulu stm32mp1_clk_lock(&refcount_lock); 1189*91f16700Schasinglulu 1190*91f16700Schasinglulu if (gate_refcounts[i] == 0U) { 1191*91f16700Schasinglulu ERROR("Clock %lu refcount reached 0\n", id); 1192*91f16700Schasinglulu panic(); 1193*91f16700Schasinglulu } 1194*91f16700Schasinglulu gate_refcounts[i]--; 1195*91f16700Schasinglulu 1196*91f16700Schasinglulu if (gate_refcounts[i] == 0U) { 1197*91f16700Schasinglulu __clk_disable(gate); 1198*91f16700Schasinglulu } 1199*91f16700Schasinglulu 1200*91f16700Schasinglulu stm32mp1_clk_unlock(&refcount_lock); 1201*91f16700Schasinglulu } 1202*91f16700Schasinglulu 1203*91f16700Schasinglulu static int stm32mp_clk_enable(unsigned long id) 1204*91f16700Schasinglulu { 1205*91f16700Schasinglulu __stm32mp1_clk_enable(id, true); 1206*91f16700Schasinglulu 1207*91f16700Schasinglulu return 0; 1208*91f16700Schasinglulu } 1209*91f16700Schasinglulu 1210*91f16700Schasinglulu static void stm32mp_clk_disable(unsigned long id) 1211*91f16700Schasinglulu { 1212*91f16700Schasinglulu __stm32mp1_clk_disable(id, true); 1213*91f16700Schasinglulu } 1214*91f16700Schasinglulu 1215*91f16700Schasinglulu static bool stm32mp_clk_is_enabled(unsigned long id) 1216*91f16700Schasinglulu { 1217*91f16700Schasinglulu int i; 1218*91f16700Schasinglulu 1219*91f16700Schasinglulu if (clock_is_always_on(id)) { 1220*91f16700Schasinglulu return true; 1221*91f16700Schasinglulu } 1222*91f16700Schasinglulu 1223*91f16700Schasinglulu i = stm32mp1_clk_get_gated_id(id); 1224*91f16700Schasinglulu if (i < 0) { 1225*91f16700Schasinglulu panic(); 1226*91f16700Schasinglulu } 1227*91f16700Schasinglulu 1228*91f16700Schasinglulu return __clk_is_enabled(gate_ref(i)); 1229*91f16700Schasinglulu } 1230*91f16700Schasinglulu 1231*91f16700Schasinglulu static unsigned long stm32mp_clk_get_rate(unsigned long id) 1232*91f16700Schasinglulu { 1233*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1234*91f16700Schasinglulu int p = stm32mp1_clk_get_parent(id); 1235*91f16700Schasinglulu uint32_t prescaler, timpre; 1236*91f16700Schasinglulu unsigned long parent_rate; 1237*91f16700Schasinglulu 1238*91f16700Schasinglulu if (p < 0) { 1239*91f16700Schasinglulu return 0; 1240*91f16700Schasinglulu } 1241*91f16700Schasinglulu 1242*91f16700Schasinglulu parent_rate = get_clock_rate(p); 1243*91f16700Schasinglulu 1244*91f16700Schasinglulu switch (id) { 1245*91f16700Schasinglulu case TIM2_K: 1246*91f16700Schasinglulu case TIM3_K: 1247*91f16700Schasinglulu case TIM4_K: 1248*91f16700Schasinglulu case TIM5_K: 1249*91f16700Schasinglulu case TIM6_K: 1250*91f16700Schasinglulu case TIM7_K: 1251*91f16700Schasinglulu case TIM12_K: 1252*91f16700Schasinglulu case TIM13_K: 1253*91f16700Schasinglulu case TIM14_K: 1254*91f16700Schasinglulu prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & 1255*91f16700Schasinglulu RCC_APBXDIV_MASK; 1256*91f16700Schasinglulu timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & 1257*91f16700Schasinglulu RCC_TIMGXPRER_TIMGXPRE; 1258*91f16700Schasinglulu break; 1259*91f16700Schasinglulu 1260*91f16700Schasinglulu case TIM1_K: 1261*91f16700Schasinglulu case TIM8_K: 1262*91f16700Schasinglulu case TIM15_K: 1263*91f16700Schasinglulu case TIM16_K: 1264*91f16700Schasinglulu case TIM17_K: 1265*91f16700Schasinglulu prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & 1266*91f16700Schasinglulu RCC_APBXDIV_MASK; 1267*91f16700Schasinglulu timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & 1268*91f16700Schasinglulu RCC_TIMGXPRER_TIMGXPRE; 1269*91f16700Schasinglulu break; 1270*91f16700Schasinglulu 1271*91f16700Schasinglulu default: 1272*91f16700Schasinglulu return parent_rate; 1273*91f16700Schasinglulu } 1274*91f16700Schasinglulu 1275*91f16700Schasinglulu if (prescaler == 0U) { 1276*91f16700Schasinglulu return parent_rate; 1277*91f16700Schasinglulu } 1278*91f16700Schasinglulu 1279*91f16700Schasinglulu return parent_rate * (timpre + 1U) * 2U; 1280*91f16700Schasinglulu } 1281*91f16700Schasinglulu 1282*91f16700Schasinglulu static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) 1283*91f16700Schasinglulu { 1284*91f16700Schasinglulu uintptr_t address = stm32mp_rcc_base() + offset; 1285*91f16700Schasinglulu 1286*91f16700Schasinglulu if (enable) { 1287*91f16700Schasinglulu mmio_setbits_32(address, mask_on); 1288*91f16700Schasinglulu } else { 1289*91f16700Schasinglulu mmio_clrbits_32(address, mask_on); 1290*91f16700Schasinglulu } 1291*91f16700Schasinglulu } 1292*91f16700Schasinglulu 1293*91f16700Schasinglulu static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) 1294*91f16700Schasinglulu { 1295*91f16700Schasinglulu uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; 1296*91f16700Schasinglulu uintptr_t address = stm32mp_rcc_base() + offset; 1297*91f16700Schasinglulu 1298*91f16700Schasinglulu mmio_write_32(address, mask_on); 1299*91f16700Schasinglulu } 1300*91f16700Schasinglulu 1301*91f16700Schasinglulu static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) 1302*91f16700Schasinglulu { 1303*91f16700Schasinglulu uint64_t timeout; 1304*91f16700Schasinglulu uint32_t mask_test; 1305*91f16700Schasinglulu uintptr_t address = stm32mp_rcc_base() + offset; 1306*91f16700Schasinglulu 1307*91f16700Schasinglulu if (enable) { 1308*91f16700Schasinglulu mask_test = mask_rdy; 1309*91f16700Schasinglulu } else { 1310*91f16700Schasinglulu mask_test = 0; 1311*91f16700Schasinglulu } 1312*91f16700Schasinglulu 1313*91f16700Schasinglulu timeout = timeout_init_us(OSCRDY_TIMEOUT); 1314*91f16700Schasinglulu while ((mmio_read_32(address) & mask_rdy) != mask_test) { 1315*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 1316*91f16700Schasinglulu ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", 1317*91f16700Schasinglulu mask_rdy, address, enable, mmio_read_32(address)); 1318*91f16700Schasinglulu return -ETIMEDOUT; 1319*91f16700Schasinglulu } 1320*91f16700Schasinglulu } 1321*91f16700Schasinglulu 1322*91f16700Schasinglulu return 0; 1323*91f16700Schasinglulu } 1324*91f16700Schasinglulu 1325*91f16700Schasinglulu static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) 1326*91f16700Schasinglulu { 1327*91f16700Schasinglulu uint32_t value; 1328*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1329*91f16700Schasinglulu 1330*91f16700Schasinglulu if (digbyp) { 1331*91f16700Schasinglulu mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); 1332*91f16700Schasinglulu } 1333*91f16700Schasinglulu 1334*91f16700Schasinglulu if (bypass || digbyp) { 1335*91f16700Schasinglulu mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); 1336*91f16700Schasinglulu } 1337*91f16700Schasinglulu 1338*91f16700Schasinglulu /* 1339*91f16700Schasinglulu * Warning: not recommended to switch directly from "high drive" 1340*91f16700Schasinglulu * to "medium low drive", and vice-versa. 1341*91f16700Schasinglulu */ 1342*91f16700Schasinglulu value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> 1343*91f16700Schasinglulu RCC_BDCR_LSEDRV_SHIFT; 1344*91f16700Schasinglulu 1345*91f16700Schasinglulu while (value != lsedrv) { 1346*91f16700Schasinglulu if (value > lsedrv) { 1347*91f16700Schasinglulu value--; 1348*91f16700Schasinglulu } else { 1349*91f16700Schasinglulu value++; 1350*91f16700Schasinglulu } 1351*91f16700Schasinglulu 1352*91f16700Schasinglulu mmio_clrsetbits_32(rcc_base + RCC_BDCR, 1353*91f16700Schasinglulu RCC_BDCR_LSEDRV_MASK, 1354*91f16700Schasinglulu value << RCC_BDCR_LSEDRV_SHIFT); 1355*91f16700Schasinglulu } 1356*91f16700Schasinglulu 1357*91f16700Schasinglulu stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); 1358*91f16700Schasinglulu } 1359*91f16700Schasinglulu 1360*91f16700Schasinglulu static void stm32mp1_lse_wait(void) 1361*91f16700Schasinglulu { 1362*91f16700Schasinglulu if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { 1363*91f16700Schasinglulu VERBOSE("%s: failed\n", __func__); 1364*91f16700Schasinglulu } 1365*91f16700Schasinglulu } 1366*91f16700Schasinglulu 1367*91f16700Schasinglulu static void stm32mp1_lsi_set(bool enable) 1368*91f16700Schasinglulu { 1369*91f16700Schasinglulu stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); 1370*91f16700Schasinglulu 1371*91f16700Schasinglulu if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { 1372*91f16700Schasinglulu VERBOSE("%s: failed\n", __func__); 1373*91f16700Schasinglulu } 1374*91f16700Schasinglulu } 1375*91f16700Schasinglulu 1376*91f16700Schasinglulu static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) 1377*91f16700Schasinglulu { 1378*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1379*91f16700Schasinglulu 1380*91f16700Schasinglulu if (digbyp) { 1381*91f16700Schasinglulu mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); 1382*91f16700Schasinglulu } 1383*91f16700Schasinglulu 1384*91f16700Schasinglulu if (bypass || digbyp) { 1385*91f16700Schasinglulu mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); 1386*91f16700Schasinglulu } 1387*91f16700Schasinglulu 1388*91f16700Schasinglulu stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); 1389*91f16700Schasinglulu if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { 1390*91f16700Schasinglulu VERBOSE("%s: failed\n", __func__); 1391*91f16700Schasinglulu } 1392*91f16700Schasinglulu 1393*91f16700Schasinglulu if (css) { 1394*91f16700Schasinglulu mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); 1395*91f16700Schasinglulu } 1396*91f16700Schasinglulu 1397*91f16700Schasinglulu #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER 1398*91f16700Schasinglulu if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) && 1399*91f16700Schasinglulu (!(digbyp || bypass))) { 1400*91f16700Schasinglulu panic(); 1401*91f16700Schasinglulu } 1402*91f16700Schasinglulu #endif 1403*91f16700Schasinglulu } 1404*91f16700Schasinglulu 1405*91f16700Schasinglulu static void stm32mp1_csi_set(bool enable) 1406*91f16700Schasinglulu { 1407*91f16700Schasinglulu stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); 1408*91f16700Schasinglulu if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { 1409*91f16700Schasinglulu VERBOSE("%s: failed\n", __func__); 1410*91f16700Schasinglulu } 1411*91f16700Schasinglulu } 1412*91f16700Schasinglulu 1413*91f16700Schasinglulu static void stm32mp1_hsi_set(bool enable) 1414*91f16700Schasinglulu { 1415*91f16700Schasinglulu stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); 1416*91f16700Schasinglulu if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { 1417*91f16700Schasinglulu VERBOSE("%s: failed\n", __func__); 1418*91f16700Schasinglulu } 1419*91f16700Schasinglulu } 1420*91f16700Schasinglulu 1421*91f16700Schasinglulu static int stm32mp1_set_hsidiv(uint8_t hsidiv) 1422*91f16700Schasinglulu { 1423*91f16700Schasinglulu uint64_t timeout; 1424*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1425*91f16700Schasinglulu uintptr_t address = rcc_base + RCC_OCRDYR; 1426*91f16700Schasinglulu 1427*91f16700Schasinglulu mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, 1428*91f16700Schasinglulu RCC_HSICFGR_HSIDIV_MASK, 1429*91f16700Schasinglulu RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); 1430*91f16700Schasinglulu 1431*91f16700Schasinglulu timeout = timeout_init_us(HSIDIV_TIMEOUT); 1432*91f16700Schasinglulu while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { 1433*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 1434*91f16700Schasinglulu ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", 1435*91f16700Schasinglulu address, mmio_read_32(address)); 1436*91f16700Schasinglulu return -ETIMEDOUT; 1437*91f16700Schasinglulu } 1438*91f16700Schasinglulu } 1439*91f16700Schasinglulu 1440*91f16700Schasinglulu return 0; 1441*91f16700Schasinglulu } 1442*91f16700Schasinglulu 1443*91f16700Schasinglulu static int stm32mp1_hsidiv(unsigned long hsifreq) 1444*91f16700Schasinglulu { 1445*91f16700Schasinglulu uint8_t hsidiv; 1446*91f16700Schasinglulu uint32_t hsidivfreq = MAX_HSI_HZ; 1447*91f16700Schasinglulu 1448*91f16700Schasinglulu for (hsidiv = 0; hsidiv < 4U; hsidiv++) { 1449*91f16700Schasinglulu if (hsidivfreq == hsifreq) { 1450*91f16700Schasinglulu break; 1451*91f16700Schasinglulu } 1452*91f16700Schasinglulu 1453*91f16700Schasinglulu hsidivfreq /= 2U; 1454*91f16700Schasinglulu } 1455*91f16700Schasinglulu 1456*91f16700Schasinglulu if (hsidiv == 4U) { 1457*91f16700Schasinglulu ERROR("Invalid clk-hsi frequency\n"); 1458*91f16700Schasinglulu return -1; 1459*91f16700Schasinglulu } 1460*91f16700Schasinglulu 1461*91f16700Schasinglulu if (hsidiv != 0U) { 1462*91f16700Schasinglulu return stm32mp1_set_hsidiv(hsidiv); 1463*91f16700Schasinglulu } 1464*91f16700Schasinglulu 1465*91f16700Schasinglulu return 0; 1466*91f16700Schasinglulu } 1467*91f16700Schasinglulu 1468*91f16700Schasinglulu static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, 1469*91f16700Schasinglulu unsigned int clksrc, 1470*91f16700Schasinglulu uint32_t *pllcfg, int plloff) 1471*91f16700Schasinglulu { 1472*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1473*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1474*91f16700Schasinglulu uintptr_t pllxcr = rcc_base + pll->pllxcr; 1475*91f16700Schasinglulu enum stm32mp1_plltype type = pll->plltype; 1476*91f16700Schasinglulu uintptr_t clksrc_address = rcc_base + (clksrc >> 4); 1477*91f16700Schasinglulu unsigned long refclk; 1478*91f16700Schasinglulu uint32_t ifrge = 0U; 1479*91f16700Schasinglulu uint32_t src, value, fracv = 0; 1480*91f16700Schasinglulu void *fdt; 1481*91f16700Schasinglulu 1482*91f16700Schasinglulu /* Check PLL output */ 1483*91f16700Schasinglulu if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { 1484*91f16700Schasinglulu return false; 1485*91f16700Schasinglulu } 1486*91f16700Schasinglulu 1487*91f16700Schasinglulu /* Check current clksrc */ 1488*91f16700Schasinglulu src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; 1489*91f16700Schasinglulu if (src != (clksrc & RCC_SELR_SRC_MASK)) { 1490*91f16700Schasinglulu return false; 1491*91f16700Schasinglulu } 1492*91f16700Schasinglulu 1493*91f16700Schasinglulu /* Check Div */ 1494*91f16700Schasinglulu src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; 1495*91f16700Schasinglulu 1496*91f16700Schasinglulu refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 1497*91f16700Schasinglulu (pllcfg[PLLCFG_M] + 1U); 1498*91f16700Schasinglulu 1499*91f16700Schasinglulu if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 1500*91f16700Schasinglulu (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 1501*91f16700Schasinglulu return false; 1502*91f16700Schasinglulu } 1503*91f16700Schasinglulu 1504*91f16700Schasinglulu if ((type == PLL_800) && (refclk >= 8000000U)) { 1505*91f16700Schasinglulu ifrge = 1U; 1506*91f16700Schasinglulu } 1507*91f16700Schasinglulu 1508*91f16700Schasinglulu value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 1509*91f16700Schasinglulu RCC_PLLNCFGR1_DIVN_MASK; 1510*91f16700Schasinglulu value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 1511*91f16700Schasinglulu RCC_PLLNCFGR1_DIVM_MASK; 1512*91f16700Schasinglulu value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 1513*91f16700Schasinglulu RCC_PLLNCFGR1_IFRGE_MASK; 1514*91f16700Schasinglulu if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { 1515*91f16700Schasinglulu return false; 1516*91f16700Schasinglulu } 1517*91f16700Schasinglulu 1518*91f16700Schasinglulu /* Fractional configuration */ 1519*91f16700Schasinglulu if (fdt_get_address(&fdt) == 1) { 1520*91f16700Schasinglulu fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); 1521*91f16700Schasinglulu } 1522*91f16700Schasinglulu 1523*91f16700Schasinglulu value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 1524*91f16700Schasinglulu value |= RCC_PLLNFRACR_FRACLE; 1525*91f16700Schasinglulu if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { 1526*91f16700Schasinglulu return false; 1527*91f16700Schasinglulu } 1528*91f16700Schasinglulu 1529*91f16700Schasinglulu /* Output config */ 1530*91f16700Schasinglulu value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 1531*91f16700Schasinglulu RCC_PLLNCFGR2_DIVP_MASK; 1532*91f16700Schasinglulu value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 1533*91f16700Schasinglulu RCC_PLLNCFGR2_DIVQ_MASK; 1534*91f16700Schasinglulu value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 1535*91f16700Schasinglulu RCC_PLLNCFGR2_DIVR_MASK; 1536*91f16700Schasinglulu if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { 1537*91f16700Schasinglulu return false; 1538*91f16700Schasinglulu } 1539*91f16700Schasinglulu 1540*91f16700Schasinglulu return true; 1541*91f16700Schasinglulu } 1542*91f16700Schasinglulu 1543*91f16700Schasinglulu static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) 1544*91f16700Schasinglulu { 1545*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1546*91f16700Schasinglulu uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1547*91f16700Schasinglulu 1548*91f16700Schasinglulu /* Preserve RCC_PLLNCR_SSCG_CTRL value */ 1549*91f16700Schasinglulu mmio_clrsetbits_32(pllxcr, 1550*91f16700Schasinglulu RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 1551*91f16700Schasinglulu RCC_PLLNCR_DIVREN, 1552*91f16700Schasinglulu RCC_PLLNCR_PLLON); 1553*91f16700Schasinglulu } 1554*91f16700Schasinglulu 1555*91f16700Schasinglulu static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) 1556*91f16700Schasinglulu { 1557*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1558*91f16700Schasinglulu uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1559*91f16700Schasinglulu uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); 1560*91f16700Schasinglulu 1561*91f16700Schasinglulu /* Wait PLL lock */ 1562*91f16700Schasinglulu while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { 1563*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 1564*91f16700Schasinglulu ERROR("PLL%u start failed @ 0x%lx: 0x%x\n", 1565*91f16700Schasinglulu pll_id, pllxcr, mmio_read_32(pllxcr)); 1566*91f16700Schasinglulu return -ETIMEDOUT; 1567*91f16700Schasinglulu } 1568*91f16700Schasinglulu } 1569*91f16700Schasinglulu 1570*91f16700Schasinglulu /* Start the requested output */ 1571*91f16700Schasinglulu mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); 1572*91f16700Schasinglulu 1573*91f16700Schasinglulu return 0; 1574*91f16700Schasinglulu } 1575*91f16700Schasinglulu 1576*91f16700Schasinglulu static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) 1577*91f16700Schasinglulu { 1578*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1579*91f16700Schasinglulu uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1580*91f16700Schasinglulu uint64_t timeout; 1581*91f16700Schasinglulu 1582*91f16700Schasinglulu /* Stop all output */ 1583*91f16700Schasinglulu mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 1584*91f16700Schasinglulu RCC_PLLNCR_DIVREN); 1585*91f16700Schasinglulu 1586*91f16700Schasinglulu /* Stop PLL */ 1587*91f16700Schasinglulu mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); 1588*91f16700Schasinglulu 1589*91f16700Schasinglulu timeout = timeout_init_us(PLLRDY_TIMEOUT); 1590*91f16700Schasinglulu /* Wait PLL stopped */ 1591*91f16700Schasinglulu while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { 1592*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 1593*91f16700Schasinglulu ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n", 1594*91f16700Schasinglulu pll_id, pllxcr, mmio_read_32(pllxcr)); 1595*91f16700Schasinglulu return -ETIMEDOUT; 1596*91f16700Schasinglulu } 1597*91f16700Schasinglulu } 1598*91f16700Schasinglulu 1599*91f16700Schasinglulu return 0; 1600*91f16700Schasinglulu } 1601*91f16700Schasinglulu 1602*91f16700Schasinglulu static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, 1603*91f16700Schasinglulu uint32_t *pllcfg) 1604*91f16700Schasinglulu { 1605*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1606*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1607*91f16700Schasinglulu uint32_t value; 1608*91f16700Schasinglulu 1609*91f16700Schasinglulu value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 1610*91f16700Schasinglulu RCC_PLLNCFGR2_DIVP_MASK; 1611*91f16700Schasinglulu value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 1612*91f16700Schasinglulu RCC_PLLNCFGR2_DIVQ_MASK; 1613*91f16700Schasinglulu value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 1614*91f16700Schasinglulu RCC_PLLNCFGR2_DIVR_MASK; 1615*91f16700Schasinglulu mmio_write_32(rcc_base + pll->pllxcfgr2, value); 1616*91f16700Schasinglulu } 1617*91f16700Schasinglulu 1618*91f16700Schasinglulu static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, 1619*91f16700Schasinglulu uint32_t *pllcfg, uint32_t fracv) 1620*91f16700Schasinglulu { 1621*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1622*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1623*91f16700Schasinglulu enum stm32mp1_plltype type = pll->plltype; 1624*91f16700Schasinglulu unsigned long refclk; 1625*91f16700Schasinglulu uint32_t ifrge = 0; 1626*91f16700Schasinglulu uint32_t src, value; 1627*91f16700Schasinglulu 1628*91f16700Schasinglulu src = mmio_read_32(rcc_base + pll->rckxselr) & 1629*91f16700Schasinglulu RCC_SELR_REFCLK_SRC_MASK; 1630*91f16700Schasinglulu 1631*91f16700Schasinglulu refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 1632*91f16700Schasinglulu (pllcfg[PLLCFG_M] + 1U); 1633*91f16700Schasinglulu 1634*91f16700Schasinglulu if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 1635*91f16700Schasinglulu (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 1636*91f16700Schasinglulu return -EINVAL; 1637*91f16700Schasinglulu } 1638*91f16700Schasinglulu 1639*91f16700Schasinglulu if ((type == PLL_800) && (refclk >= 8000000U)) { 1640*91f16700Schasinglulu ifrge = 1U; 1641*91f16700Schasinglulu } 1642*91f16700Schasinglulu 1643*91f16700Schasinglulu value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 1644*91f16700Schasinglulu RCC_PLLNCFGR1_DIVN_MASK; 1645*91f16700Schasinglulu value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 1646*91f16700Schasinglulu RCC_PLLNCFGR1_DIVM_MASK; 1647*91f16700Schasinglulu value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 1648*91f16700Schasinglulu RCC_PLLNCFGR1_IFRGE_MASK; 1649*91f16700Schasinglulu mmio_write_32(rcc_base + pll->pllxcfgr1, value); 1650*91f16700Schasinglulu 1651*91f16700Schasinglulu /* Fractional configuration */ 1652*91f16700Schasinglulu value = 0; 1653*91f16700Schasinglulu mmio_write_32(rcc_base + pll->pllxfracr, value); 1654*91f16700Schasinglulu 1655*91f16700Schasinglulu value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 1656*91f16700Schasinglulu mmio_write_32(rcc_base + pll->pllxfracr, value); 1657*91f16700Schasinglulu 1658*91f16700Schasinglulu value |= RCC_PLLNFRACR_FRACLE; 1659*91f16700Schasinglulu mmio_write_32(rcc_base + pll->pllxfracr, value); 1660*91f16700Schasinglulu 1661*91f16700Schasinglulu stm32mp1_pll_config_output(pll_id, pllcfg); 1662*91f16700Schasinglulu 1663*91f16700Schasinglulu return 0; 1664*91f16700Schasinglulu } 1665*91f16700Schasinglulu 1666*91f16700Schasinglulu static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) 1667*91f16700Schasinglulu { 1668*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 1669*91f16700Schasinglulu uint32_t pllxcsg = 0; 1670*91f16700Schasinglulu 1671*91f16700Schasinglulu pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & 1672*91f16700Schasinglulu RCC_PLLNCSGR_MOD_PER_MASK; 1673*91f16700Schasinglulu 1674*91f16700Schasinglulu pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & 1675*91f16700Schasinglulu RCC_PLLNCSGR_INC_STEP_MASK; 1676*91f16700Schasinglulu 1677*91f16700Schasinglulu pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & 1678*91f16700Schasinglulu RCC_PLLNCSGR_SSCG_MODE_MASK; 1679*91f16700Schasinglulu 1680*91f16700Schasinglulu mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); 1681*91f16700Schasinglulu 1682*91f16700Schasinglulu mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, 1683*91f16700Schasinglulu RCC_PLLNCR_SSCG_CTRL); 1684*91f16700Schasinglulu } 1685*91f16700Schasinglulu 1686*91f16700Schasinglulu static int stm32mp1_set_clksrc(unsigned int clksrc) 1687*91f16700Schasinglulu { 1688*91f16700Schasinglulu uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 1689*91f16700Schasinglulu uint64_t timeout; 1690*91f16700Schasinglulu 1691*91f16700Schasinglulu mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, 1692*91f16700Schasinglulu clksrc & RCC_SELR_SRC_MASK); 1693*91f16700Schasinglulu 1694*91f16700Schasinglulu timeout = timeout_init_us(CLKSRC_TIMEOUT); 1695*91f16700Schasinglulu while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { 1696*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 1697*91f16700Schasinglulu ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, 1698*91f16700Schasinglulu clksrc_address, mmio_read_32(clksrc_address)); 1699*91f16700Schasinglulu return -ETIMEDOUT; 1700*91f16700Schasinglulu } 1701*91f16700Schasinglulu } 1702*91f16700Schasinglulu 1703*91f16700Schasinglulu return 0; 1704*91f16700Schasinglulu } 1705*91f16700Schasinglulu 1706*91f16700Schasinglulu static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) 1707*91f16700Schasinglulu { 1708*91f16700Schasinglulu uint64_t timeout; 1709*91f16700Schasinglulu 1710*91f16700Schasinglulu mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, 1711*91f16700Schasinglulu clkdiv & RCC_DIVR_DIV_MASK); 1712*91f16700Schasinglulu 1713*91f16700Schasinglulu timeout = timeout_init_us(CLKDIV_TIMEOUT); 1714*91f16700Schasinglulu while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { 1715*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 1716*91f16700Schasinglulu ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", 1717*91f16700Schasinglulu clkdiv, address, mmio_read_32(address)); 1718*91f16700Schasinglulu return -ETIMEDOUT; 1719*91f16700Schasinglulu } 1720*91f16700Schasinglulu } 1721*91f16700Schasinglulu 1722*91f16700Schasinglulu return 0; 1723*91f16700Schasinglulu } 1724*91f16700Schasinglulu 1725*91f16700Schasinglulu static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) 1726*91f16700Schasinglulu { 1727*91f16700Schasinglulu uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 1728*91f16700Schasinglulu 1729*91f16700Schasinglulu /* 1730*91f16700Schasinglulu * Binding clksrc : 1731*91f16700Schasinglulu * bit15-4 offset 1732*91f16700Schasinglulu * bit3: disable 1733*91f16700Schasinglulu * bit2-0: MCOSEL[2:0] 1734*91f16700Schasinglulu */ 1735*91f16700Schasinglulu if ((clksrc & 0x8U) != 0U) { 1736*91f16700Schasinglulu mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); 1737*91f16700Schasinglulu } else { 1738*91f16700Schasinglulu mmio_clrsetbits_32(clksrc_address, 1739*91f16700Schasinglulu RCC_MCOCFG_MCOSRC_MASK, 1740*91f16700Schasinglulu clksrc & RCC_MCOCFG_MCOSRC_MASK); 1741*91f16700Schasinglulu mmio_clrsetbits_32(clksrc_address, 1742*91f16700Schasinglulu RCC_MCOCFG_MCODIV_MASK, 1743*91f16700Schasinglulu clkdiv << RCC_MCOCFG_MCODIV_SHIFT); 1744*91f16700Schasinglulu mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); 1745*91f16700Schasinglulu } 1746*91f16700Schasinglulu } 1747*91f16700Schasinglulu 1748*91f16700Schasinglulu static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) 1749*91f16700Schasinglulu { 1750*91f16700Schasinglulu uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; 1751*91f16700Schasinglulu 1752*91f16700Schasinglulu if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || 1753*91f16700Schasinglulu (clksrc != (uint32_t)CLK_RTC_DISABLED)) { 1754*91f16700Schasinglulu mmio_clrsetbits_32(address, 1755*91f16700Schasinglulu RCC_BDCR_RTCSRC_MASK, 1756*91f16700Schasinglulu (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); 1757*91f16700Schasinglulu 1758*91f16700Schasinglulu mmio_setbits_32(address, RCC_BDCR_RTCCKEN); 1759*91f16700Schasinglulu } 1760*91f16700Schasinglulu 1761*91f16700Schasinglulu if (lse_css) { 1762*91f16700Schasinglulu mmio_setbits_32(address, RCC_BDCR_LSECSSON); 1763*91f16700Schasinglulu } 1764*91f16700Schasinglulu } 1765*91f16700Schasinglulu 1766*91f16700Schasinglulu static void stm32mp1_pkcs_config(uint32_t pkcs) 1767*91f16700Schasinglulu { 1768*91f16700Schasinglulu uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); 1769*91f16700Schasinglulu uint32_t value = pkcs & 0xFU; 1770*91f16700Schasinglulu uint32_t mask = 0xFU; 1771*91f16700Schasinglulu 1772*91f16700Schasinglulu if ((pkcs & BIT(31)) != 0U) { 1773*91f16700Schasinglulu mask <<= 4; 1774*91f16700Schasinglulu value <<= 4; 1775*91f16700Schasinglulu } 1776*91f16700Schasinglulu 1777*91f16700Schasinglulu mmio_clrsetbits_32(address, mask, value); 1778*91f16700Schasinglulu } 1779*91f16700Schasinglulu 1780*91f16700Schasinglulu static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg, 1781*91f16700Schasinglulu uint32_t *fracv, uint32_t *csg, 1782*91f16700Schasinglulu bool *csg_set) 1783*91f16700Schasinglulu { 1784*91f16700Schasinglulu void *fdt; 1785*91f16700Schasinglulu int ret; 1786*91f16700Schasinglulu 1787*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 1788*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 1789*91f16700Schasinglulu } 1790*91f16700Schasinglulu 1791*91f16700Schasinglulu ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB, 1792*91f16700Schasinglulu pllcfg); 1793*91f16700Schasinglulu if (ret < 0) { 1794*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 1795*91f16700Schasinglulu } 1796*91f16700Schasinglulu 1797*91f16700Schasinglulu *fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); 1798*91f16700Schasinglulu 1799*91f16700Schasinglulu ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB, 1800*91f16700Schasinglulu csg); 1801*91f16700Schasinglulu 1802*91f16700Schasinglulu *csg_set = (ret == 0); 1803*91f16700Schasinglulu 1804*91f16700Schasinglulu if (ret == -FDT_ERR_NOTFOUND) { 1805*91f16700Schasinglulu ret = 0; 1806*91f16700Schasinglulu } 1807*91f16700Schasinglulu 1808*91f16700Schasinglulu return ret; 1809*91f16700Schasinglulu } 1810*91f16700Schasinglulu 1811*91f16700Schasinglulu int stm32mp1_clk_init(void) 1812*91f16700Schasinglulu { 1813*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 1814*91f16700Schasinglulu uint32_t pllfracv[_PLL_NB]; 1815*91f16700Schasinglulu uint32_t pllcsg[_PLL_NB][PLLCSG_NB]; 1816*91f16700Schasinglulu unsigned int clksrc[CLKSRC_NB]; 1817*91f16700Schasinglulu unsigned int clkdiv[CLKDIV_NB]; 1818*91f16700Schasinglulu unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; 1819*91f16700Schasinglulu int plloff[_PLL_NB]; 1820*91f16700Schasinglulu int ret, len; 1821*91f16700Schasinglulu enum stm32mp1_pll_id i; 1822*91f16700Schasinglulu bool pllcsg_set[_PLL_NB]; 1823*91f16700Schasinglulu bool pllcfg_valid[_PLL_NB]; 1824*91f16700Schasinglulu bool lse_css = false; 1825*91f16700Schasinglulu bool pll3_preserve = false; 1826*91f16700Schasinglulu bool pll4_preserve = false; 1827*91f16700Schasinglulu bool pll4_bootrom = false; 1828*91f16700Schasinglulu const fdt32_t *pkcs_cell; 1829*91f16700Schasinglulu void *fdt; 1830*91f16700Schasinglulu int stgen_p = stm32mp1_clk_get_parent(STGEN_K); 1831*91f16700Schasinglulu int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K); 1832*91f16700Schasinglulu 1833*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 1834*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 1835*91f16700Schasinglulu } 1836*91f16700Schasinglulu 1837*91f16700Schasinglulu ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, 1838*91f16700Schasinglulu clksrc); 1839*91f16700Schasinglulu if (ret < 0) { 1840*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 1841*91f16700Schasinglulu } 1842*91f16700Schasinglulu 1843*91f16700Schasinglulu ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, 1844*91f16700Schasinglulu clkdiv); 1845*91f16700Schasinglulu if (ret < 0) { 1846*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 1847*91f16700Schasinglulu } 1848*91f16700Schasinglulu 1849*91f16700Schasinglulu for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 1850*91f16700Schasinglulu char name[12]; 1851*91f16700Schasinglulu 1852*91f16700Schasinglulu snprintf(name, sizeof(name), "st,pll@%u", i); 1853*91f16700Schasinglulu plloff[i] = fdt_rcc_subnode_offset(name); 1854*91f16700Schasinglulu 1855*91f16700Schasinglulu pllcfg_valid[i] = fdt_check_node(plloff[i]); 1856*91f16700Schasinglulu if (!pllcfg_valid[i]) { 1857*91f16700Schasinglulu continue; 1858*91f16700Schasinglulu } 1859*91f16700Schasinglulu 1860*91f16700Schasinglulu ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i], 1861*91f16700Schasinglulu &pllfracv[i], pllcsg[i], 1862*91f16700Schasinglulu &pllcsg_set[i]); 1863*91f16700Schasinglulu if (ret != 0) { 1864*91f16700Schasinglulu return ret; 1865*91f16700Schasinglulu } 1866*91f16700Schasinglulu } 1867*91f16700Schasinglulu 1868*91f16700Schasinglulu stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); 1869*91f16700Schasinglulu stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); 1870*91f16700Schasinglulu 1871*91f16700Schasinglulu /* 1872*91f16700Schasinglulu * Switch ON oscillator found in device-tree. 1873*91f16700Schasinglulu * Note: HSI already ON after BootROM stage. 1874*91f16700Schasinglulu */ 1875*91f16700Schasinglulu if (stm32mp1_osc[_LSI] != 0U) { 1876*91f16700Schasinglulu stm32mp1_lsi_set(true); 1877*91f16700Schasinglulu } 1878*91f16700Schasinglulu if (stm32mp1_osc[_LSE] != 0U) { 1879*91f16700Schasinglulu const char *name = stm32mp_osc_node_label[_LSE]; 1880*91f16700Schasinglulu bool bypass, digbyp; 1881*91f16700Schasinglulu uint32_t lsedrv; 1882*91f16700Schasinglulu 1883*91f16700Schasinglulu bypass = fdt_clk_read_bool(name, "st,bypass"); 1884*91f16700Schasinglulu digbyp = fdt_clk_read_bool(name, "st,digbypass"); 1885*91f16700Schasinglulu lse_css = fdt_clk_read_bool(name, "st,css"); 1886*91f16700Schasinglulu lsedrv = fdt_clk_read_uint32_default(name, "st,drive", 1887*91f16700Schasinglulu LSEDRV_MEDIUM_HIGH); 1888*91f16700Schasinglulu stm32mp1_lse_enable(bypass, digbyp, lsedrv); 1889*91f16700Schasinglulu } 1890*91f16700Schasinglulu if (stm32mp1_osc[_HSE] != 0U) { 1891*91f16700Schasinglulu const char *name = stm32mp_osc_node_label[_HSE]; 1892*91f16700Schasinglulu bool bypass, digbyp, css; 1893*91f16700Schasinglulu 1894*91f16700Schasinglulu bypass = fdt_clk_read_bool(name, "st,bypass"); 1895*91f16700Schasinglulu digbyp = fdt_clk_read_bool(name, "st,digbypass"); 1896*91f16700Schasinglulu css = fdt_clk_read_bool(name, "st,css"); 1897*91f16700Schasinglulu stm32mp1_hse_enable(bypass, digbyp, css); 1898*91f16700Schasinglulu } 1899*91f16700Schasinglulu /* 1900*91f16700Schasinglulu * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) 1901*91f16700Schasinglulu * => switch on CSI even if node is not present in device tree 1902*91f16700Schasinglulu */ 1903*91f16700Schasinglulu stm32mp1_csi_set(true); 1904*91f16700Schasinglulu 1905*91f16700Schasinglulu /* Come back to HSI */ 1906*91f16700Schasinglulu ret = stm32mp1_set_clksrc(CLK_MPU_HSI); 1907*91f16700Schasinglulu if (ret != 0) { 1908*91f16700Schasinglulu return ret; 1909*91f16700Schasinglulu } 1910*91f16700Schasinglulu ret = stm32mp1_set_clksrc(CLK_AXI_HSI); 1911*91f16700Schasinglulu if (ret != 0) { 1912*91f16700Schasinglulu return ret; 1913*91f16700Schasinglulu } 1914*91f16700Schasinglulu ret = stm32mp1_set_clksrc(CLK_MCU_HSI); 1915*91f16700Schasinglulu if (ret != 0) { 1916*91f16700Schasinglulu return ret; 1917*91f16700Schasinglulu } 1918*91f16700Schasinglulu 1919*91f16700Schasinglulu if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & 1920*91f16700Schasinglulu RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { 1921*91f16700Schasinglulu if (pllcfg_valid[_PLL3]) { 1922*91f16700Schasinglulu pll3_preserve = 1923*91f16700Schasinglulu stm32mp1_check_pll_conf(_PLL3, 1924*91f16700Schasinglulu clksrc[CLKSRC_PLL3], 1925*91f16700Schasinglulu pllcfg[_PLL3], 1926*91f16700Schasinglulu plloff[_PLL3]); 1927*91f16700Schasinglulu } 1928*91f16700Schasinglulu 1929*91f16700Schasinglulu if (pllcfg_valid[_PLL4]) { 1930*91f16700Schasinglulu pll4_preserve = 1931*91f16700Schasinglulu stm32mp1_check_pll_conf(_PLL4, 1932*91f16700Schasinglulu clksrc[CLKSRC_PLL4], 1933*91f16700Schasinglulu pllcfg[_PLL4], 1934*91f16700Schasinglulu plloff[_PLL4]); 1935*91f16700Schasinglulu } 1936*91f16700Schasinglulu } 1937*91f16700Schasinglulu /* Don't initialize PLL4, when used by BOOTROM */ 1938*91f16700Schasinglulu if ((stm32mp_get_boot_itf_selected() == 1939*91f16700Schasinglulu BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && 1940*91f16700Schasinglulu ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { 1941*91f16700Schasinglulu pll4_bootrom = true; 1942*91f16700Schasinglulu pll4_preserve = true; 1943*91f16700Schasinglulu } 1944*91f16700Schasinglulu 1945*91f16700Schasinglulu for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 1946*91f16700Schasinglulu if (((i == _PLL3) && pll3_preserve) || 1947*91f16700Schasinglulu ((i == _PLL4) && pll4_preserve)) { 1948*91f16700Schasinglulu continue; 1949*91f16700Schasinglulu } 1950*91f16700Schasinglulu 1951*91f16700Schasinglulu ret = stm32mp1_pll_stop(i); 1952*91f16700Schasinglulu if (ret != 0) { 1953*91f16700Schasinglulu return ret; 1954*91f16700Schasinglulu } 1955*91f16700Schasinglulu } 1956*91f16700Schasinglulu 1957*91f16700Schasinglulu /* Configure HSIDIV */ 1958*91f16700Schasinglulu if (stm32mp1_osc[_HSI] != 0U) { 1959*91f16700Schasinglulu ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); 1960*91f16700Schasinglulu if (ret != 0) { 1961*91f16700Schasinglulu return ret; 1962*91f16700Schasinglulu } 1963*91f16700Schasinglulu 1964*91f16700Schasinglulu stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); 1965*91f16700Schasinglulu } 1966*91f16700Schasinglulu 1967*91f16700Schasinglulu /* Select DIV */ 1968*91f16700Schasinglulu /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ 1969*91f16700Schasinglulu mmio_write_32(rcc_base + RCC_MPCKDIVR, 1970*91f16700Schasinglulu clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); 1971*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); 1972*91f16700Schasinglulu if (ret != 0) { 1973*91f16700Schasinglulu return ret; 1974*91f16700Schasinglulu } 1975*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); 1976*91f16700Schasinglulu if (ret != 0) { 1977*91f16700Schasinglulu return ret; 1978*91f16700Schasinglulu } 1979*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); 1980*91f16700Schasinglulu if (ret != 0) { 1981*91f16700Schasinglulu return ret; 1982*91f16700Schasinglulu } 1983*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); 1984*91f16700Schasinglulu if (ret != 0) { 1985*91f16700Schasinglulu return ret; 1986*91f16700Schasinglulu } 1987*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); 1988*91f16700Schasinglulu if (ret != 0) { 1989*91f16700Schasinglulu return ret; 1990*91f16700Schasinglulu } 1991*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); 1992*91f16700Schasinglulu if (ret != 0) { 1993*91f16700Schasinglulu return ret; 1994*91f16700Schasinglulu } 1995*91f16700Schasinglulu ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); 1996*91f16700Schasinglulu if (ret != 0) { 1997*91f16700Schasinglulu return ret; 1998*91f16700Schasinglulu } 1999*91f16700Schasinglulu 2000*91f16700Schasinglulu /* No ready bit for RTC */ 2001*91f16700Schasinglulu mmio_write_32(rcc_base + RCC_RTCDIVR, 2002*91f16700Schasinglulu clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); 2003*91f16700Schasinglulu 2004*91f16700Schasinglulu /* Configure PLLs source */ 2005*91f16700Schasinglulu ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); 2006*91f16700Schasinglulu if (ret != 0) { 2007*91f16700Schasinglulu return ret; 2008*91f16700Schasinglulu } 2009*91f16700Schasinglulu 2010*91f16700Schasinglulu if (!pll3_preserve) { 2011*91f16700Schasinglulu ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); 2012*91f16700Schasinglulu if (ret != 0) { 2013*91f16700Schasinglulu return ret; 2014*91f16700Schasinglulu } 2015*91f16700Schasinglulu } 2016*91f16700Schasinglulu 2017*91f16700Schasinglulu if (!pll4_preserve) { 2018*91f16700Schasinglulu ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); 2019*91f16700Schasinglulu if (ret != 0) { 2020*91f16700Schasinglulu return ret; 2021*91f16700Schasinglulu } 2022*91f16700Schasinglulu } 2023*91f16700Schasinglulu 2024*91f16700Schasinglulu /* Configure and start PLLs */ 2025*91f16700Schasinglulu for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 2026*91f16700Schasinglulu if (((i == _PLL3) && pll3_preserve) || 2027*91f16700Schasinglulu ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { 2028*91f16700Schasinglulu continue; 2029*91f16700Schasinglulu } 2030*91f16700Schasinglulu 2031*91f16700Schasinglulu if (!pllcfg_valid[i]) { 2032*91f16700Schasinglulu continue; 2033*91f16700Schasinglulu } 2034*91f16700Schasinglulu 2035*91f16700Schasinglulu if ((i == _PLL4) && pll4_bootrom) { 2036*91f16700Schasinglulu /* Set output divider if not done by the Bootrom */ 2037*91f16700Schasinglulu stm32mp1_pll_config_output(i, pllcfg[i]); 2038*91f16700Schasinglulu continue; 2039*91f16700Schasinglulu } 2040*91f16700Schasinglulu 2041*91f16700Schasinglulu ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]); 2042*91f16700Schasinglulu if (ret != 0) { 2043*91f16700Schasinglulu return ret; 2044*91f16700Schasinglulu } 2045*91f16700Schasinglulu 2046*91f16700Schasinglulu if (pllcsg_set[i]) { 2047*91f16700Schasinglulu stm32mp1_pll_csg(i, pllcsg[i]); 2048*91f16700Schasinglulu } 2049*91f16700Schasinglulu 2050*91f16700Schasinglulu stm32mp1_pll_start(i); 2051*91f16700Schasinglulu } 2052*91f16700Schasinglulu /* Wait and start PLLs output when ready */ 2053*91f16700Schasinglulu for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 2054*91f16700Schasinglulu if (!pllcfg_valid[i]) { 2055*91f16700Schasinglulu continue; 2056*91f16700Schasinglulu } 2057*91f16700Schasinglulu 2058*91f16700Schasinglulu ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); 2059*91f16700Schasinglulu if (ret != 0) { 2060*91f16700Schasinglulu return ret; 2061*91f16700Schasinglulu } 2062*91f16700Schasinglulu } 2063*91f16700Schasinglulu /* Wait LSE ready before to use it */ 2064*91f16700Schasinglulu if (stm32mp1_osc[_LSE] != 0U) { 2065*91f16700Schasinglulu stm32mp1_lse_wait(); 2066*91f16700Schasinglulu } 2067*91f16700Schasinglulu 2068*91f16700Schasinglulu /* Configure with expected clock source */ 2069*91f16700Schasinglulu ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); 2070*91f16700Schasinglulu if (ret != 0) { 2071*91f16700Schasinglulu return ret; 2072*91f16700Schasinglulu } 2073*91f16700Schasinglulu ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); 2074*91f16700Schasinglulu if (ret != 0) { 2075*91f16700Schasinglulu return ret; 2076*91f16700Schasinglulu } 2077*91f16700Schasinglulu ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); 2078*91f16700Schasinglulu if (ret != 0) { 2079*91f16700Schasinglulu return ret; 2080*91f16700Schasinglulu } 2081*91f16700Schasinglulu stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); 2082*91f16700Schasinglulu 2083*91f16700Schasinglulu /* Configure PKCK */ 2084*91f16700Schasinglulu pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); 2085*91f16700Schasinglulu if (pkcs_cell != NULL) { 2086*91f16700Schasinglulu bool ckper_disabled = false; 2087*91f16700Schasinglulu uint32_t j; 2088*91f16700Schasinglulu uint32_t usbreg_bootrom = 0U; 2089*91f16700Schasinglulu 2090*91f16700Schasinglulu if (pll4_bootrom) { 2091*91f16700Schasinglulu usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR); 2092*91f16700Schasinglulu } 2093*91f16700Schasinglulu 2094*91f16700Schasinglulu for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { 2095*91f16700Schasinglulu uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); 2096*91f16700Schasinglulu 2097*91f16700Schasinglulu if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { 2098*91f16700Schasinglulu ckper_disabled = true; 2099*91f16700Schasinglulu continue; 2100*91f16700Schasinglulu } 2101*91f16700Schasinglulu stm32mp1_pkcs_config(pkcs); 2102*91f16700Schasinglulu } 2103*91f16700Schasinglulu 2104*91f16700Schasinglulu /* 2105*91f16700Schasinglulu * CKPER is source for some peripheral clocks 2106*91f16700Schasinglulu * (FMC-NAND / QPSI-NOR) and switching source is allowed 2107*91f16700Schasinglulu * only if previous clock is still ON 2108*91f16700Schasinglulu * => deactivated CKPER only after switching clock 2109*91f16700Schasinglulu */ 2110*91f16700Schasinglulu if (ckper_disabled) { 2111*91f16700Schasinglulu stm32mp1_pkcs_config(CLK_CKPER_DISABLED); 2112*91f16700Schasinglulu } 2113*91f16700Schasinglulu 2114*91f16700Schasinglulu if (pll4_bootrom) { 2115*91f16700Schasinglulu uint32_t usbreg_value, usbreg_mask; 2116*91f16700Schasinglulu const struct stm32mp1_clk_sel *sel; 2117*91f16700Schasinglulu 2118*91f16700Schasinglulu sel = clk_sel_ref(_USBPHY_SEL); 2119*91f16700Schasinglulu usbreg_mask = (uint32_t)sel->msk << sel->src; 2120*91f16700Schasinglulu sel = clk_sel_ref(_USBO_SEL); 2121*91f16700Schasinglulu usbreg_mask |= (uint32_t)sel->msk << sel->src; 2122*91f16700Schasinglulu 2123*91f16700Schasinglulu usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) & 2124*91f16700Schasinglulu usbreg_mask; 2125*91f16700Schasinglulu usbreg_bootrom &= usbreg_mask; 2126*91f16700Schasinglulu if (usbreg_bootrom != usbreg_value) { 2127*91f16700Schasinglulu VERBOSE("forbidden new USB clk path\n"); 2128*91f16700Schasinglulu VERBOSE("vs bootrom on USB boot\n"); 2129*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 2130*91f16700Schasinglulu } 2131*91f16700Schasinglulu } 2132*91f16700Schasinglulu } 2133*91f16700Schasinglulu 2134*91f16700Schasinglulu /* Switch OFF HSI if not found in device-tree */ 2135*91f16700Schasinglulu if (stm32mp1_osc[_HSI] == 0U) { 2136*91f16700Schasinglulu stm32mp1_hsi_set(false); 2137*91f16700Schasinglulu } 2138*91f16700Schasinglulu 2139*91f16700Schasinglulu stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); 2140*91f16700Schasinglulu 2141*91f16700Schasinglulu /* Software Self-Refresh mode (SSR) during DDR initilialization */ 2142*91f16700Schasinglulu mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, 2143*91f16700Schasinglulu RCC_DDRITFCR_DDRCKMOD_MASK, 2144*91f16700Schasinglulu RCC_DDRITFCR_DDRCKMOD_SSR << 2145*91f16700Schasinglulu RCC_DDRITFCR_DDRCKMOD_SHIFT); 2146*91f16700Schasinglulu 2147*91f16700Schasinglulu return 0; 2148*91f16700Schasinglulu } 2149*91f16700Schasinglulu 2150*91f16700Schasinglulu static void stm32mp1_osc_clk_init(const char *name, 2151*91f16700Schasinglulu enum stm32mp_osc_id index) 2152*91f16700Schasinglulu { 2153*91f16700Schasinglulu uint32_t frequency; 2154*91f16700Schasinglulu 2155*91f16700Schasinglulu if (fdt_osc_read_freq(name, &frequency) == 0) { 2156*91f16700Schasinglulu stm32mp1_osc[index] = frequency; 2157*91f16700Schasinglulu } 2158*91f16700Schasinglulu } 2159*91f16700Schasinglulu 2160*91f16700Schasinglulu static void stm32mp1_osc_init(void) 2161*91f16700Schasinglulu { 2162*91f16700Schasinglulu enum stm32mp_osc_id i; 2163*91f16700Schasinglulu 2164*91f16700Schasinglulu for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { 2165*91f16700Schasinglulu stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); 2166*91f16700Schasinglulu } 2167*91f16700Schasinglulu } 2168*91f16700Schasinglulu 2169*91f16700Schasinglulu #ifdef STM32MP_SHARED_RESOURCES 2170*91f16700Schasinglulu /* 2171*91f16700Schasinglulu * Get the parent ID of the target parent clock, for tagging as secure 2172*91f16700Schasinglulu * shared clock dependencies. 2173*91f16700Schasinglulu */ 2174*91f16700Schasinglulu static int get_parent_id_parent(unsigned int parent_id) 2175*91f16700Schasinglulu { 2176*91f16700Schasinglulu enum stm32mp1_parent_sel s = _UNKNOWN_SEL; 2177*91f16700Schasinglulu enum stm32mp1_pll_id pll_id; 2178*91f16700Schasinglulu uint32_t p_sel; 2179*91f16700Schasinglulu uintptr_t rcc_base = stm32mp_rcc_base(); 2180*91f16700Schasinglulu 2181*91f16700Schasinglulu switch (parent_id) { 2182*91f16700Schasinglulu case _ACLK: 2183*91f16700Schasinglulu case _PCLK4: 2184*91f16700Schasinglulu case _PCLK5: 2185*91f16700Schasinglulu s = _AXIS_SEL; 2186*91f16700Schasinglulu break; 2187*91f16700Schasinglulu case _PLL1_P: 2188*91f16700Schasinglulu case _PLL1_Q: 2189*91f16700Schasinglulu case _PLL1_R: 2190*91f16700Schasinglulu pll_id = _PLL1; 2191*91f16700Schasinglulu break; 2192*91f16700Schasinglulu case _PLL2_P: 2193*91f16700Schasinglulu case _PLL2_Q: 2194*91f16700Schasinglulu case _PLL2_R: 2195*91f16700Schasinglulu pll_id = _PLL2; 2196*91f16700Schasinglulu break; 2197*91f16700Schasinglulu case _PLL3_P: 2198*91f16700Schasinglulu case _PLL3_Q: 2199*91f16700Schasinglulu case _PLL3_R: 2200*91f16700Schasinglulu pll_id = _PLL3; 2201*91f16700Schasinglulu break; 2202*91f16700Schasinglulu case _PLL4_P: 2203*91f16700Schasinglulu case _PLL4_Q: 2204*91f16700Schasinglulu case _PLL4_R: 2205*91f16700Schasinglulu pll_id = _PLL4; 2206*91f16700Schasinglulu break; 2207*91f16700Schasinglulu case _PCLK1: 2208*91f16700Schasinglulu case _PCLK2: 2209*91f16700Schasinglulu case _HCLK2: 2210*91f16700Schasinglulu case _HCLK6: 2211*91f16700Schasinglulu case _CK_PER: 2212*91f16700Schasinglulu case _CK_MPU: 2213*91f16700Schasinglulu case _CK_MCU: 2214*91f16700Schasinglulu case _USB_PHY_48: 2215*91f16700Schasinglulu /* We do not expect to access these */ 2216*91f16700Schasinglulu panic(); 2217*91f16700Schasinglulu break; 2218*91f16700Schasinglulu default: 2219*91f16700Schasinglulu /* Other parents have no parent */ 2220*91f16700Schasinglulu return -1; 2221*91f16700Schasinglulu } 2222*91f16700Schasinglulu 2223*91f16700Schasinglulu if (s != _UNKNOWN_SEL) { 2224*91f16700Schasinglulu const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); 2225*91f16700Schasinglulu 2226*91f16700Schasinglulu p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & 2227*91f16700Schasinglulu sel->msk; 2228*91f16700Schasinglulu 2229*91f16700Schasinglulu if (p_sel < sel->nb_parent) { 2230*91f16700Schasinglulu return (int)sel->parent[p_sel]; 2231*91f16700Schasinglulu } 2232*91f16700Schasinglulu } else { 2233*91f16700Schasinglulu const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 2234*91f16700Schasinglulu 2235*91f16700Schasinglulu p_sel = mmio_read_32(rcc_base + pll->rckxselr) & 2236*91f16700Schasinglulu RCC_SELR_REFCLK_SRC_MASK; 2237*91f16700Schasinglulu 2238*91f16700Schasinglulu if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { 2239*91f16700Schasinglulu return (int)pll->refclk[p_sel]; 2240*91f16700Schasinglulu } 2241*91f16700Schasinglulu } 2242*91f16700Schasinglulu 2243*91f16700Schasinglulu VERBOSE("No parent selected for %s\n", 2244*91f16700Schasinglulu stm32mp1_clk_parent_name[parent_id]); 2245*91f16700Schasinglulu 2246*91f16700Schasinglulu return -1; 2247*91f16700Schasinglulu } 2248*91f16700Schasinglulu 2249*91f16700Schasinglulu static void secure_parent_clocks(unsigned long parent_id) 2250*91f16700Schasinglulu { 2251*91f16700Schasinglulu int grandparent_id; 2252*91f16700Schasinglulu 2253*91f16700Schasinglulu switch (parent_id) { 2254*91f16700Schasinglulu case _PLL3_P: 2255*91f16700Schasinglulu case _PLL3_Q: 2256*91f16700Schasinglulu case _PLL3_R: 2257*91f16700Schasinglulu stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 2258*91f16700Schasinglulu break; 2259*91f16700Schasinglulu 2260*91f16700Schasinglulu /* These clocks are always secure when RCC is secure */ 2261*91f16700Schasinglulu case _ACLK: 2262*91f16700Schasinglulu case _HCLK2: 2263*91f16700Schasinglulu case _HCLK6: 2264*91f16700Schasinglulu case _PCLK4: 2265*91f16700Schasinglulu case _PCLK5: 2266*91f16700Schasinglulu case _PLL1_P: 2267*91f16700Schasinglulu case _PLL1_Q: 2268*91f16700Schasinglulu case _PLL1_R: 2269*91f16700Schasinglulu case _PLL2_P: 2270*91f16700Schasinglulu case _PLL2_Q: 2271*91f16700Schasinglulu case _PLL2_R: 2272*91f16700Schasinglulu case _HSI: 2273*91f16700Schasinglulu case _HSI_KER: 2274*91f16700Schasinglulu case _LSI: 2275*91f16700Schasinglulu case _CSI: 2276*91f16700Schasinglulu case _CSI_KER: 2277*91f16700Schasinglulu case _HSE: 2278*91f16700Schasinglulu case _HSE_KER: 2279*91f16700Schasinglulu case _HSE_KER_DIV2: 2280*91f16700Schasinglulu case _HSE_RTC: 2281*91f16700Schasinglulu case _LSE: 2282*91f16700Schasinglulu break; 2283*91f16700Schasinglulu 2284*91f16700Schasinglulu default: 2285*91f16700Schasinglulu VERBOSE("Cannot secure parent clock %s\n", 2286*91f16700Schasinglulu stm32mp1_clk_parent_name[parent_id]); 2287*91f16700Schasinglulu panic(); 2288*91f16700Schasinglulu } 2289*91f16700Schasinglulu 2290*91f16700Schasinglulu grandparent_id = get_parent_id_parent(parent_id); 2291*91f16700Schasinglulu if (grandparent_id >= 0) { 2292*91f16700Schasinglulu secure_parent_clocks(grandparent_id); 2293*91f16700Schasinglulu } 2294*91f16700Schasinglulu } 2295*91f16700Schasinglulu 2296*91f16700Schasinglulu void stm32mp1_register_clock_parents_secure(unsigned long clock_id) 2297*91f16700Schasinglulu { 2298*91f16700Schasinglulu int parent_id; 2299*91f16700Schasinglulu 2300*91f16700Schasinglulu if (!stm32mp1_rcc_is_secure()) { 2301*91f16700Schasinglulu return; 2302*91f16700Schasinglulu } 2303*91f16700Schasinglulu 2304*91f16700Schasinglulu switch (clock_id) { 2305*91f16700Schasinglulu case PLL1: 2306*91f16700Schasinglulu case PLL2: 2307*91f16700Schasinglulu /* PLL1/PLL2 are always secure: nothing to do */ 2308*91f16700Schasinglulu break; 2309*91f16700Schasinglulu case PLL3: 2310*91f16700Schasinglulu stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 2311*91f16700Schasinglulu break; 2312*91f16700Schasinglulu case PLL4: 2313*91f16700Schasinglulu ERROR("PLL4 cannot be secured\n"); 2314*91f16700Schasinglulu panic(); 2315*91f16700Schasinglulu break; 2316*91f16700Schasinglulu default: 2317*91f16700Schasinglulu /* Others are expected gateable clock */ 2318*91f16700Schasinglulu parent_id = stm32mp1_clk_get_parent(clock_id); 2319*91f16700Schasinglulu if (parent_id < 0) { 2320*91f16700Schasinglulu INFO("No parent found for clock %lu\n", clock_id); 2321*91f16700Schasinglulu } else { 2322*91f16700Schasinglulu secure_parent_clocks(parent_id); 2323*91f16700Schasinglulu } 2324*91f16700Schasinglulu break; 2325*91f16700Schasinglulu } 2326*91f16700Schasinglulu } 2327*91f16700Schasinglulu #endif /* STM32MP_SHARED_RESOURCES */ 2328*91f16700Schasinglulu 2329*91f16700Schasinglulu static void sync_earlyboot_clocks_state(void) 2330*91f16700Schasinglulu { 2331*91f16700Schasinglulu unsigned int idx; 2332*91f16700Schasinglulu const unsigned long secure_enable[] = { 2333*91f16700Schasinglulu AXIDCG, 2334*91f16700Schasinglulu BSEC, 2335*91f16700Schasinglulu DDRC1, DDRC1LP, 2336*91f16700Schasinglulu DDRC2, DDRC2LP, 2337*91f16700Schasinglulu DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, 2338*91f16700Schasinglulu DDRPHYC, DDRPHYCLP, 2339*91f16700Schasinglulu RTCAPB, 2340*91f16700Schasinglulu TZC1, TZC2, 2341*91f16700Schasinglulu TZPC, 2342*91f16700Schasinglulu STGEN_K, 2343*91f16700Schasinglulu }; 2344*91f16700Schasinglulu 2345*91f16700Schasinglulu for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { 2346*91f16700Schasinglulu stm32mp_clk_enable(secure_enable[idx]); 2347*91f16700Schasinglulu } 2348*91f16700Schasinglulu } 2349*91f16700Schasinglulu 2350*91f16700Schasinglulu static const struct clk_ops stm32mp_clk_ops = { 2351*91f16700Schasinglulu .enable = stm32mp_clk_enable, 2352*91f16700Schasinglulu .disable = stm32mp_clk_disable, 2353*91f16700Schasinglulu .is_enabled = stm32mp_clk_is_enabled, 2354*91f16700Schasinglulu .get_rate = stm32mp_clk_get_rate, 2355*91f16700Schasinglulu .get_parent = stm32mp1_clk_get_parent, 2356*91f16700Schasinglulu }; 2357*91f16700Schasinglulu 2358*91f16700Schasinglulu int stm32mp1_clk_probe(void) 2359*91f16700Schasinglulu { 2360*91f16700Schasinglulu #if defined(IMAGE_BL32) 2361*91f16700Schasinglulu if (!fdt_get_rcc_secure_state()) { 2362*91f16700Schasinglulu mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U); 2363*91f16700Schasinglulu } 2364*91f16700Schasinglulu #endif 2365*91f16700Schasinglulu 2366*91f16700Schasinglulu stm32mp1_osc_init(); 2367*91f16700Schasinglulu 2368*91f16700Schasinglulu sync_earlyboot_clocks_state(); 2369*91f16700Schasinglulu 2370*91f16700Schasinglulu clk_register(&stm32mp_clk_ops); 2371*91f16700Schasinglulu 2372*91f16700Schasinglulu return 0; 2373*91f16700Schasinglulu } 2374