17839a050SYann Gautier /* 277b4ca0bSLionel Debieve * Copyright (C) 2018-2024, STMicroelectronics - All Rights Reserved 37839a050SYann Gautier * 47839a050SYann Gautier * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 57839a050SYann Gautier */ 67839a050SYann Gautier 77839a050SYann Gautier #include <assert.h> 87839a050SYann Gautier #include <errno.h> 97839a050SYann Gautier #include <stdint.h> 1039b6cc66SAntonio Nino Diaz #include <stdio.h> 1109d40e0eSAntonio Nino Diaz 1209d40e0eSAntonio Nino Diaz #include <arch.h> 1309d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1409d40e0eSAntonio Nino Diaz #include <common/debug.h> 1552a616b4SAndre Przywara #include <common/fdt_wrappers.h> 1633667d29SYann Gautier #include <drivers/clk.h> 1709d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 18447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h> 1909d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h> 2009d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h> 2109d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h> 2209d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 230d21680cSYann Gautier #include <lib/spinlock.h> 2409d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 25964e5ff1SNicolas Le Bayon #include <libfdt.h> 2609d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 2709d40e0eSAntonio Nino Diaz 28964e5ff1SNicolas Le Bayon #include <platform_def.h> 29964e5ff1SNicolas Le Bayon 30*ae1e5037SGabriel Fernandez enum stm32mp1_pllcfg { 31*ae1e5037SGabriel Fernandez PLLCFG_M, 32*ae1e5037SGabriel Fernandez PLLCFG_N, 33*ae1e5037SGabriel Fernandez PLL_DIV_MN_NB, 34*ae1e5037SGabriel Fernandez PLLCFG_P = PLL_DIV_MN_NB, 35*ae1e5037SGabriel Fernandez PLLCFG_Q, 36*ae1e5037SGabriel Fernandez PLLCFG_R, 37*ae1e5037SGabriel Fernandez PLLCFG_O, 38*ae1e5037SGabriel Fernandez PLLCFG_NB 39*ae1e5037SGabriel Fernandez }; 40*ae1e5037SGabriel Fernandez 41*ae1e5037SGabriel Fernandez #define PLL_DIV_MN_NB 2 42*ae1e5037SGabriel Fernandez #define PLL_DIV_PQR_NB 3 43*ae1e5037SGabriel Fernandez 44*ae1e5037SGabriel Fernandez enum stm32mp1_pllcsg { 45*ae1e5037SGabriel Fernandez PLLCSG_MOD_PER, 46*ae1e5037SGabriel Fernandez PLLCSG_INC_STEP, 47*ae1e5037SGabriel Fernandez PLLCSG_SSCG_MODE, 48*ae1e5037SGabriel Fernandez PLLCSG_NB 49*ae1e5037SGabriel Fernandez }; 50*ae1e5037SGabriel Fernandez 51*ae1e5037SGabriel Fernandez struct stm32_pll_dt_cfg { 52*ae1e5037SGabriel Fernandez bool status; 53*ae1e5037SGabriel Fernandez uint32_t src; 54*ae1e5037SGabriel Fernandez uint32_t cfg[PLLCFG_NB]; 55*ae1e5037SGabriel Fernandez uint32_t frac; 56*ae1e5037SGabriel Fernandez bool csg_enabled; 57*ae1e5037SGabriel Fernandez uint32_t csg[PLLCSG_NB]; 58*ae1e5037SGabriel Fernandez }; 59*ae1e5037SGabriel Fernandez 60*ae1e5037SGabriel Fernandez struct stm32_clk_platdata { 61*ae1e5037SGabriel Fernandez uint32_t npll; 62*ae1e5037SGabriel Fernandez struct stm32_pll_dt_cfg *pll; 63*ae1e5037SGabriel Fernandez uint32_t nclksrc; 64*ae1e5037SGabriel Fernandez uint32_t *clksrc; 65*ae1e5037SGabriel Fernandez uint32_t nclkdiv; 66*ae1e5037SGabriel Fernandez uint32_t *clkdiv; 67*ae1e5037SGabriel Fernandez }; 68*ae1e5037SGabriel Fernandez 69*ae1e5037SGabriel Fernandez struct stm32_clk_priv { 70*ae1e5037SGabriel Fernandez uintptr_t base; 71*ae1e5037SGabriel Fernandez const struct mux_cfg *parents; 72*ae1e5037SGabriel Fernandez const uint32_t nb_parents; 73*ae1e5037SGabriel Fernandez const struct div_cfg *div; 74*ae1e5037SGabriel Fernandez const uint32_t nb_div; 75*ae1e5037SGabriel Fernandez void *pdata; 76*ae1e5037SGabriel Fernandez }; 77*ae1e5037SGabriel Fernandez 78*ae1e5037SGabriel Fernandez static struct stm32_clk_priv *stm32_clock_data; 79*ae1e5037SGabriel Fernandez 80*ae1e5037SGabriel Fernandez static struct stm32_clk_priv *clk_stm32_get_priv(void) 81*ae1e5037SGabriel Fernandez { 82*ae1e5037SGabriel Fernandez return stm32_clock_data; 83*ae1e5037SGabriel Fernandez } 84*ae1e5037SGabriel Fernandez 85*ae1e5037SGabriel Fernandez static int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base) 86*ae1e5037SGabriel Fernandez { 87*ae1e5037SGabriel Fernandez stm32_clock_data = priv; 88*ae1e5037SGabriel Fernandez 89*ae1e5037SGabriel Fernandez priv->base = base; 90*ae1e5037SGabriel Fernandez 91*ae1e5037SGabriel Fernandez return 0; 92*ae1e5037SGabriel Fernandez } 93*ae1e5037SGabriel Fernandez 947839a050SYann Gautier #define MAX_HSI_HZ 64000000 950d21680cSYann Gautier #define USB_PHY_48_MHZ 48000000 967839a050SYann Gautier 97dfdb057aSYann Gautier #define TIMEOUT_US_200MS U(200000) 98dfdb057aSYann Gautier #define TIMEOUT_US_1S U(1000000) 997839a050SYann Gautier 100dfdb057aSYann Gautier #define PLLRDY_TIMEOUT TIMEOUT_US_200MS 101dfdb057aSYann Gautier #define CLKSRC_TIMEOUT TIMEOUT_US_200MS 102dfdb057aSYann Gautier #define CLKDIV_TIMEOUT TIMEOUT_US_200MS 103dfdb057aSYann Gautier #define HSIDIV_TIMEOUT TIMEOUT_US_200MS 104dfdb057aSYann Gautier #define OSCRDY_TIMEOUT TIMEOUT_US_1S 1057839a050SYann Gautier 106*ae1e5037SGabriel Fernandez struct mux_cfg { 107*ae1e5037SGabriel Fernandez uint16_t offset; 108*ae1e5037SGabriel Fernandez uint8_t shift; 109*ae1e5037SGabriel Fernandez uint8_t width; 110*ae1e5037SGabriel Fernandez uint8_t bitrdy; 111*ae1e5037SGabriel Fernandez }; 112*ae1e5037SGabriel Fernandez 113*ae1e5037SGabriel Fernandez struct div_cfg { 114*ae1e5037SGabriel Fernandez uint16_t offset; 115*ae1e5037SGabriel Fernandez uint8_t shift; 116*ae1e5037SGabriel Fernandez uint8_t width; 117*ae1e5037SGabriel Fernandez uint8_t bitrdy; 118*ae1e5037SGabriel Fernandez }; 119*ae1e5037SGabriel Fernandez 120*ae1e5037SGabriel Fernandez #define DIV_NO_BIT_RDY UINT8_MAX 121*ae1e5037SGabriel Fernandez 122*ae1e5037SGabriel Fernandez #define DIV_CFG(_id, _offset, _shift, _width, _bitrdy)\ 123*ae1e5037SGabriel Fernandez [(_id)] = {\ 124*ae1e5037SGabriel Fernandez .offset = (_offset),\ 125*ae1e5037SGabriel Fernandez .shift = (_shift),\ 126*ae1e5037SGabriel Fernandez .width = (_width),\ 127*ae1e5037SGabriel Fernandez .bitrdy = (_bitrdy),\ 128*ae1e5037SGabriel Fernandez } 129*ae1e5037SGabriel Fernandez 130*ae1e5037SGabriel Fernandez static const struct div_cfg dividers_mp15[] = { 131*ae1e5037SGabriel Fernandez DIV_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 31), 132*ae1e5037SGabriel Fernandez DIV_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 31), 133*ae1e5037SGabriel Fernandez DIV_CFG(DIV_MCU, RCC_MCUDIVR, 0, 4, 31), 134*ae1e5037SGabriel Fernandez DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 31), 135*ae1e5037SGabriel Fernandez DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 31), 136*ae1e5037SGabriel Fernandez DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 31), 137*ae1e5037SGabriel Fernandez DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 31), 138*ae1e5037SGabriel Fernandez DIV_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 31), 139*ae1e5037SGabriel Fernandez DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, DIV_NO_BIT_RDY), 140*ae1e5037SGabriel Fernandez DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, DIV_NO_BIT_RDY), 141*ae1e5037SGabriel Fernandez DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, DIV_NO_BIT_RDY), 142*ae1e5037SGabriel Fernandez DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, DIV_NO_BIT_RDY), 143*ae1e5037SGabriel Fernandez DIV_CFG(DIV_ETHPTP, RCC_ETHCKSELR, 4, 4, DIV_NO_BIT_RDY), 144*ae1e5037SGabriel Fernandez }; 145*ae1e5037SGabriel Fernandez 146*ae1e5037SGabriel Fernandez /* 147*ae1e5037SGabriel Fernandez * MUX CONFIG 148*ae1e5037SGabriel Fernandez */ 149*ae1e5037SGabriel Fernandez 150*ae1e5037SGabriel Fernandez #define MUX_NO_BIT_RDY UINT8_MAX 151*ae1e5037SGabriel Fernandez 152*ae1e5037SGabriel Fernandez #define MUXRDY_CFG(_id, _offset, _shift, _width, _bitrdy)\ 153*ae1e5037SGabriel Fernandez [(_id)] = {\ 154*ae1e5037SGabriel Fernandez .offset = (_offset),\ 155*ae1e5037SGabriel Fernandez .shift = (_shift),\ 156*ae1e5037SGabriel Fernandez .width = (_width),\ 157*ae1e5037SGabriel Fernandez .bitrdy = (_bitrdy),\ 158*ae1e5037SGabriel Fernandez } 159*ae1e5037SGabriel Fernandez 160*ae1e5037SGabriel Fernandez #define MUX_CFG(_id, _offset, _shift, _width)\ 161*ae1e5037SGabriel Fernandez MUXRDY_CFG(_id, _offset, _shift, _width, MUX_NO_BIT_RDY) 162*ae1e5037SGabriel Fernandez 163*ae1e5037SGabriel Fernandez static const struct mux_cfg parent_mp15[MUX_NB] = { 164*ae1e5037SGabriel Fernandez MUX_CFG(MUX_PLL12, RCC_RCK12SELR, 0, 2), 165*ae1e5037SGabriel Fernandez MUX_CFG(MUX_PLL3, RCC_RCK3SELR, 0, 2), 166*ae1e5037SGabriel Fernandez MUX_CFG(MUX_PLL4, RCC_RCK4SELR, 0, 2), 167*ae1e5037SGabriel Fernandez MUX_CFG(MUX_CKPER, RCC_CPERCKSELR, 0, 2), 168*ae1e5037SGabriel Fernandez MUXRDY_CFG(MUX_MPU, RCC_MPCKSELR, 0, 2, 31), 169*ae1e5037SGabriel Fernandez MUXRDY_CFG(MUX_AXI, RCC_ASSCKSELR, 0, 3, 31), 170*ae1e5037SGabriel Fernandez MUXRDY_CFG(MUX_MCU, RCC_MSSCKSELR, 0, 2, 31), 171*ae1e5037SGabriel Fernandez MUX_CFG(MUX_RTC, RCC_BDCR, 16, 2), 172*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SDMMC12, RCC_SDMMC12CKSELR, 0, 3), 173*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SPI2S23, RCC_SPI2S23CKSELR, 0, 3), 174*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SPI45, RCC_SPI45CKSELR, 0, 3), 175*ae1e5037SGabriel Fernandez MUX_CFG(MUX_I2C12, RCC_I2C12CKSELR, 0, 3), 176*ae1e5037SGabriel Fernandez MUX_CFG(MUX_I2C35, RCC_I2C35CKSELR, 0, 3), 177*ae1e5037SGabriel Fernandez MUX_CFG(MUX_LPTIM23, RCC_LPTIM23CKSELR, 0, 3), 178*ae1e5037SGabriel Fernandez MUX_CFG(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3), 179*ae1e5037SGabriel Fernandez MUX_CFG(MUX_UART24, RCC_UART24CKSELR, 0, 3), 180*ae1e5037SGabriel Fernandez MUX_CFG(MUX_UART35, RCC_UART35CKSELR, 0, 3), 181*ae1e5037SGabriel Fernandez MUX_CFG(MUX_UART78, RCC_UART78CKSELR, 0, 3), 182*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SAI1, RCC_SAI1CKSELR, 0, 3), 183*ae1e5037SGabriel Fernandez MUX_CFG(MUX_ETH, RCC_ETHCKSELR, 0, 2), 184*ae1e5037SGabriel Fernandez MUX_CFG(MUX_I2C46, RCC_I2C46CKSELR, 0, 3), 185*ae1e5037SGabriel Fernandez MUX_CFG(MUX_RNG2, RCC_RNG2CKSELR, 0, 2), 186*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SDMMC3, RCC_SDMMC3CKSELR, 0, 3), 187*ae1e5037SGabriel Fernandez MUX_CFG(MUX_FMC, RCC_FMCCKSELR, 0, 2), 188*ae1e5037SGabriel Fernandez MUX_CFG(MUX_QSPI, RCC_QSPICKSELR, 0, 2), 189*ae1e5037SGabriel Fernandez MUX_CFG(MUX_USBPHY, RCC_USBCKSELR, 0, 2), 190*ae1e5037SGabriel Fernandez MUX_CFG(MUX_USBO, RCC_USBCKSELR, 4, 1), 191*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2), 192*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SPI2S1, RCC_SPI2S1CKSELR, 0, 3), 193*ae1e5037SGabriel Fernandez MUX_CFG(MUX_CEC, RCC_CECCKSELR, 0, 2), 194*ae1e5037SGabriel Fernandez MUX_CFG(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3), 195*ae1e5037SGabriel Fernandez MUX_CFG(MUX_UART6, RCC_UART6CKSELR, 0, 3), 196*ae1e5037SGabriel Fernandez MUX_CFG(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2), 197*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SAI2, RCC_SAI2CKSELR, 0, 3), 198*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SAI3, RCC_SAI3CKSELR, 0, 3), 199*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SAI4, RCC_SAI4CKSELR, 0, 3), 200*ae1e5037SGabriel Fernandez MUX_CFG(MUX_ADC, RCC_ADCCKSELR, 0, 2), 201*ae1e5037SGabriel Fernandez MUX_CFG(MUX_DSI, RCC_DSICKSELR, 0, 1), 202*ae1e5037SGabriel Fernandez MUX_CFG(MUX_RNG1, RCC_RNG1CKSELR, 0, 2), 203*ae1e5037SGabriel Fernandez MUX_CFG(MUX_STGEN, RCC_STGENCKSELR, 0, 2), 204*ae1e5037SGabriel Fernandez MUX_CFG(MUX_UART1, RCC_UART1CKSELR, 0, 3), 205*ae1e5037SGabriel Fernandez MUX_CFG(MUX_SPI6, RCC_SPI6CKSELR, 0, 3), 206*ae1e5037SGabriel Fernandez MUX_CFG(MUX_MCO1, RCC_MCO1CFGR, 0, 3), 207*ae1e5037SGabriel Fernandez MUX_CFG(MUX_MCO2, RCC_MCO2CFGR, 0, 3), 208*ae1e5037SGabriel Fernandez }; 209*ae1e5037SGabriel Fernandez 210*ae1e5037SGabriel Fernandez #define MASK_WIDTH_SHIFT(_width, _shift) \ 211*ae1e5037SGabriel Fernandez GENMASK(((_width) + (_shift) - 1U), (_shift)) 212*ae1e5037SGabriel Fernandez 213*ae1e5037SGabriel Fernandez int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id) 214*ae1e5037SGabriel Fernandez { 215*ae1e5037SGabriel Fernandez const struct mux_cfg *mux; 216*ae1e5037SGabriel Fernandez uint32_t mask; 217*ae1e5037SGabriel Fernandez 218*ae1e5037SGabriel Fernandez if (mux_id >= priv->nb_parents) { 219*ae1e5037SGabriel Fernandez panic(); 220*ae1e5037SGabriel Fernandez } 221*ae1e5037SGabriel Fernandez 222*ae1e5037SGabriel Fernandez mux = &priv->parents[mux_id]; 223*ae1e5037SGabriel Fernandez 224*ae1e5037SGabriel Fernandez mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); 225*ae1e5037SGabriel Fernandez 226*ae1e5037SGabriel Fernandez return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift; 227*ae1e5037SGabriel Fernandez } 228*ae1e5037SGabriel Fernandez 229*ae1e5037SGabriel Fernandez static int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel) 230*ae1e5037SGabriel Fernandez { 231*ae1e5037SGabriel Fernandez const struct mux_cfg *mux = &priv->parents[pid]; 232*ae1e5037SGabriel Fernandez uintptr_t address = priv->base + mux->offset; 233*ae1e5037SGabriel Fernandez uint32_t mask; 234*ae1e5037SGabriel Fernandez uint64_t timeout; 235*ae1e5037SGabriel Fernandez 236*ae1e5037SGabriel Fernandez mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); 237*ae1e5037SGabriel Fernandez 238*ae1e5037SGabriel Fernandez mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask); 239*ae1e5037SGabriel Fernandez 240*ae1e5037SGabriel Fernandez if (mux->bitrdy == MUX_NO_BIT_RDY) { 241*ae1e5037SGabriel Fernandez return 0; 242*ae1e5037SGabriel Fernandez } 243*ae1e5037SGabriel Fernandez 244*ae1e5037SGabriel Fernandez timeout = timeout_init_us(CLKSRC_TIMEOUT); 245*ae1e5037SGabriel Fernandez 246*ae1e5037SGabriel Fernandez mask = BIT(mux->bitrdy); 247*ae1e5037SGabriel Fernandez 248*ae1e5037SGabriel Fernandez while ((mmio_read_32(address) & mask) == 0U) { 249*ae1e5037SGabriel Fernandez if (timeout_elapsed(timeout)) { 250*ae1e5037SGabriel Fernandez return -ETIMEDOUT; 251*ae1e5037SGabriel Fernandez } 252*ae1e5037SGabriel Fernandez } 253*ae1e5037SGabriel Fernandez 254*ae1e5037SGabriel Fernandez return 0; 255*ae1e5037SGabriel Fernandez } 256*ae1e5037SGabriel Fernandez 257*ae1e5037SGabriel Fernandez static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t val) 258*ae1e5037SGabriel Fernandez { 259*ae1e5037SGabriel Fernandez uint32_t data = val & CMD_DATA_MASK; 260*ae1e5037SGabriel Fernandez int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; 261*ae1e5037SGabriel Fernandez int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; 262*ae1e5037SGabriel Fernandez 263*ae1e5037SGabriel Fernandez return clk_mux_set_parent(priv, mux, sel); 264*ae1e5037SGabriel Fernandez } 265*ae1e5037SGabriel Fernandez 266*ae1e5037SGabriel Fernandez int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value) 267*ae1e5037SGabriel Fernandez { 268*ae1e5037SGabriel Fernandez const struct div_cfg *divider; 269*ae1e5037SGabriel Fernandez uintptr_t address; 270*ae1e5037SGabriel Fernandez uint64_t timeout; 271*ae1e5037SGabriel Fernandez uint32_t mask; 272*ae1e5037SGabriel Fernandez 273*ae1e5037SGabriel Fernandez if (div_id >= priv->nb_div) { 274*ae1e5037SGabriel Fernandez panic(); 275*ae1e5037SGabriel Fernandez } 276*ae1e5037SGabriel Fernandez 277*ae1e5037SGabriel Fernandez divider = &priv->div[div_id]; 278*ae1e5037SGabriel Fernandez address = priv->base + divider->offset; 279*ae1e5037SGabriel Fernandez 280*ae1e5037SGabriel Fernandez mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); 281*ae1e5037SGabriel Fernandez mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask); 282*ae1e5037SGabriel Fernandez 283*ae1e5037SGabriel Fernandez if (divider->bitrdy == DIV_NO_BIT_RDY) { 284*ae1e5037SGabriel Fernandez return 0; 285*ae1e5037SGabriel Fernandez } 286*ae1e5037SGabriel Fernandez 287*ae1e5037SGabriel Fernandez timeout = timeout_init_us(CLKSRC_TIMEOUT); 288*ae1e5037SGabriel Fernandez mask = BIT(divider->bitrdy); 289*ae1e5037SGabriel Fernandez 290*ae1e5037SGabriel Fernandez while ((mmio_read_32(address) & mask) == 0U) { 291*ae1e5037SGabriel Fernandez if (timeout_elapsed(timeout)) { 292*ae1e5037SGabriel Fernandez return -ETIMEDOUT; 293*ae1e5037SGabriel Fernandez } 294*ae1e5037SGabriel Fernandez } 295*ae1e5037SGabriel Fernandez 296*ae1e5037SGabriel Fernandez return 0; 297*ae1e5037SGabriel Fernandez } 298*ae1e5037SGabriel Fernandez 299f66358afSYann Gautier const char *stm32mp_osc_node_label[NB_OSC] = { 300f66358afSYann Gautier [_LSI] = "clk-lsi", 301f66358afSYann Gautier [_LSE] = "clk-lse", 302f66358afSYann Gautier [_HSI] = "clk-hsi", 303f66358afSYann Gautier [_HSE] = "clk-hse", 304f66358afSYann Gautier [_CSI] = "clk-csi", 305f66358afSYann Gautier [_I2S_CKIN] = "i2s_ckin", 306f66358afSYann Gautier }; 307f66358afSYann Gautier 3087839a050SYann Gautier enum stm32mp1_parent_id { 3097839a050SYann Gautier /* Oscillators are defined in enum stm32mp_osc_id */ 3107839a050SYann Gautier 3117839a050SYann Gautier /* Other parent source */ 3127839a050SYann Gautier _HSI_KER = NB_OSC, 3137839a050SYann Gautier _HSE_KER, 3147839a050SYann Gautier _HSE_KER_DIV2, 315cbd2e8a6SGabriel Fernandez _HSE_RTC, 3167839a050SYann Gautier _CSI_KER, 3177839a050SYann Gautier _PLL1_P, 3187839a050SYann Gautier _PLL1_Q, 3197839a050SYann Gautier _PLL1_R, 3207839a050SYann Gautier _PLL2_P, 3217839a050SYann Gautier _PLL2_Q, 3227839a050SYann Gautier _PLL2_R, 3237839a050SYann Gautier _PLL3_P, 3247839a050SYann Gautier _PLL3_Q, 3257839a050SYann Gautier _PLL3_R, 3267839a050SYann Gautier _PLL4_P, 3277839a050SYann Gautier _PLL4_Q, 3287839a050SYann Gautier _PLL4_R, 3297839a050SYann Gautier _ACLK, 3307839a050SYann Gautier _PCLK1, 3317839a050SYann Gautier _PCLK2, 3327839a050SYann Gautier _PCLK3, 3337839a050SYann Gautier _PCLK4, 3347839a050SYann Gautier _PCLK5, 3357839a050SYann Gautier _HCLK6, 3367839a050SYann Gautier _HCLK2, 3377839a050SYann Gautier _CK_PER, 3387839a050SYann Gautier _CK_MPU, 339b053a22eSYann Gautier _CK_MCU, 3400d21680cSYann Gautier _USB_PHY_48, 3417839a050SYann Gautier _PARENT_NB, 3427839a050SYann Gautier _UNKNOWN_ID = 0xff, 3437839a050SYann Gautier }; 3447839a050SYann Gautier 3450d21680cSYann Gautier /* Lists only the parent clock we are interested in */ 3467839a050SYann Gautier enum stm32mp1_parent_sel { 3470d21680cSYann Gautier _I2C12_SEL, 3480d21680cSYann Gautier _I2C35_SEL, 3490d21680cSYann Gautier _STGEN_SEL, 3507839a050SYann Gautier _I2C46_SEL, 3510d21680cSYann Gautier _SPI6_SEL, 352d4151d2fSYann Gautier _UART1_SEL, 3530d21680cSYann Gautier _RNG1_SEL, 3547839a050SYann Gautier _UART6_SEL, 3557839a050SYann Gautier _UART24_SEL, 3567839a050SYann Gautier _UART35_SEL, 3577839a050SYann Gautier _UART78_SEL, 3587839a050SYann Gautier _SDMMC12_SEL, 3597839a050SYann Gautier _SDMMC3_SEL, 3607839a050SYann Gautier _QSPI_SEL, 3617839a050SYann Gautier _FMC_SEL, 362d4151d2fSYann Gautier _AXIS_SEL, 363d4151d2fSYann Gautier _MCUS_SEL, 3647839a050SYann Gautier _USBPHY_SEL, 3657839a050SYann Gautier _USBO_SEL, 3668fbcd9e4SEtienne Carriere _MPU_SEL, 367288f5cf2SYann Gautier _CKPER_SEL, 368016af006SEtienne Carriere _RTC_SEL, 3697839a050SYann Gautier _PARENT_SEL_NB, 3707839a050SYann Gautier _UNKNOWN_SEL = 0xff, 3717839a050SYann Gautier }; 3727839a050SYann Gautier 3738fbcd9e4SEtienne Carriere /* State the parent clock ID straight related to a clock */ 3748fbcd9e4SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = { 3758fbcd9e4SEtienne Carriere [_HSE] = CK_HSE, 3768fbcd9e4SEtienne Carriere [_HSI] = CK_HSI, 3778fbcd9e4SEtienne Carriere [_CSI] = CK_CSI, 3788fbcd9e4SEtienne Carriere [_LSE] = CK_LSE, 3798fbcd9e4SEtienne Carriere [_LSI] = CK_LSI, 3808fbcd9e4SEtienne Carriere [_I2S_CKIN] = _UNKNOWN_ID, 3818fbcd9e4SEtienne Carriere [_USB_PHY_48] = _UNKNOWN_ID, 3828fbcd9e4SEtienne Carriere [_HSI_KER] = CK_HSI, 3838fbcd9e4SEtienne Carriere [_HSE_KER] = CK_HSE, 3848fbcd9e4SEtienne Carriere [_HSE_KER_DIV2] = CK_HSE_DIV2, 385cbd2e8a6SGabriel Fernandez [_HSE_RTC] = _UNKNOWN_ID, 3868fbcd9e4SEtienne Carriere [_CSI_KER] = CK_CSI, 3878fbcd9e4SEtienne Carriere [_PLL1_P] = PLL1_P, 3888fbcd9e4SEtienne Carriere [_PLL1_Q] = PLL1_Q, 3898fbcd9e4SEtienne Carriere [_PLL1_R] = PLL1_R, 3908fbcd9e4SEtienne Carriere [_PLL2_P] = PLL2_P, 3918fbcd9e4SEtienne Carriere [_PLL2_Q] = PLL2_Q, 3928fbcd9e4SEtienne Carriere [_PLL2_R] = PLL2_R, 3938fbcd9e4SEtienne Carriere [_PLL3_P] = PLL3_P, 3948fbcd9e4SEtienne Carriere [_PLL3_Q] = PLL3_Q, 3958fbcd9e4SEtienne Carriere [_PLL3_R] = PLL3_R, 3968fbcd9e4SEtienne Carriere [_PLL4_P] = PLL4_P, 3978fbcd9e4SEtienne Carriere [_PLL4_Q] = PLL4_Q, 3988fbcd9e4SEtienne Carriere [_PLL4_R] = PLL4_R, 3998fbcd9e4SEtienne Carriere [_ACLK] = CK_AXI, 4008fbcd9e4SEtienne Carriere [_PCLK1] = CK_AXI, 4018fbcd9e4SEtienne Carriere [_PCLK2] = CK_AXI, 4028fbcd9e4SEtienne Carriere [_PCLK3] = CK_AXI, 4038fbcd9e4SEtienne Carriere [_PCLK4] = CK_AXI, 4048fbcd9e4SEtienne Carriere [_PCLK5] = CK_AXI, 4058fbcd9e4SEtienne Carriere [_CK_PER] = CK_PER, 4068fbcd9e4SEtienne Carriere [_CK_MPU] = CK_MPU, 4078fbcd9e4SEtienne Carriere [_CK_MCU] = CK_MCU, 4088fbcd9e4SEtienne Carriere }; 4098fbcd9e4SEtienne Carriere 4108fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id) 4118fbcd9e4SEtienne Carriere { 4128fbcd9e4SEtienne Carriere unsigned int n; 4138fbcd9e4SEtienne Carriere 4148fbcd9e4SEtienne Carriere for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { 4158fbcd9e4SEtienne Carriere if (parent_id_clock_id[n] == id) { 4168fbcd9e4SEtienne Carriere return n; 4178fbcd9e4SEtienne Carriere } 4188fbcd9e4SEtienne Carriere } 4198fbcd9e4SEtienne Carriere 4208fbcd9e4SEtienne Carriere return _UNKNOWN_ID; 4218fbcd9e4SEtienne Carriere } 4228fbcd9e4SEtienne Carriere 4237839a050SYann Gautier enum stm32mp1_pll_id { 4247839a050SYann Gautier _PLL1, 4257839a050SYann Gautier _PLL2, 4267839a050SYann Gautier _PLL3, 4277839a050SYann Gautier _PLL4, 4287839a050SYann Gautier _PLL_NB 4297839a050SYann Gautier }; 4307839a050SYann Gautier 4317839a050SYann Gautier enum stm32mp1_div_id { 4327839a050SYann Gautier _DIV_P, 4337839a050SYann Gautier _DIV_Q, 4347839a050SYann Gautier _DIV_R, 4357839a050SYann Gautier _DIV_NB, 4367839a050SYann Gautier }; 4377839a050SYann Gautier 4387839a050SYann Gautier enum stm32mp1_clksrc_id { 4397839a050SYann Gautier CLKSRC_MPU, 4407839a050SYann Gautier CLKSRC_AXI, 441b053a22eSYann Gautier CLKSRC_MCU, 4427839a050SYann Gautier CLKSRC_PLL12, 4437839a050SYann Gautier CLKSRC_PLL3, 4447839a050SYann Gautier CLKSRC_PLL4, 4457839a050SYann Gautier CLKSRC_RTC, 4467839a050SYann Gautier CLKSRC_MCO1, 4477839a050SYann Gautier CLKSRC_MCO2, 4487839a050SYann Gautier CLKSRC_NB 4497839a050SYann Gautier }; 4507839a050SYann Gautier 4517839a050SYann Gautier enum stm32mp1_clkdiv_id { 4527839a050SYann Gautier CLKDIV_MPU, 4537839a050SYann Gautier CLKDIV_AXI, 454b053a22eSYann Gautier CLKDIV_MCU, 4557839a050SYann Gautier CLKDIV_APB1, 4567839a050SYann Gautier CLKDIV_APB2, 4577839a050SYann Gautier CLKDIV_APB3, 4587839a050SYann Gautier CLKDIV_APB4, 4597839a050SYann Gautier CLKDIV_APB5, 4607839a050SYann Gautier CLKDIV_RTC, 4617839a050SYann Gautier CLKDIV_MCO1, 4627839a050SYann Gautier CLKDIV_MCO2, 4637839a050SYann Gautier CLKDIV_NB 4647839a050SYann Gautier }; 4657839a050SYann Gautier 4667839a050SYann Gautier enum stm32mp1_plltype { 4677839a050SYann Gautier PLL_800, 4687839a050SYann Gautier PLL_1600, 4697839a050SYann Gautier PLL_TYPE_NB 4707839a050SYann Gautier }; 4717839a050SYann Gautier 4727839a050SYann Gautier struct stm32mp1_pll { 4737839a050SYann Gautier uint8_t refclk_min; 4747839a050SYann Gautier uint8_t refclk_max; 4757839a050SYann Gautier }; 4767839a050SYann Gautier 4777839a050SYann Gautier struct stm32mp1_clk_gate { 4787839a050SYann Gautier uint16_t offset; 4797839a050SYann Gautier uint8_t bit; 4807839a050SYann Gautier uint8_t index; 4817839a050SYann Gautier uint8_t set_clr; 482aaa09b71SYann Gautier uint8_t secure; 4830d21680cSYann Gautier uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ 4840d21680cSYann Gautier uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ 4857839a050SYann Gautier }; 4867839a050SYann Gautier 4877839a050SYann Gautier struct stm32mp1_clk_sel { 4887839a050SYann Gautier uint16_t offset; 4897839a050SYann Gautier uint8_t src; 4907839a050SYann Gautier uint8_t msk; 4917839a050SYann Gautier uint8_t nb_parent; 4927839a050SYann Gautier const uint8_t *parent; 4937839a050SYann Gautier }; 4947839a050SYann Gautier 4957839a050SYann Gautier #define REFCLK_SIZE 4 4967839a050SYann Gautier struct stm32mp1_clk_pll { 4977839a050SYann Gautier enum stm32mp1_plltype plltype; 4987839a050SYann Gautier uint16_t rckxselr; 4997839a050SYann Gautier uint16_t pllxcfgr1; 5007839a050SYann Gautier uint16_t pllxcfgr2; 5017839a050SYann Gautier uint16_t pllxfracr; 5027839a050SYann Gautier uint16_t pllxcr; 5037839a050SYann Gautier uint16_t pllxcsgr; 5047839a050SYann Gautier enum stm32mp_osc_id refclk[REFCLK_SIZE]; 5057839a050SYann Gautier }; 5067839a050SYann Gautier 5070d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */ 508aaa09b71SYann Gautier #define _CLK_SELEC(sec, off, b, idx, s) \ 5097839a050SYann Gautier { \ 5107839a050SYann Gautier .offset = (off), \ 5117839a050SYann Gautier .bit = (b), \ 5127839a050SYann Gautier .index = (idx), \ 5137839a050SYann Gautier .set_clr = 0, \ 514aaa09b71SYann Gautier .secure = (sec), \ 5157839a050SYann Gautier .sel = (s), \ 5167839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 5177839a050SYann Gautier } 5187839a050SYann Gautier 5190d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */ 520aaa09b71SYann Gautier #define _CLK_FIXED(sec, off, b, idx, f) \ 5217839a050SYann Gautier { \ 5227839a050SYann Gautier .offset = (off), \ 5237839a050SYann Gautier .bit = (b), \ 5247839a050SYann Gautier .index = (idx), \ 5257839a050SYann Gautier .set_clr = 0, \ 526aaa09b71SYann Gautier .secure = (sec), \ 5277839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 5287839a050SYann Gautier .fixed = (f), \ 5297839a050SYann Gautier } 5307839a050SYann Gautier 5310d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */ 532aaa09b71SYann Gautier #define _CLK_SC_SELEC(sec, off, b, idx, s) \ 5337839a050SYann Gautier { \ 5347839a050SYann Gautier .offset = (off), \ 5357839a050SYann Gautier .bit = (b), \ 5367839a050SYann Gautier .index = (idx), \ 5377839a050SYann Gautier .set_clr = 1, \ 538aaa09b71SYann Gautier .secure = (sec), \ 5397839a050SYann Gautier .sel = (s), \ 5407839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 5417839a050SYann Gautier } 5427839a050SYann Gautier 5430d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */ 544aaa09b71SYann Gautier #define _CLK_SC_FIXED(sec, off, b, idx, f) \ 5457839a050SYann Gautier { \ 5467839a050SYann Gautier .offset = (off), \ 5477839a050SYann Gautier .bit = (b), \ 5487839a050SYann Gautier .index = (idx), \ 5497839a050SYann Gautier .set_clr = 1, \ 550aaa09b71SYann Gautier .secure = (sec), \ 5517839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 5527839a050SYann Gautier .fixed = (f), \ 5537839a050SYann Gautier } 5547839a050SYann Gautier 555d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ 556d4151d2fSYann Gautier [_ ## _label ## _SEL] = { \ 557d4151d2fSYann Gautier .offset = _rcc_selr, \ 558d4151d2fSYann Gautier .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ 5598ae08dcdSEtienne Carriere .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ 5608ae08dcdSEtienne Carriere (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ 561d4151d2fSYann Gautier .parent = (_parents), \ 562d4151d2fSYann Gautier .nb_parent = ARRAY_SIZE(_parents) \ 5637839a050SYann Gautier } 5647839a050SYann Gautier 5650d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3, \ 5667839a050SYann Gautier off4, off5, off6, \ 5677839a050SYann Gautier p1, p2, p3, p4) \ 5687839a050SYann Gautier [(idx)] = { \ 5697839a050SYann Gautier .plltype = (type), \ 5707839a050SYann Gautier .rckxselr = (off1), \ 5717839a050SYann Gautier .pllxcfgr1 = (off2), \ 5727839a050SYann Gautier .pllxcfgr2 = (off3), \ 5737839a050SYann Gautier .pllxfracr = (off4), \ 5747839a050SYann Gautier .pllxcr = (off5), \ 5757839a050SYann Gautier .pllxcsgr = (off6), \ 5767839a050SYann Gautier .refclk[0] = (p1), \ 5777839a050SYann Gautier .refclk[1] = (p2), \ 5787839a050SYann Gautier .refclk[2] = (p3), \ 5797839a050SYann Gautier .refclk[3] = (p4), \ 5807839a050SYann Gautier } 5817839a050SYann Gautier 5820d21680cSYann Gautier #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) 5830d21680cSYann Gautier 584aaa09b71SYann Gautier #define SEC 1 585aaa09b71SYann Gautier #define N_S 0 586aaa09b71SYann Gautier 5877839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { 588aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), 589aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), 590aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), 591aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), 592aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), 593aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), 594aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), 595aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), 596aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), 597aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), 598aaa09b71SYann Gautier _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), 5997839a050SYann Gautier 6007418cf39SYann Gautier #if defined(IMAGE_BL32) 601aaa09b71SYann Gautier _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), 6027418cf39SYann Gautier #endif 603aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), 604aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), 605aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), 606aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), 607aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), 608aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), 609aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), 610aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), 611aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), 612aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), 6137839a050SYann Gautier 6147418cf39SYann Gautier #if defined(IMAGE_BL32) 615aaa09b71SYann Gautier _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), 6167418cf39SYann Gautier #endif 617aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), 6187839a050SYann Gautier 619aaa09b71SYann Gautier _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), 620f33b2433SYann Gautier 621aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), 622aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), 623aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), 6247839a050SYann Gautier 625aaa09b71SYann Gautier _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), 626aaa09b71SYann Gautier _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), 627aaa09b71SYann Gautier _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), 628aaa09b71SYann Gautier _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), 629aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), 630aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), 631aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), 632aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), 633aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), 634aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), 635aaa09b71SYann Gautier _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), 6367839a050SYann Gautier 6377418cf39SYann Gautier #if defined(IMAGE_BL32) 638aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), 639aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), 6407418cf39SYann Gautier #endif 6417839a050SYann Gautier 642aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), 643aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), 644aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), 645aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), 646aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), 647aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), 648aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), 649aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), 650aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), 651aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), 652aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), 6537839a050SYann Gautier 654aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), 655aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), 656aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), 657aaa09b71SYann Gautier _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), 658aaa09b71SYann Gautier _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), 6597839a050SYann Gautier 6607418cf39SYann Gautier #if defined(IMAGE_BL2) 661aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), 662aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), 6637418cf39SYann Gautier #endif 664aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), 665aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), 6667418cf39SYann Gautier #if defined(IMAGE_BL32) 667aaa09b71SYann Gautier _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), 6687418cf39SYann Gautier #endif 6697839a050SYann Gautier 670aaa09b71SYann Gautier _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), 671aaa09b71SYann Gautier _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), 6727839a050SYann Gautier }; 6737839a050SYann Gautier 6740d21680cSYann Gautier static const uint8_t i2c12_parents[] = { 6750d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 6760d21680cSYann Gautier }; 6770d21680cSYann Gautier 6780d21680cSYann Gautier static const uint8_t i2c35_parents[] = { 6790d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 6800d21680cSYann Gautier }; 6810d21680cSYann Gautier 6820d21680cSYann Gautier static const uint8_t stgen_parents[] = { 6830d21680cSYann Gautier _HSI_KER, _HSE_KER 6840d21680cSYann Gautier }; 6850d21680cSYann Gautier 6860d21680cSYann Gautier static const uint8_t i2c46_parents[] = { 6870d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER 6880d21680cSYann Gautier }; 6890d21680cSYann Gautier 6900d21680cSYann Gautier static const uint8_t spi6_parents[] = { 6910d21680cSYann Gautier _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q 6920d21680cSYann Gautier }; 6930d21680cSYann Gautier 6940d21680cSYann Gautier static const uint8_t usart1_parents[] = { 6950d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER 6960d21680cSYann Gautier }; 6970d21680cSYann Gautier 6980d21680cSYann Gautier static const uint8_t rng1_parents[] = { 6990d21680cSYann Gautier _CSI, _PLL4_R, _LSE, _LSI 7000d21680cSYann Gautier }; 7010d21680cSYann Gautier 7020d21680cSYann Gautier static const uint8_t uart6_parents[] = { 7030d21680cSYann Gautier _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 7040d21680cSYann Gautier }; 7050d21680cSYann Gautier 7060d21680cSYann Gautier static const uint8_t uart234578_parents[] = { 7070d21680cSYann Gautier _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 7080d21680cSYann Gautier }; 7090d21680cSYann Gautier 7100d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = { 7110d21680cSYann Gautier _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER 7120d21680cSYann Gautier }; 7130d21680cSYann Gautier 7140d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = { 7150d21680cSYann Gautier _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER 7160d21680cSYann Gautier }; 7170d21680cSYann Gautier 7180d21680cSYann Gautier static const uint8_t qspi_parents[] = { 7190d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 7200d21680cSYann Gautier }; 7210d21680cSYann Gautier 7220d21680cSYann Gautier static const uint8_t fmc_parents[] = { 7230d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 7240d21680cSYann Gautier }; 7250d21680cSYann Gautier 726b8fe48b6SEtienne Carriere static const uint8_t axiss_parents[] = { 727b8fe48b6SEtienne Carriere _HSI, _HSE, _PLL2_P 7280d21680cSYann Gautier }; 7290d21680cSYann Gautier 730b8fe48b6SEtienne Carriere static const uint8_t mcuss_parents[] = { 731b8fe48b6SEtienne Carriere _HSI, _HSE, _CSI, _PLL3_P 732b053a22eSYann Gautier }; 733b053a22eSYann Gautier 7340d21680cSYann Gautier static const uint8_t usbphy_parents[] = { 7350d21680cSYann Gautier _HSE_KER, _PLL4_R, _HSE_KER_DIV2 7360d21680cSYann Gautier }; 7370d21680cSYann Gautier 7380d21680cSYann Gautier static const uint8_t usbo_parents[] = { 7390d21680cSYann Gautier _PLL4_R, _USB_PHY_48 7400d21680cSYann Gautier }; 7417839a050SYann Gautier 7428fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = { 7438fbcd9e4SEtienne Carriere _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ 7448fbcd9e4SEtienne Carriere }; 7458fbcd9e4SEtienne Carriere 7468fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = { 7478fbcd9e4SEtienne Carriere _HSI, _HSE, _CSI, 7488fbcd9e4SEtienne Carriere }; 7498fbcd9e4SEtienne Carriere 750016af006SEtienne Carriere static const uint8_t rtc_parents[] = { 751cbd2e8a6SGabriel Fernandez _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC 752016af006SEtienne Carriere }; 753016af006SEtienne Carriere 7547839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { 755d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), 756d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), 757d4151d2fSYann Gautier _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), 758d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), 759d4151d2fSYann Gautier _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), 760d4151d2fSYann Gautier _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), 761d4151d2fSYann Gautier _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), 7628fbcd9e4SEtienne Carriere _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), 763288f5cf2SYann Gautier _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents), 764016af006SEtienne Carriere _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), 765d4151d2fSYann Gautier _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), 766d4151d2fSYann Gautier _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), 767d4151d2fSYann Gautier _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), 768d4151d2fSYann Gautier _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), 769d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), 770d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), 771d4151d2fSYann Gautier _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), 772d4151d2fSYann Gautier _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), 773b8fe48b6SEtienne Carriere _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents), 774b8fe48b6SEtienne Carriere _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), 775d4151d2fSYann Gautier _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), 776d4151d2fSYann Gautier _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), 7777839a050SYann Gautier }; 7787839a050SYann Gautier 7797839a050SYann Gautier /* Define characteristic of PLL according type */ 780f6559227SYann Gautier #define POST_DIVM_MIN 8000000U 781f6559227SYann Gautier #define POST_DIVM_MAX 16000000U 782f6559227SYann Gautier #define DIVM_MIN 0U 783f6559227SYann Gautier #define DIVM_MAX 63U 784f6559227SYann Gautier #define DIVN_MIN 24U 785f6559227SYann Gautier #define DIVN_MAX 99U 786f6559227SYann Gautier #define DIVP_MIN 0U 787f6559227SYann Gautier #define DIVP_MAX 127U 788f6559227SYann Gautier #define FRAC_MAX 8192U 789f6559227SYann Gautier #define VCO_MIN 800000000U 790f6559227SYann Gautier #define VCO_MAX 1600000000U 791f6559227SYann Gautier 7927839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { 7937839a050SYann Gautier [PLL_800] = { 7947839a050SYann Gautier .refclk_min = 4, 7957839a050SYann Gautier .refclk_max = 16, 7967839a050SYann Gautier }, 7977839a050SYann Gautier [PLL_1600] = { 7987839a050SYann Gautier .refclk_min = 8, 7997839a050SYann Gautier .refclk_max = 16, 8007839a050SYann Gautier }, 8017839a050SYann Gautier }; 8027839a050SYann Gautier 8037839a050SYann Gautier /* PLLNCFGR2 register divider by output */ 8047839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = { 8057839a050SYann Gautier [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, 8067839a050SYann Gautier [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, 8070d21680cSYann Gautier [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, 8087839a050SYann Gautier }; 8097839a050SYann Gautier 8107839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { 8110d21680cSYann Gautier _CLK_PLL(_PLL1, PLL_1600, 8127839a050SYann Gautier RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, 8137839a050SYann Gautier RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, 8147839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 8150d21680cSYann Gautier _CLK_PLL(_PLL2, PLL_1600, 8167839a050SYann Gautier RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, 8177839a050SYann Gautier RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, 8187839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 8190d21680cSYann Gautier _CLK_PLL(_PLL3, PLL_800, 8207839a050SYann Gautier RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, 8217839a050SYann Gautier RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, 8227839a050SYann Gautier _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), 8230d21680cSYann Gautier _CLK_PLL(_PLL4, PLL_800, 8247839a050SYann Gautier RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, 8257839a050SYann Gautier RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, 8267839a050SYann Gautier _HSI, _HSE, _CSI, _I2S_CKIN), 8277839a050SYann Gautier }; 8287839a050SYann Gautier 8297839a050SYann Gautier /* Prescaler table lookups for clock computation */ 830b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ 831b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = { 832b053a22eSYann Gautier 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 833b053a22eSYann Gautier }; 8347839a050SYann Gautier 8357839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ 8367839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div 8377839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div 8387839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = { 8397839a050SYann Gautier 0, 1, 2, 3, 4, 4, 4, 4 8407839a050SYann Gautier }; 8417839a050SYann Gautier 8427839a050SYann Gautier /* div = /1 /2 /3 /4 */ 8437839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = { 8447839a050SYann Gautier 1, 2, 3, 4, 4, 4, 4, 4 8457839a050SYann Gautier }; 8467839a050SYann Gautier 84737e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { 84837e8295aSEtienne Carriere [_HSI] = "HSI", 84937e8295aSEtienne Carriere [_HSE] = "HSE", 85037e8295aSEtienne Carriere [_CSI] = "CSI", 85137e8295aSEtienne Carriere [_LSI] = "LSI", 85237e8295aSEtienne Carriere [_LSE] = "LSE", 85337e8295aSEtienne Carriere [_I2S_CKIN] = "I2S_CKIN", 85437e8295aSEtienne Carriere [_HSI_KER] = "HSI_KER", 85537e8295aSEtienne Carriere [_HSE_KER] = "HSE_KER", 85637e8295aSEtienne Carriere [_HSE_KER_DIV2] = "HSE_KER_DIV2", 857cbd2e8a6SGabriel Fernandez [_HSE_RTC] = "HSE_RTC", 85837e8295aSEtienne Carriere [_CSI_KER] = "CSI_KER", 85937e8295aSEtienne Carriere [_PLL1_P] = "PLL1_P", 86037e8295aSEtienne Carriere [_PLL1_Q] = "PLL1_Q", 86137e8295aSEtienne Carriere [_PLL1_R] = "PLL1_R", 86237e8295aSEtienne Carriere [_PLL2_P] = "PLL2_P", 86337e8295aSEtienne Carriere [_PLL2_Q] = "PLL2_Q", 86437e8295aSEtienne Carriere [_PLL2_R] = "PLL2_R", 86537e8295aSEtienne Carriere [_PLL3_P] = "PLL3_P", 86637e8295aSEtienne Carriere [_PLL3_Q] = "PLL3_Q", 86737e8295aSEtienne Carriere [_PLL3_R] = "PLL3_R", 86837e8295aSEtienne Carriere [_PLL4_P] = "PLL4_P", 86937e8295aSEtienne Carriere [_PLL4_Q] = "PLL4_Q", 87037e8295aSEtienne Carriere [_PLL4_R] = "PLL4_R", 87137e8295aSEtienne Carriere [_ACLK] = "ACLK", 87237e8295aSEtienne Carriere [_PCLK1] = "PCLK1", 87337e8295aSEtienne Carriere [_PCLK2] = "PCLK2", 87437e8295aSEtienne Carriere [_PCLK3] = "PCLK3", 87537e8295aSEtienne Carriere [_PCLK4] = "PCLK4", 87637e8295aSEtienne Carriere [_PCLK5] = "PCLK5", 87737e8295aSEtienne Carriere [_HCLK6] = "KCLK6", 87837e8295aSEtienne Carriere [_HCLK2] = "HCLK2", 87937e8295aSEtienne Carriere [_CK_PER] = "CK_PER", 88037e8295aSEtienne Carriere [_CK_MPU] = "CK_MPU", 88137e8295aSEtienne Carriere [_CK_MCU] = "CK_MCU", 88237e8295aSEtienne Carriere [_USB_PHY_48] = "USB_PHY_48", 88337e8295aSEtienne Carriere }; 88437e8295aSEtienne Carriere 8850d21680cSYann Gautier /* RCC clock device driver private */ 8860d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC]; 8870d21680cSYann Gautier static struct spinlock reg_lock; 8880d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES]; 8890d21680cSYann Gautier static struct spinlock refcount_lock; 8907839a050SYann Gautier 8910d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) 8920d21680cSYann Gautier { 8930d21680cSYann Gautier return &stm32mp1_clk_gate[idx]; 8940d21680cSYann Gautier } 8957839a050SYann Gautier 8963d69149aSYann Gautier #if defined(IMAGE_BL32) 8973d69149aSYann Gautier static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) 8983d69149aSYann Gautier { 8993d69149aSYann Gautier return gate->secure == N_S; 9003d69149aSYann Gautier } 9013d69149aSYann Gautier #endif 9023d69149aSYann Gautier 9030d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) 9040d21680cSYann Gautier { 9050d21680cSYann Gautier return &stm32mp1_clk_sel[idx]; 9060d21680cSYann Gautier } 9070d21680cSYann Gautier 9080d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) 9090d21680cSYann Gautier { 9100d21680cSYann Gautier return &stm32mp1_clk_pll[idx]; 9110d21680cSYann Gautier } 9120d21680cSYann Gautier 9130d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock) 9140d21680cSYann Gautier { 915e463d3f4SYann Gautier if (stm32mp_lock_available()) { 9160d21680cSYann Gautier /* Assume interrupts are masked */ 9170d21680cSYann Gautier spin_lock(lock); 9180d21680cSYann Gautier } 919e463d3f4SYann Gautier } 9200d21680cSYann Gautier 9210d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock) 9220d21680cSYann Gautier { 923e463d3f4SYann Gautier if (stm32mp_lock_available()) { 9240d21680cSYann Gautier spin_unlock(lock); 9250d21680cSYann Gautier } 926e463d3f4SYann Gautier } 9270d21680cSYann Gautier 9280d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void) 9290d21680cSYann Gautier { 9300d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 9311bb9072aSEtienne Carriere uint32_t mask = RCC_TZCR_TZEN; 9320d21680cSYann Gautier 9331bb9072aSEtienne Carriere return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 9340d21680cSYann Gautier } 9350d21680cSYann Gautier 936b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void) 937b053a22eSYann Gautier { 938b053a22eSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 9391bb9072aSEtienne Carriere uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; 940b053a22eSYann Gautier 9411bb9072aSEtienne Carriere return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 942b053a22eSYann Gautier } 943b053a22eSYann Gautier 9440d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void) 9450d21680cSYann Gautier { 9460d21680cSYann Gautier stm32mp1_clk_lock(®_lock); 9470d21680cSYann Gautier } 9480d21680cSYann Gautier 9490d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void) 9500d21680cSYann Gautier { 9510d21680cSYann Gautier stm32mp1_clk_unlock(®_lock); 9520d21680cSYann Gautier } 9530d21680cSYann Gautier 9540d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) 9557839a050SYann Gautier { 9567839a050SYann Gautier if (idx >= NB_OSC) { 9577839a050SYann Gautier return 0; 9587839a050SYann Gautier } 9597839a050SYann Gautier 9600d21680cSYann Gautier return stm32mp1_osc[idx]; 9617839a050SYann Gautier } 9627839a050SYann Gautier 9630d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id) 9647839a050SYann Gautier { 9650d21680cSYann Gautier unsigned int i; 9667839a050SYann Gautier 9670d21680cSYann Gautier for (i = 0U; i < NB_GATES; i++) { 9680d21680cSYann Gautier if (gate_ref(i)->index == id) { 9697839a050SYann Gautier return i; 9707839a050SYann Gautier } 9717839a050SYann Gautier } 9727839a050SYann Gautier 97344fb470bSYann Gautier ERROR("%s: clk id %lu not found\n", __func__, id); 9747839a050SYann Gautier 9757839a050SYann Gautier return -EINVAL; 9767839a050SYann Gautier } 9777839a050SYann Gautier 9780d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) 9797839a050SYann Gautier { 9800d21680cSYann Gautier return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); 9817839a050SYann Gautier } 9827839a050SYann Gautier 9830d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) 9847839a050SYann Gautier { 9850d21680cSYann Gautier return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); 9867839a050SYann Gautier } 9877839a050SYann Gautier 9880d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id) 9897839a050SYann Gautier { 9900d21680cSYann Gautier const struct stm32mp1_clk_sel *sel; 9918fbcd9e4SEtienne Carriere uint32_t p_sel; 9927839a050SYann Gautier int i; 9937839a050SYann Gautier enum stm32mp1_parent_id p; 9947839a050SYann Gautier enum stm32mp1_parent_sel s; 9950d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 9967839a050SYann Gautier 9978fbcd9e4SEtienne Carriere /* Few non gateable clock have a static parent ID, find them */ 9988fbcd9e4SEtienne Carriere i = (int)clock_id2parent_id(id); 9998fbcd9e4SEtienne Carriere if (i != _UNKNOWN_ID) { 10008fbcd9e4SEtienne Carriere return i; 10017839a050SYann Gautier } 10027839a050SYann Gautier 10030d21680cSYann Gautier i = stm32mp1_clk_get_gated_id(id); 10047839a050SYann Gautier if (i < 0) { 10050d21680cSYann Gautier panic(); 10067839a050SYann Gautier } 10077839a050SYann Gautier 10080d21680cSYann Gautier p = stm32mp1_clk_get_fixed_parent(i); 10097839a050SYann Gautier if (p < _PARENT_NB) { 10107839a050SYann Gautier return (int)p; 10117839a050SYann Gautier } 10127839a050SYann Gautier 10130d21680cSYann Gautier s = stm32mp1_clk_get_sel(i); 10140d21680cSYann Gautier if (s == _UNKNOWN_SEL) { 10150d21680cSYann Gautier return -EINVAL; 10160d21680cSYann Gautier } 10177839a050SYann Gautier if (s >= _PARENT_SEL_NB) { 10180d21680cSYann Gautier panic(); 10197839a050SYann Gautier } 10207839a050SYann Gautier 10210d21680cSYann Gautier sel = clk_sel_ref(s); 10228ae08dcdSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) & 10238ae08dcdSEtienne Carriere (sel->msk << sel->src)) >> sel->src; 10240d21680cSYann Gautier if (p_sel < sel->nb_parent) { 10250d21680cSYann Gautier return (int)sel->parent[p_sel]; 10267839a050SYann Gautier } 10277839a050SYann Gautier 10287839a050SYann Gautier return -EINVAL; 10297839a050SYann Gautier } 10307839a050SYann Gautier 10310d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) 10327839a050SYann Gautier { 10330d21680cSYann Gautier uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); 10340d21680cSYann Gautier uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; 10357839a050SYann Gautier 10360d21680cSYann Gautier return stm32mp1_clk_get_fixed(pll->refclk[src]); 10377839a050SYann Gautier } 10387839a050SYann Gautier 10397839a050SYann Gautier /* 10407839a050SYann Gautier * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL 10417839a050SYann Gautier * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) 10427839a050SYann Gautier * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) 10437839a050SYann Gautier * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) 10447839a050SYann Gautier */ 10450d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) 10467839a050SYann Gautier { 10477839a050SYann Gautier unsigned long refclk, fvco; 10487839a050SYann Gautier uint32_t cfgr1, fracr, divm, divn; 10490d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10507839a050SYann Gautier 10510d21680cSYann Gautier cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); 10520d21680cSYann Gautier fracr = mmio_read_32(rcc_base + pll->pllxfracr); 10537839a050SYann Gautier 10547839a050SYann Gautier divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; 10557839a050SYann Gautier divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; 10567839a050SYann Gautier 10570d21680cSYann Gautier refclk = stm32mp1_pll_get_fref(pll); 10587839a050SYann Gautier 10597839a050SYann Gautier /* 10607839a050SYann Gautier * With FRACV : 10617839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) 10627839a050SYann Gautier * Without FRACV 10637839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) 10647839a050SYann Gautier */ 10657839a050SYann Gautier if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { 10660d21680cSYann Gautier uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> 10670d21680cSYann Gautier RCC_PLLNFRACR_FRACV_SHIFT; 10687839a050SYann Gautier unsigned long long numerator, denominator; 10697839a050SYann Gautier 10700d21680cSYann Gautier numerator = (((unsigned long long)divn + 1U) << 13) + fracv; 10710d21680cSYann Gautier numerator = refclk * numerator; 10727839a050SYann Gautier denominator = ((unsigned long long)divm + 1U) << 13; 10737839a050SYann Gautier fvco = (unsigned long)(numerator / denominator); 10747839a050SYann Gautier } else { 10757839a050SYann Gautier fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); 10767839a050SYann Gautier } 10777839a050SYann Gautier 10787839a050SYann Gautier return fvco; 10797839a050SYann Gautier } 10807839a050SYann Gautier 10810d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, 10827839a050SYann Gautier enum stm32mp1_div_id div_id) 10837839a050SYann Gautier { 10840d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 10857839a050SYann Gautier unsigned long dfout; 10867839a050SYann Gautier uint32_t cfgr2, divy; 10877839a050SYann Gautier 10887839a050SYann Gautier if (div_id >= _DIV_NB) { 10897839a050SYann Gautier return 0; 10907839a050SYann Gautier } 10917839a050SYann Gautier 10920d21680cSYann Gautier cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); 10937839a050SYann Gautier divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; 10947839a050SYann Gautier 10950d21680cSYann Gautier dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); 10967839a050SYann Gautier 10977839a050SYann Gautier return dfout; 10987839a050SYann Gautier } 10997839a050SYann Gautier 11000d21680cSYann Gautier static unsigned long get_clock_rate(int p) 11017839a050SYann Gautier { 11027839a050SYann Gautier uint32_t reg, clkdiv; 11037839a050SYann Gautier unsigned long clock = 0; 11040d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 11057839a050SYann Gautier 11067839a050SYann Gautier switch (p) { 11077839a050SYann Gautier case _CK_MPU: 11087839a050SYann Gautier /* MPU sub system */ 11090d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKSELR); 11107839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 11117839a050SYann Gautier case RCC_MPCKSELR_HSI: 11120d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 11137839a050SYann Gautier break; 11147839a050SYann Gautier case RCC_MPCKSELR_HSE: 11150d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 11167839a050SYann Gautier break; 11177839a050SYann Gautier case RCC_MPCKSELR_PLL: 11180d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 11197839a050SYann Gautier break; 11207839a050SYann Gautier case RCC_MPCKSELR_PLL_MPUDIV: 11210d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 11227839a050SYann Gautier 11230d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); 11247839a050SYann Gautier clkdiv = reg & RCC_MPUDIV_MASK; 1125602ae2f2SGabriel Fernandez clock >>= stm32mp1_mpu_div[clkdiv]; 11267839a050SYann Gautier break; 11277839a050SYann Gautier default: 11287839a050SYann Gautier break; 11297839a050SYann Gautier } 11307839a050SYann Gautier break; 11317839a050SYann Gautier /* AXI sub system */ 11327839a050SYann Gautier case _ACLK: 11337839a050SYann Gautier case _HCLK2: 11347839a050SYann Gautier case _HCLK6: 11357839a050SYann Gautier case _PCLK4: 11367839a050SYann Gautier case _PCLK5: 11370d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); 11387839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 11397839a050SYann Gautier case RCC_ASSCKSELR_HSI: 11400d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 11417839a050SYann Gautier break; 11427839a050SYann Gautier case RCC_ASSCKSELR_HSE: 11430d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 11447839a050SYann Gautier break; 11457839a050SYann Gautier case RCC_ASSCKSELR_PLL: 11460d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 11477839a050SYann Gautier break; 11487839a050SYann Gautier default: 11497839a050SYann Gautier break; 11507839a050SYann Gautier } 11517839a050SYann Gautier 11527839a050SYann Gautier /* System clock divider */ 11530d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_AXIDIVR); 11547839a050SYann Gautier clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; 11557839a050SYann Gautier 11567839a050SYann Gautier switch (p) { 11577839a050SYann Gautier case _PCLK4: 11580d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB4DIVR); 11597839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 11607839a050SYann Gautier break; 11617839a050SYann Gautier case _PCLK5: 11620d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB5DIVR); 11637839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 11647839a050SYann Gautier break; 11657839a050SYann Gautier default: 11667839a050SYann Gautier break; 11677839a050SYann Gautier } 11687839a050SYann Gautier break; 1169b053a22eSYann Gautier /* MCU sub system */ 1170b053a22eSYann Gautier case _CK_MCU: 1171b053a22eSYann Gautier case _PCLK1: 1172b053a22eSYann Gautier case _PCLK2: 1173b053a22eSYann Gautier case _PCLK3: 1174b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); 1175b053a22eSYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 1176b053a22eSYann Gautier case RCC_MSSCKSELR_HSI: 1177b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 1178b053a22eSYann Gautier break; 1179b053a22eSYann Gautier case RCC_MSSCKSELR_HSE: 1180b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 1181b053a22eSYann Gautier break; 1182b053a22eSYann Gautier case RCC_MSSCKSELR_CSI: 1183b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 1184b053a22eSYann Gautier break; 1185b053a22eSYann Gautier case RCC_MSSCKSELR_PLL: 1186b053a22eSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 1187b053a22eSYann Gautier break; 1188b053a22eSYann Gautier default: 1189b053a22eSYann Gautier break; 1190b053a22eSYann Gautier } 1191b053a22eSYann Gautier 1192b053a22eSYann Gautier /* MCU clock divider */ 1193b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MCUDIVR); 1194b053a22eSYann Gautier clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; 1195b053a22eSYann Gautier 1196b053a22eSYann Gautier switch (p) { 1197b053a22eSYann Gautier case _PCLK1: 1198b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB1DIVR); 1199b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 1200b053a22eSYann Gautier break; 1201b053a22eSYann Gautier case _PCLK2: 1202b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB2DIVR); 1203b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 1204b053a22eSYann Gautier break; 1205b053a22eSYann Gautier case _PCLK3: 1206b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB3DIVR); 1207b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 1208b053a22eSYann Gautier break; 1209b053a22eSYann Gautier case _CK_MCU: 1210b053a22eSYann Gautier default: 1211b053a22eSYann Gautier break; 1212b053a22eSYann Gautier } 1213b053a22eSYann Gautier break; 12147839a050SYann Gautier case _CK_PER: 12150d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); 12167839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 12177839a050SYann Gautier case RCC_CPERCKSELR_HSI: 12180d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 12197839a050SYann Gautier break; 12207839a050SYann Gautier case RCC_CPERCKSELR_HSE: 12210d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 12227839a050SYann Gautier break; 12237839a050SYann Gautier case RCC_CPERCKSELR_CSI: 12240d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 12257839a050SYann Gautier break; 12267839a050SYann Gautier default: 12277839a050SYann Gautier break; 12287839a050SYann Gautier } 12297839a050SYann Gautier break; 12307839a050SYann Gautier case _HSI: 12317839a050SYann Gautier case _HSI_KER: 12320d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 12337839a050SYann Gautier break; 12347839a050SYann Gautier case _CSI: 12357839a050SYann Gautier case _CSI_KER: 12360d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 12377839a050SYann Gautier break; 12387839a050SYann Gautier case _HSE: 12397839a050SYann Gautier case _HSE_KER: 12400d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 12417839a050SYann Gautier break; 12427839a050SYann Gautier case _HSE_KER_DIV2: 12430d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE) >> 1; 12447839a050SYann Gautier break; 1245cbd2e8a6SGabriel Fernandez case _HSE_RTC: 1246cbd2e8a6SGabriel Fernandez clock = stm32mp1_clk_get_fixed(_HSE); 1247cbd2e8a6SGabriel Fernandez clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; 1248cbd2e8a6SGabriel Fernandez break; 12497839a050SYann Gautier case _LSI: 12500d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSI); 12517839a050SYann Gautier break; 12527839a050SYann Gautier case _LSE: 12530d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSE); 12547839a050SYann Gautier break; 12557839a050SYann Gautier /* PLL */ 12567839a050SYann Gautier case _PLL1_P: 12570d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 12587839a050SYann Gautier break; 12597839a050SYann Gautier case _PLL1_Q: 12600d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); 12617839a050SYann Gautier break; 12627839a050SYann Gautier case _PLL1_R: 12630d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); 12647839a050SYann Gautier break; 12657839a050SYann Gautier case _PLL2_P: 12660d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 12677839a050SYann Gautier break; 12687839a050SYann Gautier case _PLL2_Q: 12690d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); 12707839a050SYann Gautier break; 12717839a050SYann Gautier case _PLL2_R: 12720d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); 12737839a050SYann Gautier break; 12747839a050SYann Gautier case _PLL3_P: 12750d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 12767839a050SYann Gautier break; 12777839a050SYann Gautier case _PLL3_Q: 12780d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); 12797839a050SYann Gautier break; 12807839a050SYann Gautier case _PLL3_R: 12810d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); 12827839a050SYann Gautier break; 12837839a050SYann Gautier case _PLL4_P: 12840d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); 12857839a050SYann Gautier break; 12867839a050SYann Gautier case _PLL4_Q: 12870d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); 12887839a050SYann Gautier break; 12897839a050SYann Gautier case _PLL4_R: 12900d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); 12917839a050SYann Gautier break; 12927839a050SYann Gautier /* Other */ 12937839a050SYann Gautier case _USB_PHY_48: 12940d21680cSYann Gautier clock = USB_PHY_48_MHZ; 12957839a050SYann Gautier break; 12967839a050SYann Gautier default: 12977839a050SYann Gautier break; 12987839a050SYann Gautier } 12997839a050SYann Gautier 13007839a050SYann Gautier return clock; 13017839a050SYann Gautier } 13027839a050SYann Gautier 13030d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate) 13040d21680cSYann Gautier { 13050d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13060d21680cSYann Gautier 130725be845eSEtienne Carriere VERBOSE("Enable clock %u\n", gate->index); 130825be845eSEtienne Carriere 13090d21680cSYann Gautier if (gate->set_clr != 0U) { 13100d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); 13110d21680cSYann Gautier } else { 13120d21680cSYann Gautier mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); 13130d21680cSYann Gautier } 13140d21680cSYann Gautier } 13150d21680cSYann Gautier 13160d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate) 13170d21680cSYann Gautier { 13180d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13190d21680cSYann Gautier 132025be845eSEtienne Carriere VERBOSE("Disable clock %u\n", gate->index); 132125be845eSEtienne Carriere 13220d21680cSYann Gautier if (gate->set_clr != 0U) { 13230d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, 13240d21680cSYann Gautier BIT(gate->bit)); 13250d21680cSYann Gautier } else { 13260d21680cSYann Gautier mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); 13270d21680cSYann Gautier } 13280d21680cSYann Gautier } 13290d21680cSYann Gautier 13300d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) 13310d21680cSYann Gautier { 13320d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13330d21680cSYann Gautier 13340d21680cSYann Gautier return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); 13350d21680cSYann Gautier } 13360d21680cSYann Gautier 133735848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */ 133835848200SEtienne Carriere static bool clock_is_always_on(unsigned long id) 133935848200SEtienne Carriere { 134035848200SEtienne Carriere switch (id) { 134135848200SEtienne Carriere case CK_HSE: 134235848200SEtienne Carriere case CK_CSI: 134335848200SEtienne Carriere case CK_LSI: 134435848200SEtienne Carriere case CK_LSE: 134535848200SEtienne Carriere case CK_HSI: 134635848200SEtienne Carriere case CK_HSE_DIV2: 134735848200SEtienne Carriere case PLL1_Q: 134835848200SEtienne Carriere case PLL1_R: 134935848200SEtienne Carriere case PLL2_P: 135035848200SEtienne Carriere case PLL2_Q: 135135848200SEtienne Carriere case PLL2_R: 135235848200SEtienne Carriere case PLL3_P: 135335848200SEtienne Carriere case PLL3_Q: 135435848200SEtienne Carriere case PLL3_R: 1355bf39318dSYann Gautier case CK_AXI: 1356bf39318dSYann Gautier case CK_MPU: 1357bf39318dSYann Gautier case CK_MCU: 13585b111c74SHE Shushan case RTC: 135935848200SEtienne Carriere return true; 136035848200SEtienne Carriere default: 136135848200SEtienne Carriere return false; 136235848200SEtienne Carriere } 136335848200SEtienne Carriere } 136435848200SEtienne Carriere 13652444d231SYann Gautier static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) 13660d21680cSYann Gautier { 13670d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 136835848200SEtienne Carriere int i; 13690d21680cSYann Gautier 137035848200SEtienne Carriere if (clock_is_always_on(id)) { 137135848200SEtienne Carriere return; 137235848200SEtienne Carriere } 137335848200SEtienne Carriere 137435848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 13750d21680cSYann Gautier if (i < 0) { 137644fb470bSYann Gautier ERROR("Clock %lu can't be enabled\n", id); 13770d21680cSYann Gautier panic(); 13780d21680cSYann Gautier } 13790d21680cSYann Gautier 13800d21680cSYann Gautier gate = gate_ref(i); 13812444d231SYann Gautier 13822444d231SYann Gautier if (!with_refcnt) { 13832444d231SYann Gautier __clk_enable(gate); 13842444d231SYann Gautier return; 13852444d231SYann Gautier } 13860d21680cSYann Gautier 13873d69149aSYann Gautier #if defined(IMAGE_BL32) 13883d69149aSYann Gautier if (gate_is_non_secure(gate)) { 13893d69149aSYann Gautier /* Enable non-secure clock w/o any refcounting */ 13903d69149aSYann Gautier __clk_enable(gate); 13913d69149aSYann Gautier return; 13923d69149aSYann Gautier } 13933d69149aSYann Gautier #endif 13943d69149aSYann Gautier 13950d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 13960d21680cSYann Gautier 13972444d231SYann Gautier if (gate_refcounts[i] == 0U) { 13980d21680cSYann Gautier __clk_enable(gate); 13990d21680cSYann Gautier } 14000d21680cSYann Gautier 14012444d231SYann Gautier gate_refcounts[i]++; 14022444d231SYann Gautier if (gate_refcounts[i] == UINT_MAX) { 14032444d231SYann Gautier ERROR("Clock %lu refcount reached max value\n", id); 14042444d231SYann Gautier panic(); 14052444d231SYann Gautier } 14062444d231SYann Gautier 14070d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 14080d21680cSYann Gautier } 14090d21680cSYann Gautier 14102444d231SYann Gautier static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) 14110d21680cSYann Gautier { 14120d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 141335848200SEtienne Carriere int i; 14140d21680cSYann Gautier 141535848200SEtienne Carriere if (clock_is_always_on(id)) { 141635848200SEtienne Carriere return; 141735848200SEtienne Carriere } 141835848200SEtienne Carriere 141935848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 14200d21680cSYann Gautier if (i < 0) { 142144fb470bSYann Gautier ERROR("Clock %lu can't be disabled\n", id); 14220d21680cSYann Gautier panic(); 14230d21680cSYann Gautier } 14240d21680cSYann Gautier 14250d21680cSYann Gautier gate = gate_ref(i); 14262444d231SYann Gautier 14272444d231SYann Gautier if (!with_refcnt) { 14282444d231SYann Gautier __clk_disable(gate); 14292444d231SYann Gautier return; 14302444d231SYann Gautier } 14310d21680cSYann Gautier 14323d69149aSYann Gautier #if defined(IMAGE_BL32) 14333d69149aSYann Gautier if (gate_is_non_secure(gate)) { 14343d69149aSYann Gautier /* Don't disable non-secure clocks */ 14353d69149aSYann Gautier return; 14363d69149aSYann Gautier } 14373d69149aSYann Gautier #endif 14383d69149aSYann Gautier 14390d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 14400d21680cSYann Gautier 14412444d231SYann Gautier if (gate_refcounts[i] == 0U) { 14422444d231SYann Gautier ERROR("Clock %lu refcount reached 0\n", id); 14432444d231SYann Gautier panic(); 14442444d231SYann Gautier } 14452444d231SYann Gautier gate_refcounts[i]--; 14462444d231SYann Gautier 14472444d231SYann Gautier if (gate_refcounts[i] == 0U) { 14480d21680cSYann Gautier __clk_disable(gate); 14490d21680cSYann Gautier } 14500d21680cSYann Gautier 14510d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 14520d21680cSYann Gautier } 14530d21680cSYann Gautier 145433667d29SYann Gautier static int stm32mp_clk_enable(unsigned long id) 14550d21680cSYann Gautier { 14560d21680cSYann Gautier __stm32mp1_clk_enable(id, true); 145733667d29SYann Gautier 145833667d29SYann Gautier return 0; 14590d21680cSYann Gautier } 14600d21680cSYann Gautier 146133667d29SYann Gautier static void stm32mp_clk_disable(unsigned long id) 14620d21680cSYann Gautier { 14630d21680cSYann Gautier __stm32mp1_clk_disable(id, true); 14640d21680cSYann Gautier } 14650d21680cSYann Gautier 146633667d29SYann Gautier static bool stm32mp_clk_is_enabled(unsigned long id) 14677839a050SYann Gautier { 146835848200SEtienne Carriere int i; 14697839a050SYann Gautier 147035848200SEtienne Carriere if (clock_is_always_on(id)) { 147135848200SEtienne Carriere return true; 147235848200SEtienne Carriere } 147335848200SEtienne Carriere 147435848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 14757839a050SYann Gautier if (i < 0) { 14760d21680cSYann Gautier panic(); 14777839a050SYann Gautier } 14787839a050SYann Gautier 14790d21680cSYann Gautier return __clk_is_enabled(gate_ref(i)); 14807839a050SYann Gautier } 14817839a050SYann Gautier 148233667d29SYann Gautier static unsigned long stm32mp_clk_get_rate(unsigned long id) 14837839a050SYann Gautier { 148433667d29SYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 14850d21680cSYann Gautier int p = stm32mp1_clk_get_parent(id); 148633667d29SYann Gautier uint32_t prescaler, timpre; 148733667d29SYann Gautier unsigned long parent_rate; 14887839a050SYann Gautier 14897839a050SYann Gautier if (p < 0) { 14907839a050SYann Gautier return 0; 14917839a050SYann Gautier } 14927839a050SYann Gautier 149333667d29SYann Gautier parent_rate = get_clock_rate(p); 149433667d29SYann Gautier 149533667d29SYann Gautier switch (id) { 149633667d29SYann Gautier case TIM2_K: 149733667d29SYann Gautier case TIM3_K: 149833667d29SYann Gautier case TIM4_K: 149933667d29SYann Gautier case TIM5_K: 150033667d29SYann Gautier case TIM6_K: 150133667d29SYann Gautier case TIM7_K: 150233667d29SYann Gautier case TIM12_K: 150333667d29SYann Gautier case TIM13_K: 150433667d29SYann Gautier case TIM14_K: 150533667d29SYann Gautier prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & 150633667d29SYann Gautier RCC_APBXDIV_MASK; 150733667d29SYann Gautier timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & 150833667d29SYann Gautier RCC_TIMGXPRER_TIMGXPRE; 150933667d29SYann Gautier break; 151033667d29SYann Gautier 151133667d29SYann Gautier case TIM1_K: 151233667d29SYann Gautier case TIM8_K: 151333667d29SYann Gautier case TIM15_K: 151433667d29SYann Gautier case TIM16_K: 151533667d29SYann Gautier case TIM17_K: 151633667d29SYann Gautier prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & 151733667d29SYann Gautier RCC_APBXDIV_MASK; 151833667d29SYann Gautier timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & 151933667d29SYann Gautier RCC_TIMGXPRER_TIMGXPRE; 152033667d29SYann Gautier break; 152133667d29SYann Gautier 152233667d29SYann Gautier default: 152333667d29SYann Gautier return parent_rate; 152433667d29SYann Gautier } 152533667d29SYann Gautier 152633667d29SYann Gautier if (prescaler == 0U) { 152733667d29SYann Gautier return parent_rate; 152833667d29SYann Gautier } 152933667d29SYann Gautier 153033667d29SYann Gautier return parent_rate * (timpre + 1U) * 2U; 15317839a050SYann Gautier } 15327839a050SYann Gautier 15330d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) 15347839a050SYann Gautier { 15350d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 15367839a050SYann Gautier 15370d21680cSYann Gautier if (enable) { 15387839a050SYann Gautier mmio_setbits_32(address, mask_on); 15397839a050SYann Gautier } else { 15407839a050SYann Gautier mmio_clrbits_32(address, mask_on); 15417839a050SYann Gautier } 15427839a050SYann Gautier } 15437839a050SYann Gautier 15440d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) 15457839a050SYann Gautier { 15460d21680cSYann Gautier uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; 15470d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 15480d21680cSYann Gautier 15490d21680cSYann Gautier mmio_write_32(address, mask_on); 15507839a050SYann Gautier } 15517839a050SYann Gautier 15520d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) 15537839a050SYann Gautier { 1554dfdb057aSYann Gautier uint64_t timeout; 15557839a050SYann Gautier uint32_t mask_test; 15560d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 15577839a050SYann Gautier 15580d21680cSYann Gautier if (enable) { 15597839a050SYann Gautier mask_test = mask_rdy; 15607839a050SYann Gautier } else { 15617839a050SYann Gautier mask_test = 0; 15627839a050SYann Gautier } 15637839a050SYann Gautier 1564dfdb057aSYann Gautier timeout = timeout_init_us(OSCRDY_TIMEOUT); 15657839a050SYann Gautier while ((mmio_read_32(address) & mask_rdy) != mask_test) { 1566dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 15670d21680cSYann Gautier ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", 15687839a050SYann Gautier mask_rdy, address, enable, mmio_read_32(address)); 15697839a050SYann Gautier return -ETIMEDOUT; 15707839a050SYann Gautier } 15717839a050SYann Gautier } 15727839a050SYann Gautier 15737839a050SYann Gautier return 0; 15747839a050SYann Gautier } 15757839a050SYann Gautier 15760d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) 15777839a050SYann Gautier { 15787839a050SYann Gautier uint32_t value; 15790d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 15807839a050SYann Gautier 1581f4a2bb98SYann Gautier /* Do not reconfigure LSE if it is already ON */ 1582f4a2bb98SYann Gautier if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEON) == RCC_BDCR_LSEON) { 1583f4a2bb98SYann Gautier return; 1584f4a2bb98SYann Gautier } 1585f4a2bb98SYann Gautier 15860d21680cSYann Gautier if (digbyp) { 15870d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); 15880d21680cSYann Gautier } 15890d21680cSYann Gautier 15900d21680cSYann Gautier if (bypass || digbyp) { 15910d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); 15927839a050SYann Gautier } 15937839a050SYann Gautier 15947839a050SYann Gautier /* 15957839a050SYann Gautier * Warning: not recommended to switch directly from "high drive" 15967839a050SYann Gautier * to "medium low drive", and vice-versa. 15977839a050SYann Gautier */ 15980d21680cSYann Gautier value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> 15997839a050SYann Gautier RCC_BDCR_LSEDRV_SHIFT; 16007839a050SYann Gautier 16017839a050SYann Gautier while (value != lsedrv) { 16027839a050SYann Gautier if (value > lsedrv) { 16037839a050SYann Gautier value--; 16047839a050SYann Gautier } else { 16057839a050SYann Gautier value++; 16067839a050SYann Gautier } 16077839a050SYann Gautier 16080d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_BDCR, 16097839a050SYann Gautier RCC_BDCR_LSEDRV_MASK, 16107839a050SYann Gautier value << RCC_BDCR_LSEDRV_SHIFT); 16117839a050SYann Gautier } 16127839a050SYann Gautier 16130d21680cSYann Gautier stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); 16147839a050SYann Gautier } 16157839a050SYann Gautier 16160d21680cSYann Gautier static void stm32mp1_lse_wait(void) 16177839a050SYann Gautier { 16180d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { 16197839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 16207839a050SYann Gautier } 16217839a050SYann Gautier } 16227839a050SYann Gautier 16230d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable) 16247839a050SYann Gautier { 16250d21680cSYann Gautier stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); 16260d21680cSYann Gautier 16270d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { 16287839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 16297839a050SYann Gautier } 16307839a050SYann Gautier } 16317839a050SYann Gautier 16320d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) 16337839a050SYann Gautier { 16340d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 16350d21680cSYann Gautier 16360d21680cSYann Gautier if (digbyp) { 16370d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); 16387839a050SYann Gautier } 16397839a050SYann Gautier 16400d21680cSYann Gautier if (bypass || digbyp) { 16410d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); 16420d21680cSYann Gautier } 16430d21680cSYann Gautier 16440d21680cSYann Gautier stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); 16450d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { 16467839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 16477839a050SYann Gautier } 16487839a050SYann Gautier 16497839a050SYann Gautier if (css) { 16500d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); 16517839a050SYann Gautier } 165231e9750bSLionel Debieve 165331e9750bSLionel Debieve #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER 165431e9750bSLionel Debieve if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) && 165531e9750bSLionel Debieve (!(digbyp || bypass))) { 165631e9750bSLionel Debieve panic(); 165731e9750bSLionel Debieve } 165831e9750bSLionel Debieve #endif 16597839a050SYann Gautier } 16607839a050SYann Gautier 16610d21680cSYann Gautier static void stm32mp1_csi_set(bool enable) 16627839a050SYann Gautier { 16630d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); 16640d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { 16657839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 16667839a050SYann Gautier } 16677839a050SYann Gautier } 16687839a050SYann Gautier 16690d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable) 16707839a050SYann Gautier { 16710d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); 16720d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { 16737839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 16747839a050SYann Gautier } 16757839a050SYann Gautier } 16767839a050SYann Gautier 16770d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv) 16787839a050SYann Gautier { 1679dfdb057aSYann Gautier uint64_t timeout; 16800d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 16810d21680cSYann Gautier uintptr_t address = rcc_base + RCC_OCRDYR; 16827839a050SYann Gautier 16830d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, 16847839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK, 16857839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); 16867839a050SYann Gautier 1687dfdb057aSYann Gautier timeout = timeout_init_us(HSIDIV_TIMEOUT); 16887839a050SYann Gautier while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { 1689dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 16900d21680cSYann Gautier ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", 16917839a050SYann Gautier address, mmio_read_32(address)); 16927839a050SYann Gautier return -ETIMEDOUT; 16937839a050SYann Gautier } 16947839a050SYann Gautier } 16957839a050SYann Gautier 16967839a050SYann Gautier return 0; 16977839a050SYann Gautier } 16987839a050SYann Gautier 16990d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq) 17007839a050SYann Gautier { 17017839a050SYann Gautier uint8_t hsidiv; 17027839a050SYann Gautier uint32_t hsidivfreq = MAX_HSI_HZ; 17037839a050SYann Gautier 17047839a050SYann Gautier for (hsidiv = 0; hsidiv < 4U; hsidiv++) { 17057839a050SYann Gautier if (hsidivfreq == hsifreq) { 17067839a050SYann Gautier break; 17077839a050SYann Gautier } 17087839a050SYann Gautier 17097839a050SYann Gautier hsidivfreq /= 2U; 17107839a050SYann Gautier } 17117839a050SYann Gautier 17127839a050SYann Gautier if (hsidiv == 4U) { 17137839a050SYann Gautier ERROR("Invalid clk-hsi frequency\n"); 17147839a050SYann Gautier return -1; 17157839a050SYann Gautier } 17167839a050SYann Gautier 17177839a050SYann Gautier if (hsidiv != 0U) { 17180d21680cSYann Gautier return stm32mp1_set_hsidiv(hsidiv); 17197839a050SYann Gautier } 17207839a050SYann Gautier 17217839a050SYann Gautier return 0; 17227839a050SYann Gautier } 17237839a050SYann Gautier 17240d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, 17250d21680cSYann Gautier unsigned int clksrc, 1726*ae1e5037SGabriel Fernandez uint32_t *pllcfg, uint32_t fracv) 17277839a050SYann Gautier { 17280d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 17290d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 17300d21680cSYann Gautier uintptr_t pllxcr = rcc_base + pll->pllxcr; 17310d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 17320d21680cSYann Gautier uintptr_t clksrc_address = rcc_base + (clksrc >> 4); 17330d21680cSYann Gautier unsigned long refclk; 17340d21680cSYann Gautier uint32_t ifrge = 0U; 1735*ae1e5037SGabriel Fernandez uint32_t src, value; 17367839a050SYann Gautier 17370d21680cSYann Gautier /* Check PLL output */ 17380d21680cSYann Gautier if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { 17390d21680cSYann Gautier return false; 17407839a050SYann Gautier } 17417839a050SYann Gautier 17420d21680cSYann Gautier /* Check current clksrc */ 17430d21680cSYann Gautier src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; 17440d21680cSYann Gautier if (src != (clksrc & RCC_SELR_SRC_MASK)) { 17450d21680cSYann Gautier return false; 17460d21680cSYann Gautier } 17470d21680cSYann Gautier 17480d21680cSYann Gautier /* Check Div */ 17490d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; 17500d21680cSYann Gautier 17510d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 17520d21680cSYann Gautier (pllcfg[PLLCFG_M] + 1U); 17530d21680cSYann Gautier 17540d21680cSYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 17550d21680cSYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 17560d21680cSYann Gautier return false; 17570d21680cSYann Gautier } 17580d21680cSYann Gautier 17590d21680cSYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 17600d21680cSYann Gautier ifrge = 1U; 17610d21680cSYann Gautier } 17620d21680cSYann Gautier 17630d21680cSYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 17640d21680cSYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 17650d21680cSYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 17660d21680cSYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 17670d21680cSYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 17680d21680cSYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 17690d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { 17700d21680cSYann Gautier return false; 17710d21680cSYann Gautier } 17720d21680cSYann Gautier 17730d21680cSYann Gautier /* Fractional configuration */ 17740d21680cSYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 17750d21680cSYann Gautier value |= RCC_PLLNFRACR_FRACLE; 17760d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { 17770d21680cSYann Gautier return false; 17780d21680cSYann Gautier } 17790d21680cSYann Gautier 17800d21680cSYann Gautier /* Output config */ 17810d21680cSYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 17820d21680cSYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 17830d21680cSYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 17840d21680cSYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 17850d21680cSYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 17860d21680cSYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 17870d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { 17880d21680cSYann Gautier return false; 17890d21680cSYann Gautier } 17900d21680cSYann Gautier 17910d21680cSYann Gautier return true; 17920d21680cSYann Gautier } 17930d21680cSYann Gautier 17940d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) 17957839a050SYann Gautier { 17960d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 17970d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 17980d21680cSYann Gautier 1799dd98aec8SYann Gautier /* Preserve RCC_PLLNCR_SSCG_CTRL value */ 1800dd98aec8SYann Gautier mmio_clrsetbits_32(pllxcr, 1801dd98aec8SYann Gautier RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 1802dd98aec8SYann Gautier RCC_PLLNCR_DIVREN, 1803dd98aec8SYann Gautier RCC_PLLNCR_PLLON); 18040d21680cSYann Gautier } 18050d21680cSYann Gautier 18060d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) 18070d21680cSYann Gautier { 18080d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 18090d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1810dfdb057aSYann Gautier uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); 18117839a050SYann Gautier 18127839a050SYann Gautier /* Wait PLL lock */ 18137839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { 1814dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 18159fa9a0c5SYann Gautier ERROR("PLL%u start failed @ 0x%lx: 0x%x\n", 18167839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 18177839a050SYann Gautier return -ETIMEDOUT; 18187839a050SYann Gautier } 18197839a050SYann Gautier } 18207839a050SYann Gautier 18217839a050SYann Gautier /* Start the requested output */ 18227839a050SYann Gautier mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); 18237839a050SYann Gautier 18247839a050SYann Gautier return 0; 18257839a050SYann Gautier } 18267839a050SYann Gautier 18270d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) 18287839a050SYann Gautier { 18290d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 18300d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1831dfdb057aSYann Gautier uint64_t timeout; 18327839a050SYann Gautier 18337839a050SYann Gautier /* Stop all output */ 18347839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 18357839a050SYann Gautier RCC_PLLNCR_DIVREN); 18367839a050SYann Gautier 18377839a050SYann Gautier /* Stop PLL */ 18387839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); 18397839a050SYann Gautier 1840dfdb057aSYann Gautier timeout = timeout_init_us(PLLRDY_TIMEOUT); 18417839a050SYann Gautier /* Wait PLL stopped */ 18427839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { 1843dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 18449fa9a0c5SYann Gautier ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n", 18457839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 18467839a050SYann Gautier return -ETIMEDOUT; 18477839a050SYann Gautier } 18487839a050SYann Gautier } 18497839a050SYann Gautier 18507839a050SYann Gautier return 0; 18517839a050SYann Gautier } 18527839a050SYann Gautier 18530d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, 18547839a050SYann Gautier uint32_t *pllcfg) 18557839a050SYann Gautier { 18560d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 18570d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 18587839a050SYann Gautier uint32_t value; 18597839a050SYann Gautier 18607839a050SYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 18617839a050SYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 18627839a050SYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 18637839a050SYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 18647839a050SYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 18657839a050SYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 18660d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr2, value); 18677839a050SYann Gautier } 18687839a050SYann Gautier 18690d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, 18707839a050SYann Gautier uint32_t *pllcfg, uint32_t fracv) 18717839a050SYann Gautier { 18720d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 18730d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 18740d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 18757839a050SYann Gautier unsigned long refclk; 18767839a050SYann Gautier uint32_t ifrge = 0; 18777839a050SYann Gautier uint32_t src, value; 18787839a050SYann Gautier 18790d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & 18807839a050SYann Gautier RCC_SELR_REFCLK_SRC_MASK; 18817839a050SYann Gautier 18820d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 18837839a050SYann Gautier (pllcfg[PLLCFG_M] + 1U); 18847839a050SYann Gautier 18857839a050SYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 18867839a050SYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 18877839a050SYann Gautier return -EINVAL; 18887839a050SYann Gautier } 18897839a050SYann Gautier 18907839a050SYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 18917839a050SYann Gautier ifrge = 1U; 18927839a050SYann Gautier } 18937839a050SYann Gautier 18947839a050SYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 18957839a050SYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 18967839a050SYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 18977839a050SYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 18987839a050SYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 18997839a050SYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 19000d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr1, value); 19017839a050SYann Gautier 19027839a050SYann Gautier /* Fractional configuration */ 19037839a050SYann Gautier value = 0; 19040d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 19057839a050SYann Gautier 19067839a050SYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 19070d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 19087839a050SYann Gautier 19097839a050SYann Gautier value |= RCC_PLLNFRACR_FRACLE; 19100d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 19117839a050SYann Gautier 19120d21680cSYann Gautier stm32mp1_pll_config_output(pll_id, pllcfg); 19137839a050SYann Gautier 19147839a050SYann Gautier return 0; 19157839a050SYann Gautier } 19167839a050SYann Gautier 19170d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) 19187839a050SYann Gautier { 19190d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 19207839a050SYann Gautier uint32_t pllxcsg = 0; 19217839a050SYann Gautier 19227839a050SYann Gautier pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & 19237839a050SYann Gautier RCC_PLLNCSGR_MOD_PER_MASK; 19247839a050SYann Gautier 19257839a050SYann Gautier pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & 19267839a050SYann Gautier RCC_PLLNCSGR_INC_STEP_MASK; 19277839a050SYann Gautier 19287839a050SYann Gautier pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & 19297839a050SYann Gautier RCC_PLLNCSGR_SSCG_MODE_MASK; 19307839a050SYann Gautier 19310d21680cSYann Gautier mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); 1932dd98aec8SYann Gautier 1933dd98aec8SYann Gautier mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, 1934dd98aec8SYann Gautier RCC_PLLNCR_SSCG_CTRL); 19357839a050SYann Gautier } 19367839a050SYann Gautier 1937f6559227SYann Gautier static int clk_compute_pll1_settings(unsigned long input_freq, 1938f6559227SYann Gautier uint32_t freq_khz, 1939f6559227SYann Gautier uint32_t *pllcfg, uint32_t *fracv) 1940f6559227SYann Gautier { 1941f6559227SYann Gautier unsigned long long best_diff = ULLONG_MAX; 1942f6559227SYann Gautier unsigned int divm; 1943f6559227SYann Gautier 1944f6559227SYann Gautier /* Following parameters have always the same value */ 1945f6559227SYann Gautier pllcfg[PLLCFG_Q] = 0U; 1946f6559227SYann Gautier pllcfg[PLLCFG_R] = 0U; 1947f6559227SYann Gautier pllcfg[PLLCFG_O] = PQR(1, 0, 0); 1948f6559227SYann Gautier 1949f6559227SYann Gautier for (divm = (DIVM_MAX + 1U); divm != DIVM_MIN; divm--) { 1950f6559227SYann Gautier unsigned long post_divm = input_freq / divm; 1951f6559227SYann Gautier unsigned int divp; 1952f6559227SYann Gautier 1953f6559227SYann Gautier if ((post_divm < POST_DIVM_MIN) || (post_divm > POST_DIVM_MAX)) { 1954f6559227SYann Gautier continue; 1955f6559227SYann Gautier } 1956f6559227SYann Gautier 1957f6559227SYann Gautier for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { 1958f6559227SYann Gautier unsigned long long output_freq = freq_khz * 1000ULL; 1959f6559227SYann Gautier unsigned long long freq; 1960f6559227SYann Gautier unsigned long long divn; 1961f6559227SYann Gautier unsigned long long frac; 1962f6559227SYann Gautier unsigned int i; 1963f6559227SYann Gautier 1964f6559227SYann Gautier freq = output_freq * divm * (divp + 1U); 1965f6559227SYann Gautier 1966f6559227SYann Gautier divn = (freq / input_freq) - 1U; 1967f6559227SYann Gautier if ((divn < DIVN_MIN) || (divn > DIVN_MAX)) { 1968f6559227SYann Gautier continue; 1969f6559227SYann Gautier } 1970f6559227SYann Gautier 1971f6559227SYann Gautier frac = ((freq * FRAC_MAX) / input_freq) - ((divn + 1U) * FRAC_MAX); 1972f6559227SYann Gautier 1973f6559227SYann Gautier /* 2 loops to refine the fractional part */ 1974f6559227SYann Gautier for (i = 2U; i != 0U; i--) { 1975f6559227SYann Gautier unsigned long long diff; 1976f6559227SYann Gautier unsigned long long vco; 1977f6559227SYann Gautier 1978f6559227SYann Gautier if (frac > FRAC_MAX) { 1979f6559227SYann Gautier break; 1980f6559227SYann Gautier } 1981f6559227SYann Gautier 1982f6559227SYann Gautier vco = (post_divm * (divn + 1U)) + ((post_divm * frac) / FRAC_MAX); 1983f6559227SYann Gautier 1984f6559227SYann Gautier if ((vco < (VCO_MIN / 2U)) || (vco > (VCO_MAX / 2U))) { 1985f6559227SYann Gautier frac++; 1986f6559227SYann Gautier continue; 1987f6559227SYann Gautier } 1988f6559227SYann Gautier 1989f6559227SYann Gautier freq = vco / (divp + 1U); 1990f6559227SYann Gautier if (output_freq < freq) { 1991f6559227SYann Gautier diff = freq - output_freq; 1992f6559227SYann Gautier } else { 1993f6559227SYann Gautier diff = output_freq - freq; 1994f6559227SYann Gautier } 1995f6559227SYann Gautier 1996f6559227SYann Gautier if (diff < best_diff) { 1997f6559227SYann Gautier pllcfg[PLLCFG_M] = divm - 1U; 1998f6559227SYann Gautier pllcfg[PLLCFG_N] = (uint32_t)divn; 1999f6559227SYann Gautier pllcfg[PLLCFG_P] = divp; 2000f6559227SYann Gautier *fracv = (uint32_t)frac; 2001f6559227SYann Gautier 2002f6559227SYann Gautier if (diff == 0U) { 2003f6559227SYann Gautier return 0; 2004f6559227SYann Gautier } 2005f6559227SYann Gautier 2006f6559227SYann Gautier best_diff = diff; 2007f6559227SYann Gautier } 2008f6559227SYann Gautier 2009f6559227SYann Gautier frac++; 2010f6559227SYann Gautier } 2011f6559227SYann Gautier } 2012f6559227SYann Gautier } 2013f6559227SYann Gautier 2014f6559227SYann Gautier if (best_diff == ULLONG_MAX) { 2015f6559227SYann Gautier return -EINVAL; 2016f6559227SYann Gautier } 2017f6559227SYann Gautier 2018f6559227SYann Gautier return 0; 2019f6559227SYann Gautier } 2020f6559227SYann Gautier 2021f6559227SYann Gautier static int clk_get_pll1_settings(uint32_t clksrc, uint32_t freq_khz, 2022f6559227SYann Gautier uint32_t *pllcfg, uint32_t *fracv) 2023f6559227SYann Gautier { 2024f6559227SYann Gautier unsigned long input_freq = 0UL; 2025f6559227SYann Gautier 2026f6559227SYann Gautier assert(pllcfg != NULL); 2027f6559227SYann Gautier assert(fracv != NULL); 2028f6559227SYann Gautier 2029f6559227SYann Gautier switch (clksrc) { 2030f6559227SYann Gautier case CLK_PLL12_HSI: 2031f6559227SYann Gautier input_freq = stm32mp_clk_get_rate(CK_HSI); 2032f6559227SYann Gautier break; 2033f6559227SYann Gautier case CLK_PLL12_HSE: 2034f6559227SYann Gautier input_freq = stm32mp_clk_get_rate(CK_HSE); 2035f6559227SYann Gautier break; 2036f6559227SYann Gautier default: 2037f6559227SYann Gautier break; 2038f6559227SYann Gautier } 2039f6559227SYann Gautier 2040f6559227SYann Gautier if (input_freq == 0UL) { 2041f6559227SYann Gautier panic(); 2042f6559227SYann Gautier } 2043f6559227SYann Gautier 2044f6559227SYann Gautier return clk_compute_pll1_settings(input_freq, freq_khz, pllcfg, fracv); 2045f6559227SYann Gautier } 2046f6559227SYann Gautier 2047*ae1e5037SGabriel Fernandez static int stm32_clk_dividers_configure(struct stm32_clk_priv *priv) 20487839a050SYann Gautier { 2049*ae1e5037SGabriel Fernandez struct stm32_clk_platdata *pdata = priv->pdata; 2050*ae1e5037SGabriel Fernandez uint32_t i; 205152a616b4SAndre Przywara 2052*ae1e5037SGabriel Fernandez for (i = 0U; i < pdata->nclkdiv; i++) { 2053*ae1e5037SGabriel Fernandez uint32_t div_id, div_n; 2054*ae1e5037SGabriel Fernandez uint32_t val; 2055*ae1e5037SGabriel Fernandez int ret; 2056*ae1e5037SGabriel Fernandez 2057*ae1e5037SGabriel Fernandez val = pdata->clkdiv[i] & CMD_DATA_MASK; 2058*ae1e5037SGabriel Fernandez div_id = (val & DIV_ID_MASK) >> DIV_ID_SHIFT; 2059*ae1e5037SGabriel Fernandez div_n = (val & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; 2060*ae1e5037SGabriel Fernandez 2061*ae1e5037SGabriel Fernandez ret = clk_stm32_set_div(priv, div_id, div_n); 2062*ae1e5037SGabriel Fernandez if (ret != 0) { 2063*ae1e5037SGabriel Fernandez return ret; 2064*ae1e5037SGabriel Fernandez } 206552a616b4SAndre Przywara } 20667839a050SYann Gautier 2067*ae1e5037SGabriel Fernandez return 0; 20687839a050SYann Gautier } 20697839a050SYann Gautier 2070*ae1e5037SGabriel Fernandez static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data) 2071*ae1e5037SGabriel Fernandez { 2072*ae1e5037SGabriel Fernandez uint32_t sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT; 2073*ae1e5037SGabriel Fernandez uint32_t enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT; 2074*ae1e5037SGabriel Fernandez unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT; 2075*ae1e5037SGabriel Fernandez 2076*ae1e5037SGabriel Fernandez if (binding_id == RTC) { 2077*ae1e5037SGabriel Fernandez uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; 2078*ae1e5037SGabriel Fernandez 2079*ae1e5037SGabriel Fernandez if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || (enable != 0U)) { 2080*ae1e5037SGabriel Fernandez mmio_clrsetbits_32(address, RCC_BDCR_RTCSRC_MASK, 2081*ae1e5037SGabriel Fernandez (sel & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); 2082*ae1e5037SGabriel Fernandez 2083*ae1e5037SGabriel Fernandez mmio_setbits_32(address, RCC_BDCR_RTCCKEN); 2084*ae1e5037SGabriel Fernandez } 20857839a050SYann Gautier } 20867839a050SYann Gautier 2087*ae1e5037SGabriel Fernandez return 0; 2088*ae1e5037SGabriel Fernandez } 20897839a050SYann Gautier 2090*ae1e5037SGabriel Fernandez static int stm32_clk_configure_by_addr_val(struct stm32_clk_priv *priv, 2091*ae1e5037SGabriel Fernandez uint32_t data) 2092*ae1e5037SGabriel Fernandez { 2093*ae1e5037SGabriel Fernandez uint32_t addr = data >> CLK_ADDR_SHIFT; 2094*ae1e5037SGabriel Fernandez uint32_t val = data & CLK_ADDR_VAL_MASK; 20957839a050SYann Gautier 2096*ae1e5037SGabriel Fernandez mmio_setbits_32(priv->base + addr, val); 2097*ae1e5037SGabriel Fernandez 2098*ae1e5037SGabriel Fernandez return 0; 2099*ae1e5037SGabriel Fernandez } 2100*ae1e5037SGabriel Fernandez 2101*ae1e5037SGabriel Fernandez static int stm32_clk_source_configure(struct stm32_clk_priv *priv) 2102*ae1e5037SGabriel Fernandez { 2103*ae1e5037SGabriel Fernandez struct stm32_clk_platdata *pdata = priv->pdata; 2104*ae1e5037SGabriel Fernandez bool ckper_disabled = false; 2105*ae1e5037SGabriel Fernandez uint32_t i; 2106*ae1e5037SGabriel Fernandez 2107*ae1e5037SGabriel Fernandez for (i = 0U; i < pdata->nclksrc; i++) { 2108*ae1e5037SGabriel Fernandez uint32_t val = pdata->clksrc[i]; 2109*ae1e5037SGabriel Fernandez uint32_t cmd, cmd_data; 2110*ae1e5037SGabriel Fernandez int ret; 2111*ae1e5037SGabriel Fernandez 2112*ae1e5037SGabriel Fernandez if (val & CMD_ADDR_BIT) { 2113*ae1e5037SGabriel Fernandez ret = stm32_clk_configure_by_addr_val(priv, val & ~CMD_ADDR_BIT); 2114964e5ff1SNicolas Le Bayon if (ret != 0) { 2115964e5ff1SNicolas Le Bayon return ret; 21167839a050SYann Gautier } 2117f6559227SYann Gautier 2118f6559227SYann Gautier continue; 2119f6559227SYann Gautier } 2120f6559227SYann Gautier 2121*ae1e5037SGabriel Fernandez if (val == (uint32_t)CLK_CKPER_DISABLED) { 2122*ae1e5037SGabriel Fernandez ckper_disabled = true; 2123*ae1e5037SGabriel Fernandez continue; 2124*ae1e5037SGabriel Fernandez } 2125*ae1e5037SGabriel Fernandez 2126*ae1e5037SGabriel Fernandez cmd = (val & CMD_MASK) >> CMD_SHIFT; 2127*ae1e5037SGabriel Fernandez cmd_data = val & ~CMD_MASK; 2128*ae1e5037SGabriel Fernandez 2129*ae1e5037SGabriel Fernandez switch (cmd) { 2130*ae1e5037SGabriel Fernandez case CMD_MUX: 2131*ae1e5037SGabriel Fernandez ret = stm32_clk_configure_mux(priv, cmd_data); 2132*ae1e5037SGabriel Fernandez break; 2133*ae1e5037SGabriel Fernandez 2134*ae1e5037SGabriel Fernandez case CMD_CLK: 2135*ae1e5037SGabriel Fernandez ret = stm32_clk_configure_clk(priv, cmd_data); 2136*ae1e5037SGabriel Fernandez break; 2137*ae1e5037SGabriel Fernandez default: 2138*ae1e5037SGabriel Fernandez ret = -EINVAL; 2139*ae1e5037SGabriel Fernandez break; 2140*ae1e5037SGabriel Fernandez } 2141*ae1e5037SGabriel Fernandez 2142*ae1e5037SGabriel Fernandez if (ret != 0) { 2143*ae1e5037SGabriel Fernandez return ret; 2144*ae1e5037SGabriel Fernandez } 2145*ae1e5037SGabriel Fernandez } 2146*ae1e5037SGabriel Fernandez 2147*ae1e5037SGabriel Fernandez /* 2148*ae1e5037SGabriel Fernandez * CKPER is source for some peripheral clocks 2149*ae1e5037SGabriel Fernandez * (FMC-NAND / QPSI-NOR) and switching source is allowed 2150*ae1e5037SGabriel Fernandez * only if previous clock is still ON 2151*ae1e5037SGabriel Fernandez * => deactivate CKPER only after switching clock 2152*ae1e5037SGabriel Fernandez */ 2153*ae1e5037SGabriel Fernandez if (!ckper_disabled) { 2154*ae1e5037SGabriel Fernandez return 0; 2155*ae1e5037SGabriel Fernandez } 2156*ae1e5037SGabriel Fernandez 2157*ae1e5037SGabriel Fernandez return stm32_clk_configure_mux(priv, CLK_CKPER_DISABLED); 2158*ae1e5037SGabriel Fernandez } 2159*ae1e5037SGabriel Fernandez 2160*ae1e5037SGabriel Fernandez static int stm32mp1_pll_configure_src(struct stm32_clk_priv *priv, int pll_idx) 2161*ae1e5037SGabriel Fernandez { 2162*ae1e5037SGabriel Fernandez struct stm32_clk_platdata *pdata = priv->pdata; 2163*ae1e5037SGabriel Fernandez struct stm32_pll_dt_cfg *pll_conf = &pdata->pll[pll_idx]; 2164*ae1e5037SGabriel Fernandez 2165*ae1e5037SGabriel Fernandez if (!pll_conf->status) { 2166*ae1e5037SGabriel Fernandez return 0; 2167*ae1e5037SGabriel Fernandez } 2168*ae1e5037SGabriel Fernandez 2169*ae1e5037SGabriel Fernandez return stm32_clk_configure_mux(priv, pll_conf->src); 2170*ae1e5037SGabriel Fernandez } 2171*ae1e5037SGabriel Fernandez 2172*ae1e5037SGabriel Fernandez int stm32mp1_clk_init(void) 2173*ae1e5037SGabriel Fernandez { 2174*ae1e5037SGabriel Fernandez struct stm32_clk_priv *priv = clk_stm32_get_priv(); 2175*ae1e5037SGabriel Fernandez struct stm32_clk_platdata *pdata = priv->pdata; 2176*ae1e5037SGabriel Fernandez struct stm32_pll_dt_cfg *pll_conf = pdata->pll; 2177*ae1e5037SGabriel Fernandez int ret; 2178*ae1e5037SGabriel Fernandez enum stm32mp1_pll_id i; 2179*ae1e5037SGabriel Fernandez bool lse_css = false; 2180*ae1e5037SGabriel Fernandez bool pll3_preserve = false; 2181*ae1e5037SGabriel Fernandez bool pll4_preserve = false; 2182*ae1e5037SGabriel Fernandez bool pll4_bootrom = false; 2183*ae1e5037SGabriel Fernandez int stgen_p = stm32mp1_clk_get_parent(STGEN_K); 2184*ae1e5037SGabriel Fernandez int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K); 2185*ae1e5037SGabriel Fernandez uint32_t usbreg_bootrom = 0U; 2186*ae1e5037SGabriel Fernandez 2187*ae1e5037SGabriel Fernandez if (!pll_conf[_PLL1].status) { 2188*ae1e5037SGabriel Fernandez ret = clk_get_pll1_settings(pll_conf[_PLL2].src, PLL1_NOMINAL_FREQ_IN_KHZ, 2189*ae1e5037SGabriel Fernandez pll_conf[_PLL1].cfg, &pll_conf[_PLL1].frac); 2190f6559227SYann Gautier if (ret != 0) { 2191f6559227SYann Gautier return ret; 2192f6559227SYann Gautier } 2193f6559227SYann Gautier 2194*ae1e5037SGabriel Fernandez pll_conf[_PLL1].status = true; 2195*ae1e5037SGabriel Fernandez pll_conf[_PLL1].src = pll_conf[_PLL2].src; 2196f6559227SYann Gautier } 21977839a050SYann Gautier 21987839a050SYann Gautier /* 21997839a050SYann Gautier * Switch ON oscillator found in device-tree. 22007839a050SYann Gautier * Note: HSI already ON after BootROM stage. 22017839a050SYann Gautier */ 22020d21680cSYann Gautier if (stm32mp1_osc[_LSI] != 0U) { 22030d21680cSYann Gautier stm32mp1_lsi_set(true); 22047839a050SYann Gautier } 22050d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 2206b208e3daSGabriel Fernandez const char *name = stm32mp_osc_node_label[_LSE]; 22070d21680cSYann Gautier bool bypass, digbyp; 22087839a050SYann Gautier uint32_t lsedrv; 22097839a050SYann Gautier 2210b208e3daSGabriel Fernandez bypass = fdt_clk_read_bool(name, "st,bypass"); 2211b208e3daSGabriel Fernandez digbyp = fdt_clk_read_bool(name, "st,digbypass"); 2212b208e3daSGabriel Fernandez lse_css = fdt_clk_read_bool(name, "st,css"); 2213b208e3daSGabriel Fernandez lsedrv = fdt_clk_read_uint32_default(name, "st,drive", 22147839a050SYann Gautier LSEDRV_MEDIUM_HIGH); 22150d21680cSYann Gautier stm32mp1_lse_enable(bypass, digbyp, lsedrv); 22167839a050SYann Gautier } 22170d21680cSYann Gautier if (stm32mp1_osc[_HSE] != 0U) { 2218b208e3daSGabriel Fernandez const char *name = stm32mp_osc_node_label[_HSE]; 22190d21680cSYann Gautier bool bypass, digbyp, css; 22207839a050SYann Gautier 2221b208e3daSGabriel Fernandez bypass = fdt_clk_read_bool(name, "st,bypass"); 2222b208e3daSGabriel Fernandez digbyp = fdt_clk_read_bool(name, "st,digbypass"); 2223b208e3daSGabriel Fernandez css = fdt_clk_read_bool(name, "st,css"); 22240d21680cSYann Gautier stm32mp1_hse_enable(bypass, digbyp, css); 22257839a050SYann Gautier } 22267839a050SYann Gautier /* 22277839a050SYann Gautier * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) 22287839a050SYann Gautier * => switch on CSI even if node is not present in device tree 22297839a050SYann Gautier */ 22300d21680cSYann Gautier stm32mp1_csi_set(true); 22317839a050SYann Gautier 22327839a050SYann Gautier /* Come back to HSI */ 2233*ae1e5037SGabriel Fernandez ret = stm32_clk_configure_mux(priv, CLK_MPU_HSI); 22347839a050SYann Gautier if (ret != 0) { 22357839a050SYann Gautier return ret; 22367839a050SYann Gautier } 2237*ae1e5037SGabriel Fernandez ret = stm32_clk_configure_mux(priv, CLK_AXI_HSI); 22387839a050SYann Gautier if (ret != 0) { 22397839a050SYann Gautier return ret; 22407839a050SYann Gautier } 2241*ae1e5037SGabriel Fernandez ret = stm32_clk_configure_mux(priv, CLK_MCU_HSI); 2242b053a22eSYann Gautier if (ret != 0) { 2243b053a22eSYann Gautier return ret; 2244b053a22eSYann Gautier } 2245*ae1e5037SGabriel Fernandez if ((mmio_read_32(priv->base + RCC_MP_RSTSCLRR) & 22460d21680cSYann Gautier RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { 2247*ae1e5037SGabriel Fernandez pll3_preserve = stm32mp1_check_pll_conf(_PLL3, 2248*ae1e5037SGabriel Fernandez pll_conf[_PLL3].src, 2249*ae1e5037SGabriel Fernandez pll_conf[_PLL3].cfg, 2250*ae1e5037SGabriel Fernandez pll_conf[_PLL3].frac); 2251*ae1e5037SGabriel Fernandez pll4_preserve = stm32mp1_check_pll_conf(_PLL4, 2252*ae1e5037SGabriel Fernandez pll_conf[_PLL4].src, 2253*ae1e5037SGabriel Fernandez pll_conf[_PLL4].cfg, 2254*ae1e5037SGabriel Fernandez pll_conf[_PLL4].frac); 2255175758b2SYann Gautier } 2256bf1af154SPatrick Delaunay /* Don't initialize PLL4, when used by BOOTROM */ 2257bf1af154SPatrick Delaunay if ((stm32mp_get_boot_itf_selected() == 2258bf1af154SPatrick Delaunay BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && 2259bf1af154SPatrick Delaunay ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { 2260bf1af154SPatrick Delaunay pll4_bootrom = true; 2261bf1af154SPatrick Delaunay pll4_preserve = true; 2262bf1af154SPatrick Delaunay } 22630d21680cSYann Gautier 22647839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 22650d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 22660d21680cSYann Gautier ((i == _PLL4) && pll4_preserve)) { 22677839a050SYann Gautier continue; 22680d21680cSYann Gautier } 22690d21680cSYann Gautier 22700d21680cSYann Gautier ret = stm32mp1_pll_stop(i); 22717839a050SYann Gautier if (ret != 0) { 22727839a050SYann Gautier return ret; 22737839a050SYann Gautier } 22747839a050SYann Gautier } 22757839a050SYann Gautier 22767839a050SYann Gautier /* Configure HSIDIV */ 22770d21680cSYann Gautier if (stm32mp1_osc[_HSI] != 0U) { 22780d21680cSYann Gautier ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); 22797839a050SYann Gautier if (ret != 0) { 22807839a050SYann Gautier return ret; 22817839a050SYann Gautier } 2282591d80c8SLionel Debieve 2283591d80c8SLionel Debieve stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); 22847839a050SYann Gautier } 22857839a050SYann Gautier 2286*ae1e5037SGabriel Fernandez /* Configure dividers */ 2287*ae1e5037SGabriel Fernandez ret = stm32_clk_dividers_configure(priv); 22887839a050SYann Gautier if (ret != 0) { 22897839a050SYann Gautier return ret; 22907839a050SYann Gautier } 22917839a050SYann Gautier 22927839a050SYann Gautier /* Configure PLLs source */ 2293*ae1e5037SGabriel Fernandez ret = stm32mp1_pll_configure_src(priv, _PLL1); 22947839a050SYann Gautier if (ret != 0) { 22957839a050SYann Gautier return ret; 22967839a050SYann Gautier } 22977839a050SYann Gautier 22980d21680cSYann Gautier if (!pll3_preserve) { 2299*ae1e5037SGabriel Fernandez ret = stm32mp1_pll_configure_src(priv, _PLL3); 23007839a050SYann Gautier if (ret != 0) { 23017839a050SYann Gautier return ret; 23027839a050SYann Gautier } 23030d21680cSYann Gautier } 23040d21680cSYann Gautier 23050d21680cSYann Gautier if (!pll4_preserve) { 2306*ae1e5037SGabriel Fernandez ret = stm32mp1_pll_configure_src(priv, _PLL4); 23070d21680cSYann Gautier if (ret != 0) { 23080d21680cSYann Gautier return ret; 23090d21680cSYann Gautier } 23100d21680cSYann Gautier } 23117839a050SYann Gautier 23127839a050SYann Gautier /* Configure and start PLLs */ 23137839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 23140d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 23150d21680cSYann Gautier ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { 23160d21680cSYann Gautier continue; 23170d21680cSYann Gautier } 23180d21680cSYann Gautier 2319*ae1e5037SGabriel Fernandez if (!pll_conf[i].status) { 23207839a050SYann Gautier continue; 23217839a050SYann Gautier } 23227839a050SYann Gautier 23230d21680cSYann Gautier if ((i == _PLL4) && pll4_bootrom) { 23240d21680cSYann Gautier /* Set output divider if not done by the Bootrom */ 2325*ae1e5037SGabriel Fernandez stm32mp1_pll_config_output(i, pll_conf[i].cfg); 23260d21680cSYann Gautier continue; 23270d21680cSYann Gautier } 23280d21680cSYann Gautier 2329*ae1e5037SGabriel Fernandez ret = stm32mp1_pll_config(i, pll_conf[i].cfg, pll_conf[i].frac); 23307839a050SYann Gautier if (ret != 0) { 23317839a050SYann Gautier return ret; 23327839a050SYann Gautier } 2333964e5ff1SNicolas Le Bayon 2334*ae1e5037SGabriel Fernandez if (pll_conf[i].csg_enabled) { 2335*ae1e5037SGabriel Fernandez stm32mp1_pll_csg(i, pll_conf[i].csg); 23367839a050SYann Gautier } 23377839a050SYann Gautier 23380d21680cSYann Gautier stm32mp1_pll_start(i); 23397839a050SYann Gautier } 23401b491eeaSElyes Haouas /* Wait and start PLLs output when ready */ 23417839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 2342*ae1e5037SGabriel Fernandez if (!pll_conf[i].status) { 23437839a050SYann Gautier continue; 23447839a050SYann Gautier } 23457839a050SYann Gautier 2346*ae1e5037SGabriel Fernandez ret = stm32mp1_pll_output(i, pll_conf[i].cfg[PLLCFG_O]); 23477839a050SYann Gautier if (ret != 0) { 23487839a050SYann Gautier return ret; 23497839a050SYann Gautier } 23507839a050SYann Gautier } 23517839a050SYann Gautier /* Wait LSE ready before to use it */ 23520d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 23530d21680cSYann Gautier stm32mp1_lse_wait(); 23547839a050SYann Gautier } 23557839a050SYann Gautier 2356bf1af154SPatrick Delaunay if (pll4_bootrom) { 2357*ae1e5037SGabriel Fernandez usbreg_bootrom = mmio_read_32(priv->base + RCC_USBCKSELR); 2358bf1af154SPatrick Delaunay } 23597839a050SYann Gautier 2360*ae1e5037SGabriel Fernandez /* Configure with expected clock source */ 2361*ae1e5037SGabriel Fernandez ret = stm32_clk_source_configure(priv); 2362*ae1e5037SGabriel Fernandez if (ret != 0) { 2363*ae1e5037SGabriel Fernandez panic(); 23647839a050SYann Gautier } 2365bf1af154SPatrick Delaunay 2366bf1af154SPatrick Delaunay if (pll4_bootrom) { 2367bf1af154SPatrick Delaunay uint32_t usbreg_value, usbreg_mask; 2368bf1af154SPatrick Delaunay const struct stm32mp1_clk_sel *sel; 2369bf1af154SPatrick Delaunay 2370bf1af154SPatrick Delaunay sel = clk_sel_ref(_USBPHY_SEL); 2371bf1af154SPatrick Delaunay usbreg_mask = (uint32_t)sel->msk << sel->src; 2372bf1af154SPatrick Delaunay sel = clk_sel_ref(_USBO_SEL); 2373bf1af154SPatrick Delaunay usbreg_mask |= (uint32_t)sel->msk << sel->src; 2374bf1af154SPatrick Delaunay 2375*ae1e5037SGabriel Fernandez usbreg_value = mmio_read_32(priv->base + RCC_USBCKSELR) & 2376bf1af154SPatrick Delaunay usbreg_mask; 2377bf1af154SPatrick Delaunay usbreg_bootrom &= usbreg_mask; 2378bf1af154SPatrick Delaunay if (usbreg_bootrom != usbreg_value) { 2379bf1af154SPatrick Delaunay VERBOSE("forbidden new USB clk path\n"); 2380bf1af154SPatrick Delaunay VERBOSE("vs bootrom on USB boot\n"); 2381bf1af154SPatrick Delaunay return -FDT_ERR_BADVALUE; 2382bf1af154SPatrick Delaunay } 2383bf1af154SPatrick Delaunay } 2384*ae1e5037SGabriel Fernandez 2385*ae1e5037SGabriel Fernandez if (lse_css) { 2386*ae1e5037SGabriel Fernandez mmio_setbits_32(priv->base + RCC_BDCR, RCC_BDCR_LSECSSON); 23877839a050SYann Gautier } 23887839a050SYann Gautier 23897839a050SYann Gautier /* Switch OFF HSI if not found in device-tree */ 23900d21680cSYann Gautier if (stm32mp1_osc[_HSI] == 0U) { 23910d21680cSYann Gautier stm32mp1_hsi_set(false); 23927839a050SYann Gautier } 2393591d80c8SLionel Debieve 2394591d80c8SLionel Debieve stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); 23957839a050SYann Gautier 23967839a050SYann Gautier /* Software Self-Refresh mode (SSR) during DDR initilialization */ 2397*ae1e5037SGabriel Fernandez mmio_clrsetbits_32(priv->base + RCC_DDRITFCR, 23987839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_MASK, 23997839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SSR << 24007839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SHIFT); 24017839a050SYann Gautier 24027839a050SYann Gautier return 0; 24037839a050SYann Gautier } 24047839a050SYann Gautier 24057839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name, 24067839a050SYann Gautier enum stm32mp_osc_id index) 24077839a050SYann Gautier { 24087839a050SYann Gautier uint32_t frequency; 24097839a050SYann Gautier 24100d21680cSYann Gautier if (fdt_osc_read_freq(name, &frequency) == 0) { 24110d21680cSYann Gautier stm32mp1_osc[index] = frequency; 24127839a050SYann Gautier } 24137839a050SYann Gautier } 24147839a050SYann Gautier 24157839a050SYann Gautier static void stm32mp1_osc_init(void) 24167839a050SYann Gautier { 24177839a050SYann Gautier enum stm32mp_osc_id i; 24187839a050SYann Gautier 24197839a050SYann Gautier for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { 24200d21680cSYann Gautier stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); 24217839a050SYann Gautier } 24227839a050SYann Gautier } 24237839a050SYann Gautier 242437e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES 242537e8295aSEtienne Carriere /* 242637e8295aSEtienne Carriere * Get the parent ID of the target parent clock, for tagging as secure 242737e8295aSEtienne Carriere * shared clock dependencies. 242837e8295aSEtienne Carriere */ 242937e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id) 243037e8295aSEtienne Carriere { 243137e8295aSEtienne Carriere enum stm32mp1_parent_sel s = _UNKNOWN_SEL; 243237e8295aSEtienne Carriere enum stm32mp1_pll_id pll_id; 243337e8295aSEtienne Carriere uint32_t p_sel; 243437e8295aSEtienne Carriere uintptr_t rcc_base = stm32mp_rcc_base(); 243537e8295aSEtienne Carriere 243637e8295aSEtienne Carriere switch (parent_id) { 243737e8295aSEtienne Carriere case _ACLK: 243837e8295aSEtienne Carriere case _PCLK4: 243937e8295aSEtienne Carriere case _PCLK5: 244037e8295aSEtienne Carriere s = _AXIS_SEL; 244137e8295aSEtienne Carriere break; 244237e8295aSEtienne Carriere case _PLL1_P: 244337e8295aSEtienne Carriere case _PLL1_Q: 244437e8295aSEtienne Carriere case _PLL1_R: 244537e8295aSEtienne Carriere pll_id = _PLL1; 244637e8295aSEtienne Carriere break; 244737e8295aSEtienne Carriere case _PLL2_P: 244837e8295aSEtienne Carriere case _PLL2_Q: 244937e8295aSEtienne Carriere case _PLL2_R: 245037e8295aSEtienne Carriere pll_id = _PLL2; 245137e8295aSEtienne Carriere break; 245237e8295aSEtienne Carriere case _PLL3_P: 245337e8295aSEtienne Carriere case _PLL3_Q: 245437e8295aSEtienne Carriere case _PLL3_R: 245537e8295aSEtienne Carriere pll_id = _PLL3; 245637e8295aSEtienne Carriere break; 245737e8295aSEtienne Carriere case _PLL4_P: 245837e8295aSEtienne Carriere case _PLL4_Q: 245937e8295aSEtienne Carriere case _PLL4_R: 246037e8295aSEtienne Carriere pll_id = _PLL4; 246137e8295aSEtienne Carriere break; 246237e8295aSEtienne Carriere case _PCLK1: 246337e8295aSEtienne Carriere case _PCLK2: 246437e8295aSEtienne Carriere case _HCLK2: 246537e8295aSEtienne Carriere case _HCLK6: 246637e8295aSEtienne Carriere case _CK_PER: 246737e8295aSEtienne Carriere case _CK_MPU: 246837e8295aSEtienne Carriere case _CK_MCU: 246937e8295aSEtienne Carriere case _USB_PHY_48: 247037e8295aSEtienne Carriere /* We do not expect to access these */ 247137e8295aSEtienne Carriere panic(); 247237e8295aSEtienne Carriere break; 247337e8295aSEtienne Carriere default: 247437e8295aSEtienne Carriere /* Other parents have no parent */ 247537e8295aSEtienne Carriere return -1; 247637e8295aSEtienne Carriere } 247737e8295aSEtienne Carriere 247837e8295aSEtienne Carriere if (s != _UNKNOWN_SEL) { 247937e8295aSEtienne Carriere const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); 248037e8295aSEtienne Carriere 248137e8295aSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & 248237e8295aSEtienne Carriere sel->msk; 248337e8295aSEtienne Carriere 248437e8295aSEtienne Carriere if (p_sel < sel->nb_parent) { 248537e8295aSEtienne Carriere return (int)sel->parent[p_sel]; 248637e8295aSEtienne Carriere } 248737e8295aSEtienne Carriere } else { 248837e8295aSEtienne Carriere const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 248937e8295aSEtienne Carriere 249037e8295aSEtienne Carriere p_sel = mmio_read_32(rcc_base + pll->rckxselr) & 249137e8295aSEtienne Carriere RCC_SELR_REFCLK_SRC_MASK; 249237e8295aSEtienne Carriere 249337e8295aSEtienne Carriere if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { 249437e8295aSEtienne Carriere return (int)pll->refclk[p_sel]; 249537e8295aSEtienne Carriere } 249637e8295aSEtienne Carriere } 249737e8295aSEtienne Carriere 249837e8295aSEtienne Carriere VERBOSE("No parent selected for %s\n", 249937e8295aSEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 250037e8295aSEtienne Carriere 250137e8295aSEtienne Carriere return -1; 250237e8295aSEtienne Carriere } 250337e8295aSEtienne Carriere 250437e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id) 250537e8295aSEtienne Carriere { 250637e8295aSEtienne Carriere int grandparent_id; 250737e8295aSEtienne Carriere 250837e8295aSEtienne Carriere switch (parent_id) { 250937e8295aSEtienne Carriere case _PLL3_P: 251037e8295aSEtienne Carriere case _PLL3_Q: 251137e8295aSEtienne Carriere case _PLL3_R: 251237e8295aSEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 251337e8295aSEtienne Carriere break; 251437e8295aSEtienne Carriere 251537e8295aSEtienne Carriere /* These clocks are always secure when RCC is secure */ 251637e8295aSEtienne Carriere case _ACLK: 251737e8295aSEtienne Carriere case _HCLK2: 251837e8295aSEtienne Carriere case _HCLK6: 251937e8295aSEtienne Carriere case _PCLK4: 252037e8295aSEtienne Carriere case _PCLK5: 252137e8295aSEtienne Carriere case _PLL1_P: 252237e8295aSEtienne Carriere case _PLL1_Q: 252337e8295aSEtienne Carriere case _PLL1_R: 252437e8295aSEtienne Carriere case _PLL2_P: 252537e8295aSEtienne Carriere case _PLL2_Q: 252637e8295aSEtienne Carriere case _PLL2_R: 252737e8295aSEtienne Carriere case _HSI: 252837e8295aSEtienne Carriere case _HSI_KER: 252937e8295aSEtienne Carriere case _LSI: 253037e8295aSEtienne Carriere case _CSI: 253137e8295aSEtienne Carriere case _CSI_KER: 253237e8295aSEtienne Carriere case _HSE: 253337e8295aSEtienne Carriere case _HSE_KER: 253437e8295aSEtienne Carriere case _HSE_KER_DIV2: 2535cbd2e8a6SGabriel Fernandez case _HSE_RTC: 253637e8295aSEtienne Carriere case _LSE: 253737e8295aSEtienne Carriere break; 253837e8295aSEtienne Carriere 253937e8295aSEtienne Carriere default: 254037e8295aSEtienne Carriere VERBOSE("Cannot secure parent clock %s\n", 254137e8295aSEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 254237e8295aSEtienne Carriere panic(); 254337e8295aSEtienne Carriere } 254437e8295aSEtienne Carriere 254537e8295aSEtienne Carriere grandparent_id = get_parent_id_parent(parent_id); 254637e8295aSEtienne Carriere if (grandparent_id >= 0) { 254737e8295aSEtienne Carriere secure_parent_clocks(grandparent_id); 254837e8295aSEtienne Carriere } 254937e8295aSEtienne Carriere } 255037e8295aSEtienne Carriere 255137e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id) 255237e8295aSEtienne Carriere { 255337e8295aSEtienne Carriere int parent_id; 255437e8295aSEtienne Carriere 255537e8295aSEtienne Carriere if (!stm32mp1_rcc_is_secure()) { 255637e8295aSEtienne Carriere return; 255737e8295aSEtienne Carriere } 255837e8295aSEtienne Carriere 255937e8295aSEtienne Carriere switch (clock_id) { 256037e8295aSEtienne Carriere case PLL1: 256137e8295aSEtienne Carriere case PLL2: 256237e8295aSEtienne Carriere /* PLL1/PLL2 are always secure: nothing to do */ 256337e8295aSEtienne Carriere break; 256437e8295aSEtienne Carriere case PLL3: 256537e8295aSEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 256637e8295aSEtienne Carriere break; 256737e8295aSEtienne Carriere case PLL4: 256837e8295aSEtienne Carriere ERROR("PLL4 cannot be secured\n"); 256937e8295aSEtienne Carriere panic(); 257037e8295aSEtienne Carriere break; 257137e8295aSEtienne Carriere default: 257237e8295aSEtienne Carriere /* Others are expected gateable clock */ 257337e8295aSEtienne Carriere parent_id = stm32mp1_clk_get_parent(clock_id); 257437e8295aSEtienne Carriere if (parent_id < 0) { 257537e8295aSEtienne Carriere INFO("No parent found for clock %lu\n", clock_id); 257637e8295aSEtienne Carriere } else { 257737e8295aSEtienne Carriere secure_parent_clocks(parent_id); 257837e8295aSEtienne Carriere } 257937e8295aSEtienne Carriere break; 258037e8295aSEtienne Carriere } 258137e8295aSEtienne Carriere } 258237e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */ 258337e8295aSEtienne Carriere 258477b4ca0bSLionel Debieve void stm32mp1_clk_mcuss_protect(bool enable) 258577b4ca0bSLionel Debieve { 258677b4ca0bSLionel Debieve uintptr_t rcc_base = stm32mp_rcc_base(); 258777b4ca0bSLionel Debieve 258877b4ca0bSLionel Debieve if (enable) { 258977b4ca0bSLionel Debieve mmio_setbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); 259077b4ca0bSLionel Debieve } else { 259177b4ca0bSLionel Debieve mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT); 259277b4ca0bSLionel Debieve } 259377b4ca0bSLionel Debieve } 259477b4ca0bSLionel Debieve 25956cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void) 25966cb45f89SYann Gautier { 2597033b6c3aSEtienne Carriere unsigned int idx; 2598033b6c3aSEtienne Carriere const unsigned long secure_enable[] = { 2599033b6c3aSEtienne Carriere AXIDCG, 2600033b6c3aSEtienne Carriere BSEC, 2601033b6c3aSEtienne Carriere DDRC1, DDRC1LP, 2602033b6c3aSEtienne Carriere DDRC2, DDRC2LP, 2603033b6c3aSEtienne Carriere DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, 2604033b6c3aSEtienne Carriere DDRPHYC, DDRPHYCLP, 2605373f06beSLionel Debieve RTCAPB, 2606033b6c3aSEtienne Carriere TZC1, TZC2, 2607033b6c3aSEtienne Carriere TZPC, 2608033b6c3aSEtienne Carriere STGEN_K, 2609033b6c3aSEtienne Carriere }; 2610033b6c3aSEtienne Carriere 2611033b6c3aSEtienne Carriere for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { 2612033b6c3aSEtienne Carriere stm32mp_clk_enable(secure_enable[idx]); 2613033b6c3aSEtienne Carriere } 26146cb45f89SYann Gautier } 26156cb45f89SYann Gautier 261633667d29SYann Gautier static const struct clk_ops stm32mp_clk_ops = { 261733667d29SYann Gautier .enable = stm32mp_clk_enable, 261833667d29SYann Gautier .disable = stm32mp_clk_disable, 261933667d29SYann Gautier .is_enabled = stm32mp_clk_is_enabled, 262033667d29SYann Gautier .get_rate = stm32mp_clk_get_rate, 262133667d29SYann Gautier .get_parent = stm32mp1_clk_get_parent, 262233667d29SYann Gautier }; 262333667d29SYann Gautier 2624*ae1e5037SGabriel Fernandez struct stm32_pll_dt_cfg mp15_pll[_PLL_NB]; 2625*ae1e5037SGabriel Fernandez uint32_t mp15_clksrc[MUX_NB]; 2626*ae1e5037SGabriel Fernandez uint32_t mp15_clkdiv[DIV_NB]; 2627*ae1e5037SGabriel Fernandez 2628*ae1e5037SGabriel Fernandez struct stm32_clk_platdata stm32mp15_clock_pdata = { 2629*ae1e5037SGabriel Fernandez .pll = mp15_pll, 2630*ae1e5037SGabriel Fernandez .npll = _PLL_NB, 2631*ae1e5037SGabriel Fernandez .clksrc = mp15_clksrc, 2632*ae1e5037SGabriel Fernandez .nclksrc = MUX_NB, 2633*ae1e5037SGabriel Fernandez .clkdiv = mp15_clkdiv, 2634*ae1e5037SGabriel Fernandez .nclkdiv = DIV_NB, 2635*ae1e5037SGabriel Fernandez }; 2636*ae1e5037SGabriel Fernandez 2637*ae1e5037SGabriel Fernandez static struct stm32_clk_priv stm32mp15_clock_data = { 2638*ae1e5037SGabriel Fernandez .base = RCC_BASE, 2639*ae1e5037SGabriel Fernandez .parents = parent_mp15, 2640*ae1e5037SGabriel Fernandez .nb_parents = ARRAY_SIZE(parent_mp15), 2641*ae1e5037SGabriel Fernandez .div = dividers_mp15, 2642*ae1e5037SGabriel Fernandez .nb_div = ARRAY_SIZE(dividers_mp15), 2643*ae1e5037SGabriel Fernandez .pdata = &stm32mp15_clock_pdata, 2644*ae1e5037SGabriel Fernandez }; 2645*ae1e5037SGabriel Fernandez 2646*ae1e5037SGabriel Fernandez static int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, 2647*ae1e5037SGabriel Fernandez uint32_t *tab, uint32_t *nb) 2648*ae1e5037SGabriel Fernandez { 2649*ae1e5037SGabriel Fernandez const fdt32_t *cell; 2650*ae1e5037SGabriel Fernandez int len = 0; 2651*ae1e5037SGabriel Fernandez uint32_t i; 2652*ae1e5037SGabriel Fernandez 2653*ae1e5037SGabriel Fernandez cell = fdt_getprop(fdt, node, name, &len); 2654*ae1e5037SGabriel Fernandez if (cell == NULL) { 2655*ae1e5037SGabriel Fernandez *nb = 0U; 2656*ae1e5037SGabriel Fernandez return 0; 2657*ae1e5037SGabriel Fernandez } 2658*ae1e5037SGabriel Fernandez 2659*ae1e5037SGabriel Fernandez for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { 2660*ae1e5037SGabriel Fernandez tab[i] = fdt32_to_cpu(cell[i]); 2661*ae1e5037SGabriel Fernandez } 2662*ae1e5037SGabriel Fernandez 2663*ae1e5037SGabriel Fernandez *nb = (uint32_t)len / sizeof(uint32_t); 2664*ae1e5037SGabriel Fernandez 2665*ae1e5037SGabriel Fernandez return 0; 2666*ae1e5037SGabriel Fernandez } 2667*ae1e5037SGabriel Fernandez 2668*ae1e5037SGabriel Fernandez #define RCC_PLL_NAME_SIZE 12 2669*ae1e5037SGabriel Fernandez 2670*ae1e5037SGabriel Fernandez static int clk_stm32_load_vco_config(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) 2671*ae1e5037SGabriel Fernandez { 2672*ae1e5037SGabriel Fernandez int err; 2673*ae1e5037SGabriel Fernandez 2674*ae1e5037SGabriel Fernandez err = fdt_read_uint32_array(fdt, subnode, "divmn", (int)PLL_DIV_MN_NB, &pll->cfg[PLLCFG_M]); 2675*ae1e5037SGabriel Fernandez if (err != 0) { 2676*ae1e5037SGabriel Fernandez return err; 2677*ae1e5037SGabriel Fernandez } 2678*ae1e5037SGabriel Fernandez 2679*ae1e5037SGabriel Fernandez err = fdt_read_uint32_array(fdt, subnode, "csg", (int)PLLCSG_NB, pll->csg); 2680*ae1e5037SGabriel Fernandez if (err == 0) { 2681*ae1e5037SGabriel Fernandez pll->csg_enabled = true; 2682*ae1e5037SGabriel Fernandez } else if (err == -FDT_ERR_NOTFOUND) { 2683*ae1e5037SGabriel Fernandez pll->csg_enabled = false; 2684*ae1e5037SGabriel Fernandez } else { 2685*ae1e5037SGabriel Fernandez return err; 2686*ae1e5037SGabriel Fernandez } 2687*ae1e5037SGabriel Fernandez 2688*ae1e5037SGabriel Fernandez pll->status = true; 2689*ae1e5037SGabriel Fernandez 2690*ae1e5037SGabriel Fernandez pll->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0); 2691*ae1e5037SGabriel Fernandez 2692*ae1e5037SGabriel Fernandez pll->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX); 2693*ae1e5037SGabriel Fernandez 2694*ae1e5037SGabriel Fernandez return 0; 2695*ae1e5037SGabriel Fernandez } 2696*ae1e5037SGabriel Fernandez 2697*ae1e5037SGabriel Fernandez static int clk_stm32_load_output_config(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) 2698*ae1e5037SGabriel Fernandez { 2699*ae1e5037SGabriel Fernandez int err; 2700*ae1e5037SGabriel Fernandez 2701*ae1e5037SGabriel Fernandez err = fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", (int)PLL_DIV_PQR_NB, 2702*ae1e5037SGabriel Fernandez &pll->cfg[PLLCFG_P]); 2703*ae1e5037SGabriel Fernandez if (err != 0) { 2704*ae1e5037SGabriel Fernandez return err; 2705*ae1e5037SGabriel Fernandez } 2706*ae1e5037SGabriel Fernandez 2707*ae1e5037SGabriel Fernandez pll->cfg[PLLCFG_O] = PQR(1, 1, 1); 2708*ae1e5037SGabriel Fernandez 2709*ae1e5037SGabriel Fernandez return 0; 2710*ae1e5037SGabriel Fernandez } 2711*ae1e5037SGabriel Fernandez 2712*ae1e5037SGabriel Fernandez static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) 2713*ae1e5037SGabriel Fernandez { 2714*ae1e5037SGabriel Fernandez const fdt32_t *cuint; 2715*ae1e5037SGabriel Fernandez int subnode_pll; 2716*ae1e5037SGabriel Fernandez int subnode_vco; 2717*ae1e5037SGabriel Fernandez int err; 2718*ae1e5037SGabriel Fernandez 2719*ae1e5037SGabriel Fernandez cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); 2720*ae1e5037SGabriel Fernandez if (cuint == NULL) { 2721*ae1e5037SGabriel Fernandez /* Case of no pll is defined */ 2722*ae1e5037SGabriel Fernandez return 0; 2723*ae1e5037SGabriel Fernandez } 2724*ae1e5037SGabriel Fernandez 2725*ae1e5037SGabriel Fernandez subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); 2726*ae1e5037SGabriel Fernandez if (subnode_pll < 0) { 2727*ae1e5037SGabriel Fernandez return -FDT_ERR_NOTFOUND; 2728*ae1e5037SGabriel Fernandez } 2729*ae1e5037SGabriel Fernandez 2730*ae1e5037SGabriel Fernandez cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL); 2731*ae1e5037SGabriel Fernandez if (cuint == NULL) { 2732*ae1e5037SGabriel Fernandez return -FDT_ERR_NOTFOUND; 2733*ae1e5037SGabriel Fernandez } 2734*ae1e5037SGabriel Fernandez 2735*ae1e5037SGabriel Fernandez subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); 2736*ae1e5037SGabriel Fernandez if (subnode_vco < 0) { 2737*ae1e5037SGabriel Fernandez return -FDT_ERR_NOTFOUND; 2738*ae1e5037SGabriel Fernandez } 2739*ae1e5037SGabriel Fernandez 2740*ae1e5037SGabriel Fernandez err = clk_stm32_load_vco_config(fdt, subnode_vco, pll); 2741*ae1e5037SGabriel Fernandez if (err != 0) { 2742*ae1e5037SGabriel Fernandez return err; 2743*ae1e5037SGabriel Fernandez } 2744*ae1e5037SGabriel Fernandez 2745*ae1e5037SGabriel Fernandez err = clk_stm32_load_output_config(fdt, subnode_pll, pll); 2746*ae1e5037SGabriel Fernandez if (err != 0) { 2747*ae1e5037SGabriel Fernandez return err; 2748*ae1e5037SGabriel Fernandez } 2749*ae1e5037SGabriel Fernandez 2750*ae1e5037SGabriel Fernandez return 0; 2751*ae1e5037SGabriel Fernandez } 2752*ae1e5037SGabriel Fernandez 2753*ae1e5037SGabriel Fernandez static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata) 2754*ae1e5037SGabriel Fernandez { 2755*ae1e5037SGabriel Fernandez size_t i = 0U; 2756*ae1e5037SGabriel Fernandez 2757*ae1e5037SGabriel Fernandez for (i = _PLL1; i < pdata->npll; i++) { 2758*ae1e5037SGabriel Fernandez struct stm32_pll_dt_cfg *pll = pdata->pll + i; 2759*ae1e5037SGabriel Fernandez char name[RCC_PLL_NAME_SIZE]; 2760*ae1e5037SGabriel Fernandez int subnode; 2761*ae1e5037SGabriel Fernandez int err; 2762*ae1e5037SGabriel Fernandez 2763*ae1e5037SGabriel Fernandez snprintf(name, sizeof(name), "st,pll@%u", i); 2764*ae1e5037SGabriel Fernandez 2765*ae1e5037SGabriel Fernandez subnode = fdt_subnode_offset(fdt, node, name); 2766*ae1e5037SGabriel Fernandez if (!fdt_check_node(subnode)) { 2767*ae1e5037SGabriel Fernandez continue; 2768*ae1e5037SGabriel Fernandez } 2769*ae1e5037SGabriel Fernandez 2770*ae1e5037SGabriel Fernandez err = clk_stm32_parse_pll_fdt(fdt, subnode, pll); 2771*ae1e5037SGabriel Fernandez if (err != 0) { 2772*ae1e5037SGabriel Fernandez panic(); 2773*ae1e5037SGabriel Fernandez } 2774*ae1e5037SGabriel Fernandez } 2775*ae1e5037SGabriel Fernandez 2776*ae1e5037SGabriel Fernandez return 0; 2777*ae1e5037SGabriel Fernandez } 2778*ae1e5037SGabriel Fernandez 2779*ae1e5037SGabriel Fernandez static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata) 2780*ae1e5037SGabriel Fernandez { 2781*ae1e5037SGabriel Fernandez void *fdt = NULL; 2782*ae1e5037SGabriel Fernandez int node; 2783*ae1e5037SGabriel Fernandez uint32_t err; 2784*ae1e5037SGabriel Fernandez 2785*ae1e5037SGabriel Fernandez if (fdt_get_address(&fdt) == 0) { 2786*ae1e5037SGabriel Fernandez return -ENOENT; 2787*ae1e5037SGabriel Fernandez } 2788*ae1e5037SGabriel Fernandez 2789*ae1e5037SGabriel Fernandez node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); 2790*ae1e5037SGabriel Fernandez if (node < 0) { 2791*ae1e5037SGabriel Fernandez panic(); 2792*ae1e5037SGabriel Fernandez } 2793*ae1e5037SGabriel Fernandez 2794*ae1e5037SGabriel Fernandez err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); 2795*ae1e5037SGabriel Fernandez if (err != 0) { 2796*ae1e5037SGabriel Fernandez return err; 2797*ae1e5037SGabriel Fernandez } 2798*ae1e5037SGabriel Fernandez 2799*ae1e5037SGabriel Fernandez err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, &pdata->nclkdiv); 2800*ae1e5037SGabriel Fernandez if (err != 0) { 2801*ae1e5037SGabriel Fernandez return err; 2802*ae1e5037SGabriel Fernandez } 2803*ae1e5037SGabriel Fernandez 2804*ae1e5037SGabriel Fernandez err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, &pdata->nclksrc); 2805*ae1e5037SGabriel Fernandez if (err != 0) { 2806*ae1e5037SGabriel Fernandez return err; 2807*ae1e5037SGabriel Fernandez } 2808*ae1e5037SGabriel Fernandez 2809*ae1e5037SGabriel Fernandez return 0; 2810*ae1e5037SGabriel Fernandez } 2811*ae1e5037SGabriel Fernandez 28127839a050SYann Gautier int stm32mp1_clk_probe(void) 28137839a050SYann Gautier { 2814*ae1e5037SGabriel Fernandez uintptr_t base = RCC_BASE; 2815*ae1e5037SGabriel Fernandez int ret; 2816*ae1e5037SGabriel Fernandez 2817812daf91SLionel Debieve #if defined(IMAGE_BL32) 2818812daf91SLionel Debieve if (!fdt_get_rcc_secure_state()) { 2819812daf91SLionel Debieve mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U); 2820812daf91SLionel Debieve } 2821812daf91SLionel Debieve #endif 2822812daf91SLionel Debieve 28237839a050SYann Gautier stm32mp1_osc_init(); 28247839a050SYann Gautier 2825*ae1e5037SGabriel Fernandez ret = stm32_clk_parse_fdt(&stm32mp15_clock_pdata); 2826*ae1e5037SGabriel Fernandez if (ret != 0) { 2827*ae1e5037SGabriel Fernandez return ret; 2828*ae1e5037SGabriel Fernandez } 2829*ae1e5037SGabriel Fernandez 2830*ae1e5037SGabriel Fernandez ret = clk_stm32_init(&stm32mp15_clock_data, base); 2831*ae1e5037SGabriel Fernandez if (ret != 0) { 2832*ae1e5037SGabriel Fernandez return ret; 2833*ae1e5037SGabriel Fernandez } 2834*ae1e5037SGabriel Fernandez 28356cb45f89SYann Gautier sync_earlyboot_clocks_state(); 28366cb45f89SYann Gautier 283733667d29SYann Gautier clk_register(&stm32mp_clk_ops); 283833667d29SYann Gautier 28397839a050SYann Gautier return 0; 28407839a050SYann Gautier } 2841