17839a050SYann Gautier /* 2*8f97c4faSYann Gautier * Copyright (C) 2018-2021, 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 <libfdt.h> 1309d40e0eSAntonio Nino Diaz 146e6ab282SYann Gautier #include <platform_def.h> 156e6ab282SYann Gautier 1609d40e0eSAntonio Nino Diaz #include <arch.h> 1709d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1809d40e0eSAntonio Nino Diaz #include <common/debug.h> 1952a616b4SAndre Przywara #include <common/fdt_wrappers.h> 2009d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 2109d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h> 22447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h> 2309d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h> 2409d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h> 2509d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h> 2609d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 270d21680cSYann Gautier #include <lib/spinlock.h> 2809d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 2909d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 3009d40e0eSAntonio Nino Diaz 317839a050SYann Gautier #define MAX_HSI_HZ 64000000 320d21680cSYann Gautier #define USB_PHY_48_MHZ 48000000 337839a050SYann Gautier 34dfdb057aSYann Gautier #define TIMEOUT_US_200MS U(200000) 35dfdb057aSYann Gautier #define TIMEOUT_US_1S U(1000000) 367839a050SYann Gautier 37dfdb057aSYann Gautier #define PLLRDY_TIMEOUT TIMEOUT_US_200MS 38dfdb057aSYann Gautier #define CLKSRC_TIMEOUT TIMEOUT_US_200MS 39dfdb057aSYann Gautier #define CLKDIV_TIMEOUT TIMEOUT_US_200MS 40dfdb057aSYann Gautier #define HSIDIV_TIMEOUT TIMEOUT_US_200MS 41dfdb057aSYann Gautier #define OSCRDY_TIMEOUT TIMEOUT_US_1S 427839a050SYann Gautier 43f66358afSYann Gautier const char *stm32mp_osc_node_label[NB_OSC] = { 44f66358afSYann Gautier [_LSI] = "clk-lsi", 45f66358afSYann Gautier [_LSE] = "clk-lse", 46f66358afSYann Gautier [_HSI] = "clk-hsi", 47f66358afSYann Gautier [_HSE] = "clk-hse", 48f66358afSYann Gautier [_CSI] = "clk-csi", 49f66358afSYann Gautier [_I2S_CKIN] = "i2s_ckin", 50f66358afSYann Gautier }; 51f66358afSYann Gautier 527839a050SYann Gautier enum stm32mp1_parent_id { 537839a050SYann Gautier /* Oscillators are defined in enum stm32mp_osc_id */ 547839a050SYann Gautier 557839a050SYann Gautier /* Other parent source */ 567839a050SYann Gautier _HSI_KER = NB_OSC, 577839a050SYann Gautier _HSE_KER, 587839a050SYann Gautier _HSE_KER_DIV2, 597839a050SYann Gautier _CSI_KER, 607839a050SYann Gautier _PLL1_P, 617839a050SYann Gautier _PLL1_Q, 627839a050SYann Gautier _PLL1_R, 637839a050SYann Gautier _PLL2_P, 647839a050SYann Gautier _PLL2_Q, 657839a050SYann Gautier _PLL2_R, 667839a050SYann Gautier _PLL3_P, 677839a050SYann Gautier _PLL3_Q, 687839a050SYann Gautier _PLL3_R, 697839a050SYann Gautier _PLL4_P, 707839a050SYann Gautier _PLL4_Q, 717839a050SYann Gautier _PLL4_R, 727839a050SYann Gautier _ACLK, 737839a050SYann Gautier _PCLK1, 747839a050SYann Gautier _PCLK2, 757839a050SYann Gautier _PCLK3, 767839a050SYann Gautier _PCLK4, 777839a050SYann Gautier _PCLK5, 787839a050SYann Gautier _HCLK6, 797839a050SYann Gautier _HCLK2, 807839a050SYann Gautier _CK_PER, 817839a050SYann Gautier _CK_MPU, 82b053a22eSYann Gautier _CK_MCU, 830d21680cSYann Gautier _USB_PHY_48, 847839a050SYann Gautier _PARENT_NB, 857839a050SYann Gautier _UNKNOWN_ID = 0xff, 867839a050SYann Gautier }; 877839a050SYann Gautier 880d21680cSYann Gautier /* Lists only the parent clock we are interested in */ 897839a050SYann Gautier enum stm32mp1_parent_sel { 900d21680cSYann Gautier _I2C12_SEL, 910d21680cSYann Gautier _I2C35_SEL, 920d21680cSYann Gautier _STGEN_SEL, 937839a050SYann Gautier _I2C46_SEL, 940d21680cSYann Gautier _SPI6_SEL, 95d4151d2fSYann Gautier _UART1_SEL, 960d21680cSYann Gautier _RNG1_SEL, 977839a050SYann Gautier _UART6_SEL, 987839a050SYann Gautier _UART24_SEL, 997839a050SYann Gautier _UART35_SEL, 1007839a050SYann Gautier _UART78_SEL, 1017839a050SYann Gautier _SDMMC12_SEL, 1027839a050SYann Gautier _SDMMC3_SEL, 1037839a050SYann Gautier _QSPI_SEL, 1047839a050SYann Gautier _FMC_SEL, 105d4151d2fSYann Gautier _AXIS_SEL, 106d4151d2fSYann Gautier _MCUS_SEL, 1077839a050SYann Gautier _USBPHY_SEL, 1087839a050SYann Gautier _USBO_SEL, 1098fbcd9e4SEtienne Carriere _MPU_SEL, 1108fbcd9e4SEtienne Carriere _PER_SEL, 111016af006SEtienne Carriere _RTC_SEL, 1127839a050SYann Gautier _PARENT_SEL_NB, 1137839a050SYann Gautier _UNKNOWN_SEL = 0xff, 1147839a050SYann Gautier }; 1157839a050SYann Gautier 1168fbcd9e4SEtienne Carriere /* State the parent clock ID straight related to a clock */ 1178fbcd9e4SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = { 1188fbcd9e4SEtienne Carriere [_HSE] = CK_HSE, 1198fbcd9e4SEtienne Carriere [_HSI] = CK_HSI, 1208fbcd9e4SEtienne Carriere [_CSI] = CK_CSI, 1218fbcd9e4SEtienne Carriere [_LSE] = CK_LSE, 1228fbcd9e4SEtienne Carriere [_LSI] = CK_LSI, 1238fbcd9e4SEtienne Carriere [_I2S_CKIN] = _UNKNOWN_ID, 1248fbcd9e4SEtienne Carriere [_USB_PHY_48] = _UNKNOWN_ID, 1258fbcd9e4SEtienne Carriere [_HSI_KER] = CK_HSI, 1268fbcd9e4SEtienne Carriere [_HSE_KER] = CK_HSE, 1278fbcd9e4SEtienne Carriere [_HSE_KER_DIV2] = CK_HSE_DIV2, 1288fbcd9e4SEtienne Carriere [_CSI_KER] = CK_CSI, 1298fbcd9e4SEtienne Carriere [_PLL1_P] = PLL1_P, 1308fbcd9e4SEtienne Carriere [_PLL1_Q] = PLL1_Q, 1318fbcd9e4SEtienne Carriere [_PLL1_R] = PLL1_R, 1328fbcd9e4SEtienne Carriere [_PLL2_P] = PLL2_P, 1338fbcd9e4SEtienne Carriere [_PLL2_Q] = PLL2_Q, 1348fbcd9e4SEtienne Carriere [_PLL2_R] = PLL2_R, 1358fbcd9e4SEtienne Carriere [_PLL3_P] = PLL3_P, 1368fbcd9e4SEtienne Carriere [_PLL3_Q] = PLL3_Q, 1378fbcd9e4SEtienne Carriere [_PLL3_R] = PLL3_R, 1388fbcd9e4SEtienne Carriere [_PLL4_P] = PLL4_P, 1398fbcd9e4SEtienne Carriere [_PLL4_Q] = PLL4_Q, 1408fbcd9e4SEtienne Carriere [_PLL4_R] = PLL4_R, 1418fbcd9e4SEtienne Carriere [_ACLK] = CK_AXI, 1428fbcd9e4SEtienne Carriere [_PCLK1] = CK_AXI, 1438fbcd9e4SEtienne Carriere [_PCLK2] = CK_AXI, 1448fbcd9e4SEtienne Carriere [_PCLK3] = CK_AXI, 1458fbcd9e4SEtienne Carriere [_PCLK4] = CK_AXI, 1468fbcd9e4SEtienne Carriere [_PCLK5] = CK_AXI, 1478fbcd9e4SEtienne Carriere [_CK_PER] = CK_PER, 1488fbcd9e4SEtienne Carriere [_CK_MPU] = CK_MPU, 1498fbcd9e4SEtienne Carriere [_CK_MCU] = CK_MCU, 1508fbcd9e4SEtienne Carriere }; 1518fbcd9e4SEtienne Carriere 1528fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id) 1538fbcd9e4SEtienne Carriere { 1548fbcd9e4SEtienne Carriere unsigned int n; 1558fbcd9e4SEtienne Carriere 1568fbcd9e4SEtienne Carriere for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { 1578fbcd9e4SEtienne Carriere if (parent_id_clock_id[n] == id) { 1588fbcd9e4SEtienne Carriere return n; 1598fbcd9e4SEtienne Carriere } 1608fbcd9e4SEtienne Carriere } 1618fbcd9e4SEtienne Carriere 1628fbcd9e4SEtienne Carriere return _UNKNOWN_ID; 1638fbcd9e4SEtienne Carriere } 1648fbcd9e4SEtienne Carriere 1657839a050SYann Gautier enum stm32mp1_pll_id { 1667839a050SYann Gautier _PLL1, 1677839a050SYann Gautier _PLL2, 1687839a050SYann Gautier _PLL3, 1697839a050SYann Gautier _PLL4, 1707839a050SYann Gautier _PLL_NB 1717839a050SYann Gautier }; 1727839a050SYann Gautier 1737839a050SYann Gautier enum stm32mp1_div_id { 1747839a050SYann Gautier _DIV_P, 1757839a050SYann Gautier _DIV_Q, 1767839a050SYann Gautier _DIV_R, 1777839a050SYann Gautier _DIV_NB, 1787839a050SYann Gautier }; 1797839a050SYann Gautier 1807839a050SYann Gautier enum stm32mp1_clksrc_id { 1817839a050SYann Gautier CLKSRC_MPU, 1827839a050SYann Gautier CLKSRC_AXI, 183b053a22eSYann Gautier CLKSRC_MCU, 1847839a050SYann Gautier CLKSRC_PLL12, 1857839a050SYann Gautier CLKSRC_PLL3, 1867839a050SYann Gautier CLKSRC_PLL4, 1877839a050SYann Gautier CLKSRC_RTC, 1887839a050SYann Gautier CLKSRC_MCO1, 1897839a050SYann Gautier CLKSRC_MCO2, 1907839a050SYann Gautier CLKSRC_NB 1917839a050SYann Gautier }; 1927839a050SYann Gautier 1937839a050SYann Gautier enum stm32mp1_clkdiv_id { 1947839a050SYann Gautier CLKDIV_MPU, 1957839a050SYann Gautier CLKDIV_AXI, 196b053a22eSYann Gautier CLKDIV_MCU, 1977839a050SYann Gautier CLKDIV_APB1, 1987839a050SYann Gautier CLKDIV_APB2, 1997839a050SYann Gautier CLKDIV_APB3, 2007839a050SYann Gautier CLKDIV_APB4, 2017839a050SYann Gautier CLKDIV_APB5, 2027839a050SYann Gautier CLKDIV_RTC, 2037839a050SYann Gautier CLKDIV_MCO1, 2047839a050SYann Gautier CLKDIV_MCO2, 2057839a050SYann Gautier CLKDIV_NB 2067839a050SYann Gautier }; 2077839a050SYann Gautier 2087839a050SYann Gautier enum stm32mp1_pllcfg { 2097839a050SYann Gautier PLLCFG_M, 2107839a050SYann Gautier PLLCFG_N, 2117839a050SYann Gautier PLLCFG_P, 2127839a050SYann Gautier PLLCFG_Q, 2137839a050SYann Gautier PLLCFG_R, 2147839a050SYann Gautier PLLCFG_O, 2157839a050SYann Gautier PLLCFG_NB 2167839a050SYann Gautier }; 2177839a050SYann Gautier 2187839a050SYann Gautier enum stm32mp1_pllcsg { 2197839a050SYann Gautier PLLCSG_MOD_PER, 2207839a050SYann Gautier PLLCSG_INC_STEP, 2217839a050SYann Gautier PLLCSG_SSCG_MODE, 2227839a050SYann Gautier PLLCSG_NB 2237839a050SYann Gautier }; 2247839a050SYann Gautier 2257839a050SYann Gautier enum stm32mp1_plltype { 2267839a050SYann Gautier PLL_800, 2277839a050SYann Gautier PLL_1600, 2287839a050SYann Gautier PLL_TYPE_NB 2297839a050SYann Gautier }; 2307839a050SYann Gautier 2317839a050SYann Gautier struct stm32mp1_pll { 2327839a050SYann Gautier uint8_t refclk_min; 2337839a050SYann Gautier uint8_t refclk_max; 2347839a050SYann Gautier uint8_t divn_max; 2357839a050SYann Gautier }; 2367839a050SYann Gautier 2377839a050SYann Gautier struct stm32mp1_clk_gate { 2387839a050SYann Gautier uint16_t offset; 2397839a050SYann Gautier uint8_t bit; 2407839a050SYann Gautier uint8_t index; 2417839a050SYann Gautier uint8_t set_clr; 2420d21680cSYann Gautier uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ 2430d21680cSYann Gautier uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ 2447839a050SYann Gautier }; 2457839a050SYann Gautier 2467839a050SYann Gautier struct stm32mp1_clk_sel { 2477839a050SYann Gautier uint16_t offset; 2487839a050SYann Gautier uint8_t src; 2497839a050SYann Gautier uint8_t msk; 2507839a050SYann Gautier uint8_t nb_parent; 2517839a050SYann Gautier const uint8_t *parent; 2527839a050SYann Gautier }; 2537839a050SYann Gautier 2547839a050SYann Gautier #define REFCLK_SIZE 4 2557839a050SYann Gautier struct stm32mp1_clk_pll { 2567839a050SYann Gautier enum stm32mp1_plltype plltype; 2577839a050SYann Gautier uint16_t rckxselr; 2587839a050SYann Gautier uint16_t pllxcfgr1; 2597839a050SYann Gautier uint16_t pllxcfgr2; 2607839a050SYann Gautier uint16_t pllxfracr; 2617839a050SYann Gautier uint16_t pllxcr; 2627839a050SYann Gautier uint16_t pllxcsgr; 2637839a050SYann Gautier enum stm32mp_osc_id refclk[REFCLK_SIZE]; 2647839a050SYann Gautier }; 2657839a050SYann Gautier 2660d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */ 2670d21680cSYann Gautier #define _CLK_SELEC(off, b, idx, s) \ 2687839a050SYann Gautier { \ 2697839a050SYann Gautier .offset = (off), \ 2707839a050SYann Gautier .bit = (b), \ 2717839a050SYann Gautier .index = (idx), \ 2727839a050SYann Gautier .set_clr = 0, \ 2737839a050SYann Gautier .sel = (s), \ 2747839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 2757839a050SYann Gautier } 2767839a050SYann Gautier 2770d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */ 2780d21680cSYann Gautier #define _CLK_FIXED(off, b, idx, f) \ 2797839a050SYann Gautier { \ 2807839a050SYann Gautier .offset = (off), \ 2817839a050SYann Gautier .bit = (b), \ 2827839a050SYann Gautier .index = (idx), \ 2837839a050SYann Gautier .set_clr = 0, \ 2847839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 2857839a050SYann Gautier .fixed = (f), \ 2867839a050SYann Gautier } 2877839a050SYann Gautier 2880d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */ 2890d21680cSYann Gautier #define _CLK_SC_SELEC(off, b, idx, s) \ 2907839a050SYann Gautier { \ 2917839a050SYann Gautier .offset = (off), \ 2927839a050SYann Gautier .bit = (b), \ 2937839a050SYann Gautier .index = (idx), \ 2947839a050SYann Gautier .set_clr = 1, \ 2957839a050SYann Gautier .sel = (s), \ 2967839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 2977839a050SYann Gautier } 2987839a050SYann Gautier 2990d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */ 3000d21680cSYann Gautier #define _CLK_SC_FIXED(off, b, idx, f) \ 3017839a050SYann Gautier { \ 3027839a050SYann Gautier .offset = (off), \ 3037839a050SYann Gautier .bit = (b), \ 3047839a050SYann Gautier .index = (idx), \ 3057839a050SYann Gautier .set_clr = 1, \ 3067839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 3077839a050SYann Gautier .fixed = (f), \ 3087839a050SYann Gautier } 3097839a050SYann Gautier 310d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ 311d4151d2fSYann Gautier [_ ## _label ## _SEL] = { \ 312d4151d2fSYann Gautier .offset = _rcc_selr, \ 313d4151d2fSYann Gautier .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ 3148ae08dcdSEtienne Carriere .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ 3158ae08dcdSEtienne Carriere (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ 316d4151d2fSYann Gautier .parent = (_parents), \ 317d4151d2fSYann Gautier .nb_parent = ARRAY_SIZE(_parents) \ 3187839a050SYann Gautier } 3197839a050SYann Gautier 3200d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3, \ 3217839a050SYann Gautier off4, off5, off6, \ 3227839a050SYann Gautier p1, p2, p3, p4) \ 3237839a050SYann Gautier [(idx)] = { \ 3247839a050SYann Gautier .plltype = (type), \ 3257839a050SYann Gautier .rckxselr = (off1), \ 3267839a050SYann Gautier .pllxcfgr1 = (off2), \ 3277839a050SYann Gautier .pllxcfgr2 = (off3), \ 3287839a050SYann Gautier .pllxfracr = (off4), \ 3297839a050SYann Gautier .pllxcr = (off5), \ 3307839a050SYann Gautier .pllxcsgr = (off6), \ 3317839a050SYann Gautier .refclk[0] = (p1), \ 3327839a050SYann Gautier .refclk[1] = (p2), \ 3337839a050SYann Gautier .refclk[2] = (p3), \ 3347839a050SYann Gautier .refclk[3] = (p4), \ 3357839a050SYann Gautier } 3367839a050SYann Gautier 3370d21680cSYann Gautier #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) 3380d21680cSYann Gautier 3397839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { 3400d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), 3410d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), 3420d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), 3430d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), 3440d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), 3450d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), 3460d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), 3470d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), 3480d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), 3490d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), 3500d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), 3517839a050SYann Gautier 3520d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), 3530d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), 3540d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), 3550d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), 3560d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), 3570d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), 3580d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), 3590d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), 3600d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), 3610d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), 3620d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), 3637839a050SYann Gautier 3640d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), 3650d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), 3667839a050SYann Gautier 367f33b2433SYann Gautier _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), 368f33b2433SYann Gautier 3690d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), 3700d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), 3710d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), 3727839a050SYann Gautier 3730d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), 3740d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), 3750d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), 376d4151d2fSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), 3770d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), 3780d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), 3790d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), 3800d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), 3810d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), 3820d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), 3830d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), 3847839a050SYann Gautier 3850d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), 3860d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), 3877839a050SYann Gautier 3880d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), 3890d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), 3900d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), 3910d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), 3920d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), 3930d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), 3940d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), 3950d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), 3960d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), 3970d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), 3980d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), 3997839a050SYann Gautier 4000d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), 4010d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), 4020d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), 4030d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), 4040d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), 4057839a050SYann Gautier 4060d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), 4070d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), 4080d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), 4090d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), 4100d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), 4117839a050SYann Gautier 412016af006SEtienne Carriere _CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL), 4130d21680cSYann Gautier _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), 4147839a050SYann Gautier }; 4157839a050SYann Gautier 4160d21680cSYann Gautier static const uint8_t i2c12_parents[] = { 4170d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 4180d21680cSYann Gautier }; 4190d21680cSYann Gautier 4200d21680cSYann Gautier static const uint8_t i2c35_parents[] = { 4210d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 4220d21680cSYann Gautier }; 4230d21680cSYann Gautier 4240d21680cSYann Gautier static const uint8_t stgen_parents[] = { 4250d21680cSYann Gautier _HSI_KER, _HSE_KER 4260d21680cSYann Gautier }; 4270d21680cSYann Gautier 4280d21680cSYann Gautier static const uint8_t i2c46_parents[] = { 4290d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER 4300d21680cSYann Gautier }; 4310d21680cSYann Gautier 4320d21680cSYann Gautier static const uint8_t spi6_parents[] = { 4330d21680cSYann Gautier _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q 4340d21680cSYann Gautier }; 4350d21680cSYann Gautier 4360d21680cSYann Gautier static const uint8_t usart1_parents[] = { 4370d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER 4380d21680cSYann Gautier }; 4390d21680cSYann Gautier 4400d21680cSYann Gautier static const uint8_t rng1_parents[] = { 4410d21680cSYann Gautier _CSI, _PLL4_R, _LSE, _LSI 4420d21680cSYann Gautier }; 4430d21680cSYann Gautier 4440d21680cSYann Gautier static const uint8_t uart6_parents[] = { 4450d21680cSYann Gautier _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 4460d21680cSYann Gautier }; 4470d21680cSYann Gautier 4480d21680cSYann Gautier static const uint8_t uart234578_parents[] = { 4490d21680cSYann Gautier _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 4500d21680cSYann Gautier }; 4510d21680cSYann Gautier 4520d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = { 4530d21680cSYann Gautier _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER 4540d21680cSYann Gautier }; 4550d21680cSYann Gautier 4560d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = { 4570d21680cSYann Gautier _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER 4580d21680cSYann Gautier }; 4590d21680cSYann Gautier 4600d21680cSYann Gautier static const uint8_t qspi_parents[] = { 4610d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 4620d21680cSYann Gautier }; 4630d21680cSYann Gautier 4640d21680cSYann Gautier static const uint8_t fmc_parents[] = { 4650d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 4660d21680cSYann Gautier }; 4670d21680cSYann Gautier 4680d21680cSYann Gautier static const uint8_t ass_parents[] = { 4690d21680cSYann Gautier _HSI, _HSE, _PLL2 4700d21680cSYann Gautier }; 4710d21680cSYann Gautier 472b053a22eSYann Gautier static const uint8_t mss_parents[] = { 473b053a22eSYann Gautier _HSI, _HSE, _CSI, _PLL3 474b053a22eSYann Gautier }; 475b053a22eSYann Gautier 4760d21680cSYann Gautier static const uint8_t usbphy_parents[] = { 4770d21680cSYann Gautier _HSE_KER, _PLL4_R, _HSE_KER_DIV2 4780d21680cSYann Gautier }; 4790d21680cSYann Gautier 4800d21680cSYann Gautier static const uint8_t usbo_parents[] = { 4810d21680cSYann Gautier _PLL4_R, _USB_PHY_48 4820d21680cSYann Gautier }; 4837839a050SYann Gautier 4848fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = { 4858fbcd9e4SEtienne Carriere _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ 4868fbcd9e4SEtienne Carriere }; 4878fbcd9e4SEtienne Carriere 4888fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = { 4898fbcd9e4SEtienne Carriere _HSI, _HSE, _CSI, 4908fbcd9e4SEtienne Carriere }; 4918fbcd9e4SEtienne Carriere 492016af006SEtienne Carriere static const uint8_t rtc_parents[] = { 493016af006SEtienne Carriere _UNKNOWN_ID, _LSE, _LSI, _HSE 494016af006SEtienne Carriere }; 495016af006SEtienne Carriere 4967839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { 497d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), 498d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), 499d4151d2fSYann Gautier _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), 500d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), 501d4151d2fSYann Gautier _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), 502d4151d2fSYann Gautier _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), 503d4151d2fSYann Gautier _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), 5048fbcd9e4SEtienne Carriere _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), 5058fbcd9e4SEtienne Carriere _CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents), 506016af006SEtienne Carriere _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), 507d4151d2fSYann Gautier _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), 508d4151d2fSYann Gautier _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), 509d4151d2fSYann Gautier _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), 510d4151d2fSYann Gautier _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), 511d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), 512d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), 513d4151d2fSYann Gautier _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), 514d4151d2fSYann Gautier _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), 515d4151d2fSYann Gautier _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents), 516d4151d2fSYann Gautier _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents), 517d4151d2fSYann Gautier _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), 518d4151d2fSYann Gautier _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), 5197839a050SYann Gautier }; 5207839a050SYann Gautier 5217839a050SYann Gautier /* Define characteristic of PLL according type */ 5227839a050SYann Gautier #define DIVN_MIN 24 5237839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { 5247839a050SYann Gautier [PLL_800] = { 5257839a050SYann Gautier .refclk_min = 4, 5267839a050SYann Gautier .refclk_max = 16, 5277839a050SYann Gautier .divn_max = 99, 5287839a050SYann Gautier }, 5297839a050SYann Gautier [PLL_1600] = { 5307839a050SYann Gautier .refclk_min = 8, 5317839a050SYann Gautier .refclk_max = 16, 5327839a050SYann Gautier .divn_max = 199, 5337839a050SYann Gautier }, 5347839a050SYann Gautier }; 5357839a050SYann Gautier 5367839a050SYann Gautier /* PLLNCFGR2 register divider by output */ 5377839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = { 5387839a050SYann Gautier [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, 5397839a050SYann Gautier [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, 5400d21680cSYann Gautier [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, 5417839a050SYann Gautier }; 5427839a050SYann Gautier 5437839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { 5440d21680cSYann Gautier _CLK_PLL(_PLL1, PLL_1600, 5457839a050SYann Gautier RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, 5467839a050SYann Gautier RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, 5477839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 5480d21680cSYann Gautier _CLK_PLL(_PLL2, PLL_1600, 5497839a050SYann Gautier RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, 5507839a050SYann Gautier RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, 5517839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 5520d21680cSYann Gautier _CLK_PLL(_PLL3, PLL_800, 5537839a050SYann Gautier RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, 5547839a050SYann Gautier RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, 5557839a050SYann Gautier _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), 5560d21680cSYann Gautier _CLK_PLL(_PLL4, PLL_800, 5577839a050SYann Gautier RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, 5587839a050SYann Gautier RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, 5597839a050SYann Gautier _HSI, _HSE, _CSI, _I2S_CKIN), 5607839a050SYann Gautier }; 5617839a050SYann Gautier 5627839a050SYann Gautier /* Prescaler table lookups for clock computation */ 563b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ 564b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = { 565b053a22eSYann Gautier 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 566b053a22eSYann Gautier }; 5677839a050SYann Gautier 5687839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ 5697839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div 5707839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div 5717839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = { 5727839a050SYann Gautier 0, 1, 2, 3, 4, 4, 4, 4 5737839a050SYann Gautier }; 5747839a050SYann Gautier 5757839a050SYann Gautier /* div = /1 /2 /3 /4 */ 5767839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = { 5777839a050SYann Gautier 1, 2, 3, 4, 4, 4, 4, 4 5787839a050SYann Gautier }; 5797839a050SYann Gautier 58037e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { 58137e8295aSEtienne Carriere [_HSI] = "HSI", 58237e8295aSEtienne Carriere [_HSE] = "HSE", 58337e8295aSEtienne Carriere [_CSI] = "CSI", 58437e8295aSEtienne Carriere [_LSI] = "LSI", 58537e8295aSEtienne Carriere [_LSE] = "LSE", 58637e8295aSEtienne Carriere [_I2S_CKIN] = "I2S_CKIN", 58737e8295aSEtienne Carriere [_HSI_KER] = "HSI_KER", 58837e8295aSEtienne Carriere [_HSE_KER] = "HSE_KER", 58937e8295aSEtienne Carriere [_HSE_KER_DIV2] = "HSE_KER_DIV2", 59037e8295aSEtienne Carriere [_CSI_KER] = "CSI_KER", 59137e8295aSEtienne Carriere [_PLL1_P] = "PLL1_P", 59237e8295aSEtienne Carriere [_PLL1_Q] = "PLL1_Q", 59337e8295aSEtienne Carriere [_PLL1_R] = "PLL1_R", 59437e8295aSEtienne Carriere [_PLL2_P] = "PLL2_P", 59537e8295aSEtienne Carriere [_PLL2_Q] = "PLL2_Q", 59637e8295aSEtienne Carriere [_PLL2_R] = "PLL2_R", 59737e8295aSEtienne Carriere [_PLL3_P] = "PLL3_P", 59837e8295aSEtienne Carriere [_PLL3_Q] = "PLL3_Q", 59937e8295aSEtienne Carriere [_PLL3_R] = "PLL3_R", 60037e8295aSEtienne Carriere [_PLL4_P] = "PLL4_P", 60137e8295aSEtienne Carriere [_PLL4_Q] = "PLL4_Q", 60237e8295aSEtienne Carriere [_PLL4_R] = "PLL4_R", 60337e8295aSEtienne Carriere [_ACLK] = "ACLK", 60437e8295aSEtienne Carriere [_PCLK1] = "PCLK1", 60537e8295aSEtienne Carriere [_PCLK2] = "PCLK2", 60637e8295aSEtienne Carriere [_PCLK3] = "PCLK3", 60737e8295aSEtienne Carriere [_PCLK4] = "PCLK4", 60837e8295aSEtienne Carriere [_PCLK5] = "PCLK5", 60937e8295aSEtienne Carriere [_HCLK6] = "KCLK6", 61037e8295aSEtienne Carriere [_HCLK2] = "HCLK2", 61137e8295aSEtienne Carriere [_CK_PER] = "CK_PER", 61237e8295aSEtienne Carriere [_CK_MPU] = "CK_MPU", 61337e8295aSEtienne Carriere [_CK_MCU] = "CK_MCU", 61437e8295aSEtienne Carriere [_USB_PHY_48] = "USB_PHY_48", 61537e8295aSEtienne Carriere }; 61637e8295aSEtienne Carriere 6170d21680cSYann Gautier /* RCC clock device driver private */ 6180d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC]; 6190d21680cSYann Gautier static struct spinlock reg_lock; 6200d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES]; 6210d21680cSYann Gautier static struct spinlock refcount_lock; 6227839a050SYann Gautier 6230d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) 6240d21680cSYann Gautier { 6250d21680cSYann Gautier return &stm32mp1_clk_gate[idx]; 6260d21680cSYann Gautier } 6277839a050SYann Gautier 6280d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) 6290d21680cSYann Gautier { 6300d21680cSYann Gautier return &stm32mp1_clk_sel[idx]; 6310d21680cSYann Gautier } 6320d21680cSYann Gautier 6330d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) 6340d21680cSYann Gautier { 6350d21680cSYann Gautier return &stm32mp1_clk_pll[idx]; 6360d21680cSYann Gautier } 6370d21680cSYann Gautier 6380d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock) 6390d21680cSYann Gautier { 640e463d3f4SYann Gautier if (stm32mp_lock_available()) { 6410d21680cSYann Gautier /* Assume interrupts are masked */ 6420d21680cSYann Gautier spin_lock(lock); 6430d21680cSYann Gautier } 644e463d3f4SYann Gautier } 6450d21680cSYann Gautier 6460d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock) 6470d21680cSYann Gautier { 648e463d3f4SYann Gautier if (stm32mp_lock_available()) { 6490d21680cSYann Gautier spin_unlock(lock); 6500d21680cSYann Gautier } 651e463d3f4SYann Gautier } 6520d21680cSYann Gautier 6530d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void) 6540d21680cSYann Gautier { 6550d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 6561bb9072aSEtienne Carriere uint32_t mask = RCC_TZCR_TZEN; 6570d21680cSYann Gautier 6581bb9072aSEtienne Carriere return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 6590d21680cSYann Gautier } 6600d21680cSYann Gautier 661b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void) 662b053a22eSYann Gautier { 663b053a22eSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 6641bb9072aSEtienne Carriere uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; 665b053a22eSYann Gautier 6661bb9072aSEtienne Carriere return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 667b053a22eSYann Gautier } 668b053a22eSYann Gautier 6690d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void) 6700d21680cSYann Gautier { 6710d21680cSYann Gautier stm32mp1_clk_lock(®_lock); 6720d21680cSYann Gautier } 6730d21680cSYann Gautier 6740d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void) 6750d21680cSYann Gautier { 6760d21680cSYann Gautier stm32mp1_clk_unlock(®_lock); 6770d21680cSYann Gautier } 6780d21680cSYann Gautier 6790d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) 6807839a050SYann Gautier { 6817839a050SYann Gautier if (idx >= NB_OSC) { 6827839a050SYann Gautier return 0; 6837839a050SYann Gautier } 6847839a050SYann Gautier 6850d21680cSYann Gautier return stm32mp1_osc[idx]; 6867839a050SYann Gautier } 6877839a050SYann Gautier 6880d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id) 6897839a050SYann Gautier { 6900d21680cSYann Gautier unsigned int i; 6917839a050SYann Gautier 6920d21680cSYann Gautier for (i = 0U; i < NB_GATES; i++) { 6930d21680cSYann Gautier if (gate_ref(i)->index == id) { 6947839a050SYann Gautier return i; 6957839a050SYann Gautier } 6967839a050SYann Gautier } 6977839a050SYann Gautier 6987839a050SYann Gautier ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id); 6997839a050SYann Gautier 7007839a050SYann Gautier return -EINVAL; 7017839a050SYann Gautier } 7027839a050SYann Gautier 7030d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) 7047839a050SYann Gautier { 7050d21680cSYann Gautier return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); 7067839a050SYann Gautier } 7077839a050SYann Gautier 7080d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) 7097839a050SYann Gautier { 7100d21680cSYann Gautier return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); 7117839a050SYann Gautier } 7127839a050SYann Gautier 7130d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id) 7147839a050SYann Gautier { 7150d21680cSYann Gautier const struct stm32mp1_clk_sel *sel; 7168fbcd9e4SEtienne Carriere uint32_t p_sel; 7177839a050SYann Gautier int i; 7187839a050SYann Gautier enum stm32mp1_parent_id p; 7197839a050SYann Gautier enum stm32mp1_parent_sel s; 7200d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 7217839a050SYann Gautier 7228fbcd9e4SEtienne Carriere /* Few non gateable clock have a static parent ID, find them */ 7238fbcd9e4SEtienne Carriere i = (int)clock_id2parent_id(id); 7248fbcd9e4SEtienne Carriere if (i != _UNKNOWN_ID) { 7258fbcd9e4SEtienne Carriere return i; 7267839a050SYann Gautier } 7277839a050SYann Gautier 7280d21680cSYann Gautier i = stm32mp1_clk_get_gated_id(id); 7297839a050SYann Gautier if (i < 0) { 7300d21680cSYann Gautier panic(); 7317839a050SYann Gautier } 7327839a050SYann Gautier 7330d21680cSYann Gautier p = stm32mp1_clk_get_fixed_parent(i); 7347839a050SYann Gautier if (p < _PARENT_NB) { 7357839a050SYann Gautier return (int)p; 7367839a050SYann Gautier } 7377839a050SYann Gautier 7380d21680cSYann Gautier s = stm32mp1_clk_get_sel(i); 7390d21680cSYann Gautier if (s == _UNKNOWN_SEL) { 7400d21680cSYann Gautier return -EINVAL; 7410d21680cSYann Gautier } 7427839a050SYann Gautier if (s >= _PARENT_SEL_NB) { 7430d21680cSYann Gautier panic(); 7447839a050SYann Gautier } 7457839a050SYann Gautier 7460d21680cSYann Gautier sel = clk_sel_ref(s); 7478ae08dcdSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) & 7488ae08dcdSEtienne Carriere (sel->msk << sel->src)) >> sel->src; 7490d21680cSYann Gautier if (p_sel < sel->nb_parent) { 7500d21680cSYann Gautier return (int)sel->parent[p_sel]; 7517839a050SYann Gautier } 7527839a050SYann Gautier 7537839a050SYann Gautier return -EINVAL; 7547839a050SYann Gautier } 7557839a050SYann Gautier 7560d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) 7577839a050SYann Gautier { 7580d21680cSYann Gautier uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); 7590d21680cSYann Gautier uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; 7607839a050SYann Gautier 7610d21680cSYann Gautier return stm32mp1_clk_get_fixed(pll->refclk[src]); 7627839a050SYann Gautier } 7637839a050SYann Gautier 7647839a050SYann Gautier /* 7657839a050SYann Gautier * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL 7667839a050SYann Gautier * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) 7677839a050SYann Gautier * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) 7687839a050SYann Gautier * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) 7697839a050SYann Gautier */ 7700d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) 7717839a050SYann Gautier { 7727839a050SYann Gautier unsigned long refclk, fvco; 7737839a050SYann Gautier uint32_t cfgr1, fracr, divm, divn; 7740d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 7757839a050SYann Gautier 7760d21680cSYann Gautier cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); 7770d21680cSYann Gautier fracr = mmio_read_32(rcc_base + pll->pllxfracr); 7787839a050SYann Gautier 7797839a050SYann Gautier divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; 7807839a050SYann Gautier divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; 7817839a050SYann Gautier 7820d21680cSYann Gautier refclk = stm32mp1_pll_get_fref(pll); 7837839a050SYann Gautier 7847839a050SYann Gautier /* 7857839a050SYann Gautier * With FRACV : 7867839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) 7877839a050SYann Gautier * Without FRACV 7887839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) 7897839a050SYann Gautier */ 7907839a050SYann Gautier if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { 7910d21680cSYann Gautier uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> 7920d21680cSYann Gautier RCC_PLLNFRACR_FRACV_SHIFT; 7937839a050SYann Gautier unsigned long long numerator, denominator; 7947839a050SYann Gautier 7950d21680cSYann Gautier numerator = (((unsigned long long)divn + 1U) << 13) + fracv; 7960d21680cSYann Gautier numerator = refclk * numerator; 7977839a050SYann Gautier denominator = ((unsigned long long)divm + 1U) << 13; 7987839a050SYann Gautier fvco = (unsigned long)(numerator / denominator); 7997839a050SYann Gautier } else { 8007839a050SYann Gautier fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); 8017839a050SYann Gautier } 8027839a050SYann Gautier 8037839a050SYann Gautier return fvco; 8047839a050SYann Gautier } 8057839a050SYann Gautier 8060d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, 8077839a050SYann Gautier enum stm32mp1_div_id div_id) 8087839a050SYann Gautier { 8090d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 8107839a050SYann Gautier unsigned long dfout; 8117839a050SYann Gautier uint32_t cfgr2, divy; 8127839a050SYann Gautier 8137839a050SYann Gautier if (div_id >= _DIV_NB) { 8147839a050SYann Gautier return 0; 8157839a050SYann Gautier } 8167839a050SYann Gautier 8170d21680cSYann Gautier cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); 8187839a050SYann Gautier divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; 8197839a050SYann Gautier 8200d21680cSYann Gautier dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); 8217839a050SYann Gautier 8227839a050SYann Gautier return dfout; 8237839a050SYann Gautier } 8247839a050SYann Gautier 8250d21680cSYann Gautier static unsigned long get_clock_rate(int p) 8267839a050SYann Gautier { 8277839a050SYann Gautier uint32_t reg, clkdiv; 8287839a050SYann Gautier unsigned long clock = 0; 8290d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 8307839a050SYann Gautier 8317839a050SYann Gautier switch (p) { 8327839a050SYann Gautier case _CK_MPU: 8337839a050SYann Gautier /* MPU sub system */ 8340d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKSELR); 8357839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 8367839a050SYann Gautier case RCC_MPCKSELR_HSI: 8370d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 8387839a050SYann Gautier break; 8397839a050SYann Gautier case RCC_MPCKSELR_HSE: 8400d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 8417839a050SYann Gautier break; 8427839a050SYann Gautier case RCC_MPCKSELR_PLL: 8430d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 8447839a050SYann Gautier break; 8457839a050SYann Gautier case RCC_MPCKSELR_PLL_MPUDIV: 8460d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 8477839a050SYann Gautier 8480d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); 8497839a050SYann Gautier clkdiv = reg & RCC_MPUDIV_MASK; 8507839a050SYann Gautier if (clkdiv != 0U) { 8517839a050SYann Gautier clock /= stm32mp1_mpu_div[clkdiv]; 8527839a050SYann Gautier } 8537839a050SYann Gautier break; 8547839a050SYann Gautier default: 8557839a050SYann Gautier break; 8567839a050SYann Gautier } 8577839a050SYann Gautier break; 8587839a050SYann Gautier /* AXI sub system */ 8597839a050SYann Gautier case _ACLK: 8607839a050SYann Gautier case _HCLK2: 8617839a050SYann Gautier case _HCLK6: 8627839a050SYann Gautier case _PCLK4: 8637839a050SYann Gautier case _PCLK5: 8640d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); 8657839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 8667839a050SYann Gautier case RCC_ASSCKSELR_HSI: 8670d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 8687839a050SYann Gautier break; 8697839a050SYann Gautier case RCC_ASSCKSELR_HSE: 8700d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 8717839a050SYann Gautier break; 8727839a050SYann Gautier case RCC_ASSCKSELR_PLL: 8730d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 8747839a050SYann Gautier break; 8757839a050SYann Gautier default: 8767839a050SYann Gautier break; 8777839a050SYann Gautier } 8787839a050SYann Gautier 8797839a050SYann Gautier /* System clock divider */ 8800d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_AXIDIVR); 8817839a050SYann Gautier clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; 8827839a050SYann Gautier 8837839a050SYann Gautier switch (p) { 8847839a050SYann Gautier case _PCLK4: 8850d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB4DIVR); 8867839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 8877839a050SYann Gautier break; 8887839a050SYann Gautier case _PCLK5: 8890d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB5DIVR); 8907839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 8917839a050SYann Gautier break; 8927839a050SYann Gautier default: 8937839a050SYann Gautier break; 8947839a050SYann Gautier } 8957839a050SYann Gautier break; 896b053a22eSYann Gautier /* MCU sub system */ 897b053a22eSYann Gautier case _CK_MCU: 898b053a22eSYann Gautier case _PCLK1: 899b053a22eSYann Gautier case _PCLK2: 900b053a22eSYann Gautier case _PCLK3: 901b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); 902b053a22eSYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 903b053a22eSYann Gautier case RCC_MSSCKSELR_HSI: 904b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 905b053a22eSYann Gautier break; 906b053a22eSYann Gautier case RCC_MSSCKSELR_HSE: 907b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 908b053a22eSYann Gautier break; 909b053a22eSYann Gautier case RCC_MSSCKSELR_CSI: 910b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 911b053a22eSYann Gautier break; 912b053a22eSYann Gautier case RCC_MSSCKSELR_PLL: 913b053a22eSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 914b053a22eSYann Gautier break; 915b053a22eSYann Gautier default: 916b053a22eSYann Gautier break; 917b053a22eSYann Gautier } 918b053a22eSYann Gautier 919b053a22eSYann Gautier /* MCU clock divider */ 920b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MCUDIVR); 921b053a22eSYann Gautier clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; 922b053a22eSYann Gautier 923b053a22eSYann Gautier switch (p) { 924b053a22eSYann Gautier case _PCLK1: 925b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB1DIVR); 926b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 927b053a22eSYann Gautier break; 928b053a22eSYann Gautier case _PCLK2: 929b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB2DIVR); 930b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 931b053a22eSYann Gautier break; 932b053a22eSYann Gautier case _PCLK3: 933b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB3DIVR); 934b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 935b053a22eSYann Gautier break; 936b053a22eSYann Gautier case _CK_MCU: 937b053a22eSYann Gautier default: 938b053a22eSYann Gautier break; 939b053a22eSYann Gautier } 940b053a22eSYann Gautier break; 9417839a050SYann Gautier case _CK_PER: 9420d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); 9437839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 9447839a050SYann Gautier case RCC_CPERCKSELR_HSI: 9450d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 9467839a050SYann Gautier break; 9477839a050SYann Gautier case RCC_CPERCKSELR_HSE: 9480d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 9497839a050SYann Gautier break; 9507839a050SYann Gautier case RCC_CPERCKSELR_CSI: 9510d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 9527839a050SYann Gautier break; 9537839a050SYann Gautier default: 9547839a050SYann Gautier break; 9557839a050SYann Gautier } 9567839a050SYann Gautier break; 9577839a050SYann Gautier case _HSI: 9587839a050SYann Gautier case _HSI_KER: 9590d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 9607839a050SYann Gautier break; 9617839a050SYann Gautier case _CSI: 9627839a050SYann Gautier case _CSI_KER: 9630d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 9647839a050SYann Gautier break; 9657839a050SYann Gautier case _HSE: 9667839a050SYann Gautier case _HSE_KER: 9670d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 9687839a050SYann Gautier break; 9697839a050SYann Gautier case _HSE_KER_DIV2: 9700d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE) >> 1; 9717839a050SYann Gautier break; 9727839a050SYann Gautier case _LSI: 9730d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSI); 9747839a050SYann Gautier break; 9757839a050SYann Gautier case _LSE: 9760d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSE); 9777839a050SYann Gautier break; 9787839a050SYann Gautier /* PLL */ 9797839a050SYann Gautier case _PLL1_P: 9800d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 9817839a050SYann Gautier break; 9827839a050SYann Gautier case _PLL1_Q: 9830d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); 9847839a050SYann Gautier break; 9857839a050SYann Gautier case _PLL1_R: 9860d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); 9877839a050SYann Gautier break; 9887839a050SYann Gautier case _PLL2_P: 9890d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 9907839a050SYann Gautier break; 9917839a050SYann Gautier case _PLL2_Q: 9920d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); 9937839a050SYann Gautier break; 9947839a050SYann Gautier case _PLL2_R: 9950d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); 9967839a050SYann Gautier break; 9977839a050SYann Gautier case _PLL3_P: 9980d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 9997839a050SYann Gautier break; 10007839a050SYann Gautier case _PLL3_Q: 10010d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); 10027839a050SYann Gautier break; 10037839a050SYann Gautier case _PLL3_R: 10040d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); 10057839a050SYann Gautier break; 10067839a050SYann Gautier case _PLL4_P: 10070d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); 10087839a050SYann Gautier break; 10097839a050SYann Gautier case _PLL4_Q: 10100d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); 10117839a050SYann Gautier break; 10127839a050SYann Gautier case _PLL4_R: 10130d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); 10147839a050SYann Gautier break; 10157839a050SYann Gautier /* Other */ 10167839a050SYann Gautier case _USB_PHY_48: 10170d21680cSYann Gautier clock = USB_PHY_48_MHZ; 10187839a050SYann Gautier break; 10197839a050SYann Gautier default: 10207839a050SYann Gautier break; 10217839a050SYann Gautier } 10227839a050SYann Gautier 10237839a050SYann Gautier return clock; 10247839a050SYann Gautier } 10257839a050SYann Gautier 10260d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate) 10270d21680cSYann Gautier { 10280d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10290d21680cSYann Gautier 103025be845eSEtienne Carriere VERBOSE("Enable clock %u\n", gate->index); 103125be845eSEtienne Carriere 10320d21680cSYann Gautier if (gate->set_clr != 0U) { 10330d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); 10340d21680cSYann Gautier } else { 10350d21680cSYann Gautier mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); 10360d21680cSYann Gautier } 10370d21680cSYann Gautier } 10380d21680cSYann Gautier 10390d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate) 10400d21680cSYann Gautier { 10410d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10420d21680cSYann Gautier 104325be845eSEtienne Carriere VERBOSE("Disable clock %u\n", gate->index); 104425be845eSEtienne Carriere 10450d21680cSYann Gautier if (gate->set_clr != 0U) { 10460d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, 10470d21680cSYann Gautier BIT(gate->bit)); 10480d21680cSYann Gautier } else { 10490d21680cSYann Gautier mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); 10500d21680cSYann Gautier } 10510d21680cSYann Gautier } 10520d21680cSYann Gautier 10530d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) 10540d21680cSYann Gautier { 10550d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10560d21680cSYann Gautier 10570d21680cSYann Gautier return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); 10580d21680cSYann Gautier } 10590d21680cSYann Gautier 10600d21680cSYann Gautier unsigned int stm32mp1_clk_get_refcount(unsigned long id) 10610d21680cSYann Gautier { 10620d21680cSYann Gautier int i = stm32mp1_clk_get_gated_id(id); 10630d21680cSYann Gautier 10640d21680cSYann Gautier if (i < 0) { 10650d21680cSYann Gautier panic(); 10660d21680cSYann Gautier } 10670d21680cSYann Gautier 10680d21680cSYann Gautier return gate_refcounts[i]; 10690d21680cSYann Gautier } 10700d21680cSYann Gautier 107135848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */ 107235848200SEtienne Carriere static bool clock_is_always_on(unsigned long id) 107335848200SEtienne Carriere { 107435848200SEtienne Carriere switch (id) { 107535848200SEtienne Carriere case CK_HSE: 107635848200SEtienne Carriere case CK_CSI: 107735848200SEtienne Carriere case CK_LSI: 107835848200SEtienne Carriere case CK_LSE: 107935848200SEtienne Carriere case CK_HSI: 108035848200SEtienne Carriere case CK_HSE_DIV2: 108135848200SEtienne Carriere case PLL1_Q: 108235848200SEtienne Carriere case PLL1_R: 108335848200SEtienne Carriere case PLL2_P: 108435848200SEtienne Carriere case PLL2_Q: 108535848200SEtienne Carriere case PLL2_R: 108635848200SEtienne Carriere case PLL3_P: 108735848200SEtienne Carriere case PLL3_Q: 108835848200SEtienne Carriere case PLL3_R: 108935848200SEtienne Carriere return true; 109035848200SEtienne Carriere default: 109135848200SEtienne Carriere return false; 109235848200SEtienne Carriere } 109335848200SEtienne Carriere } 109435848200SEtienne Carriere 10950d21680cSYann Gautier void __stm32mp1_clk_enable(unsigned long id, bool secure) 10960d21680cSYann Gautier { 10970d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 109835848200SEtienne Carriere int i; 10990d21680cSYann Gautier unsigned int *refcnt; 11000d21680cSYann Gautier 110135848200SEtienne Carriere if (clock_is_always_on(id)) { 110235848200SEtienne Carriere return; 110335848200SEtienne Carriere } 110435848200SEtienne Carriere 110535848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11060d21680cSYann Gautier if (i < 0) { 11070d21680cSYann Gautier ERROR("Clock %d can't be enabled\n", (uint32_t)id); 11080d21680cSYann Gautier panic(); 11090d21680cSYann Gautier } 11100d21680cSYann Gautier 11110d21680cSYann Gautier gate = gate_ref(i); 11120d21680cSYann Gautier refcnt = &gate_refcounts[i]; 11130d21680cSYann Gautier 11140d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 11150d21680cSYann Gautier 11160d21680cSYann Gautier if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { 11170d21680cSYann Gautier __clk_enable(gate); 11180d21680cSYann Gautier } 11190d21680cSYann Gautier 11200d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 11210d21680cSYann Gautier } 11220d21680cSYann Gautier 11230d21680cSYann Gautier void __stm32mp1_clk_disable(unsigned long id, bool secure) 11240d21680cSYann Gautier { 11250d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 112635848200SEtienne Carriere int i; 11270d21680cSYann Gautier unsigned int *refcnt; 11280d21680cSYann Gautier 112935848200SEtienne Carriere if (clock_is_always_on(id)) { 113035848200SEtienne Carriere return; 113135848200SEtienne Carriere } 113235848200SEtienne Carriere 113335848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11340d21680cSYann Gautier if (i < 0) { 11350d21680cSYann Gautier ERROR("Clock %d can't be disabled\n", (uint32_t)id); 11360d21680cSYann Gautier panic(); 11370d21680cSYann Gautier } 11380d21680cSYann Gautier 11390d21680cSYann Gautier gate = gate_ref(i); 11400d21680cSYann Gautier refcnt = &gate_refcounts[i]; 11410d21680cSYann Gautier 11420d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 11430d21680cSYann Gautier 11440d21680cSYann Gautier if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { 11450d21680cSYann Gautier __clk_disable(gate); 11460d21680cSYann Gautier } 11470d21680cSYann Gautier 11480d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 11490d21680cSYann Gautier } 11500d21680cSYann Gautier 11510d21680cSYann Gautier void stm32mp_clk_enable(unsigned long id) 11520d21680cSYann Gautier { 11530d21680cSYann Gautier __stm32mp1_clk_enable(id, true); 11540d21680cSYann Gautier } 11550d21680cSYann Gautier 11560d21680cSYann Gautier void stm32mp_clk_disable(unsigned long id) 11570d21680cSYann Gautier { 11580d21680cSYann Gautier __stm32mp1_clk_disable(id, true); 11590d21680cSYann Gautier } 11600d21680cSYann Gautier 11613f9c9784SYann Gautier bool stm32mp_clk_is_enabled(unsigned long id) 11627839a050SYann Gautier { 116335848200SEtienne Carriere int i; 11647839a050SYann Gautier 116535848200SEtienne Carriere if (clock_is_always_on(id)) { 116635848200SEtienne Carriere return true; 116735848200SEtienne Carriere } 116835848200SEtienne Carriere 116935848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11707839a050SYann Gautier if (i < 0) { 11710d21680cSYann Gautier panic(); 11727839a050SYann Gautier } 11737839a050SYann Gautier 11740d21680cSYann Gautier return __clk_is_enabled(gate_ref(i)); 11757839a050SYann Gautier } 11767839a050SYann Gautier 11773f9c9784SYann Gautier unsigned long stm32mp_clk_get_rate(unsigned long id) 11787839a050SYann Gautier { 11790d21680cSYann Gautier int p = stm32mp1_clk_get_parent(id); 11807839a050SYann Gautier 11817839a050SYann Gautier if (p < 0) { 11827839a050SYann Gautier return 0; 11837839a050SYann Gautier } 11847839a050SYann Gautier 11850d21680cSYann Gautier return get_clock_rate(p); 11867839a050SYann Gautier } 11877839a050SYann Gautier 11880d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) 11897839a050SYann Gautier { 11900d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 11917839a050SYann Gautier 11920d21680cSYann Gautier if (enable) { 11937839a050SYann Gautier mmio_setbits_32(address, mask_on); 11947839a050SYann Gautier } else { 11957839a050SYann Gautier mmio_clrbits_32(address, mask_on); 11967839a050SYann Gautier } 11977839a050SYann Gautier } 11987839a050SYann Gautier 11990d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) 12007839a050SYann Gautier { 12010d21680cSYann Gautier uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; 12020d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 12030d21680cSYann Gautier 12040d21680cSYann Gautier mmio_write_32(address, mask_on); 12057839a050SYann Gautier } 12067839a050SYann Gautier 12070d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) 12087839a050SYann Gautier { 1209dfdb057aSYann Gautier uint64_t timeout; 12107839a050SYann Gautier uint32_t mask_test; 12110d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 12127839a050SYann Gautier 12130d21680cSYann Gautier if (enable) { 12147839a050SYann Gautier mask_test = mask_rdy; 12157839a050SYann Gautier } else { 12167839a050SYann Gautier mask_test = 0; 12177839a050SYann Gautier } 12187839a050SYann Gautier 1219dfdb057aSYann Gautier timeout = timeout_init_us(OSCRDY_TIMEOUT); 12207839a050SYann Gautier while ((mmio_read_32(address) & mask_rdy) != mask_test) { 1221dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 12220d21680cSYann Gautier ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", 12237839a050SYann Gautier mask_rdy, address, enable, mmio_read_32(address)); 12247839a050SYann Gautier return -ETIMEDOUT; 12257839a050SYann Gautier } 12267839a050SYann Gautier } 12277839a050SYann Gautier 12287839a050SYann Gautier return 0; 12297839a050SYann Gautier } 12307839a050SYann Gautier 12310d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) 12327839a050SYann Gautier { 12337839a050SYann Gautier uint32_t value; 12340d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 12357839a050SYann Gautier 12360d21680cSYann Gautier if (digbyp) { 12370d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); 12380d21680cSYann Gautier } 12390d21680cSYann Gautier 12400d21680cSYann Gautier if (bypass || digbyp) { 12410d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); 12427839a050SYann Gautier } 12437839a050SYann Gautier 12447839a050SYann Gautier /* 12457839a050SYann Gautier * Warning: not recommended to switch directly from "high drive" 12467839a050SYann Gautier * to "medium low drive", and vice-versa. 12477839a050SYann Gautier */ 12480d21680cSYann Gautier value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> 12497839a050SYann Gautier RCC_BDCR_LSEDRV_SHIFT; 12507839a050SYann Gautier 12517839a050SYann Gautier while (value != lsedrv) { 12527839a050SYann Gautier if (value > lsedrv) { 12537839a050SYann Gautier value--; 12547839a050SYann Gautier } else { 12557839a050SYann Gautier value++; 12567839a050SYann Gautier } 12577839a050SYann Gautier 12580d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_BDCR, 12597839a050SYann Gautier RCC_BDCR_LSEDRV_MASK, 12607839a050SYann Gautier value << RCC_BDCR_LSEDRV_SHIFT); 12617839a050SYann Gautier } 12627839a050SYann Gautier 12630d21680cSYann Gautier stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); 12647839a050SYann Gautier } 12657839a050SYann Gautier 12660d21680cSYann Gautier static void stm32mp1_lse_wait(void) 12677839a050SYann Gautier { 12680d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { 12697839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12707839a050SYann Gautier } 12717839a050SYann Gautier } 12727839a050SYann Gautier 12730d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable) 12747839a050SYann Gautier { 12750d21680cSYann Gautier stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); 12760d21680cSYann Gautier 12770d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { 12787839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12797839a050SYann Gautier } 12807839a050SYann Gautier } 12817839a050SYann Gautier 12820d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) 12837839a050SYann Gautier { 12840d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 12850d21680cSYann Gautier 12860d21680cSYann Gautier if (digbyp) { 12870d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); 12887839a050SYann Gautier } 12897839a050SYann Gautier 12900d21680cSYann Gautier if (bypass || digbyp) { 12910d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); 12920d21680cSYann Gautier } 12930d21680cSYann Gautier 12940d21680cSYann Gautier stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); 12950d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { 12967839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12977839a050SYann Gautier } 12987839a050SYann Gautier 12997839a050SYann Gautier if (css) { 13000d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); 13017839a050SYann Gautier } 13027839a050SYann Gautier } 13037839a050SYann Gautier 13040d21680cSYann Gautier static void stm32mp1_csi_set(bool enable) 13057839a050SYann Gautier { 13060d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); 13070d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { 13087839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13097839a050SYann Gautier } 13107839a050SYann Gautier } 13117839a050SYann Gautier 13120d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable) 13137839a050SYann Gautier { 13140d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); 13150d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { 13167839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13177839a050SYann Gautier } 13187839a050SYann Gautier } 13197839a050SYann Gautier 13200d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv) 13217839a050SYann Gautier { 1322dfdb057aSYann Gautier uint64_t timeout; 13230d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13240d21680cSYann Gautier uintptr_t address = rcc_base + RCC_OCRDYR; 13257839a050SYann Gautier 13260d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, 13277839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK, 13287839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); 13297839a050SYann Gautier 1330dfdb057aSYann Gautier timeout = timeout_init_us(HSIDIV_TIMEOUT); 13317839a050SYann Gautier while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { 1332dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 13330d21680cSYann Gautier ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", 13347839a050SYann Gautier address, mmio_read_32(address)); 13357839a050SYann Gautier return -ETIMEDOUT; 13367839a050SYann Gautier } 13377839a050SYann Gautier } 13387839a050SYann Gautier 13397839a050SYann Gautier return 0; 13407839a050SYann Gautier } 13417839a050SYann Gautier 13420d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq) 13437839a050SYann Gautier { 13447839a050SYann Gautier uint8_t hsidiv; 13457839a050SYann Gautier uint32_t hsidivfreq = MAX_HSI_HZ; 13467839a050SYann Gautier 13477839a050SYann Gautier for (hsidiv = 0; hsidiv < 4U; hsidiv++) { 13487839a050SYann Gautier if (hsidivfreq == hsifreq) { 13497839a050SYann Gautier break; 13507839a050SYann Gautier } 13517839a050SYann Gautier 13527839a050SYann Gautier hsidivfreq /= 2U; 13537839a050SYann Gautier } 13547839a050SYann Gautier 13557839a050SYann Gautier if (hsidiv == 4U) { 13567839a050SYann Gautier ERROR("Invalid clk-hsi frequency\n"); 13577839a050SYann Gautier return -1; 13587839a050SYann Gautier } 13597839a050SYann Gautier 13607839a050SYann Gautier if (hsidiv != 0U) { 13610d21680cSYann Gautier return stm32mp1_set_hsidiv(hsidiv); 13627839a050SYann Gautier } 13637839a050SYann Gautier 13647839a050SYann Gautier return 0; 13657839a050SYann Gautier } 13667839a050SYann Gautier 13670d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, 13680d21680cSYann Gautier unsigned int clksrc, 13690d21680cSYann Gautier uint32_t *pllcfg, int plloff) 13707839a050SYann Gautier { 13710d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 13720d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13730d21680cSYann Gautier uintptr_t pllxcr = rcc_base + pll->pllxcr; 13740d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 13750d21680cSYann Gautier uintptr_t clksrc_address = rcc_base + (clksrc >> 4); 13760d21680cSYann Gautier unsigned long refclk; 13770d21680cSYann Gautier uint32_t ifrge = 0U; 1378be858cffSAndre Przywara uint32_t src, value, fracv = 0; 1379be858cffSAndre Przywara void *fdt; 13807839a050SYann Gautier 13810d21680cSYann Gautier /* Check PLL output */ 13820d21680cSYann Gautier if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { 13830d21680cSYann Gautier return false; 13847839a050SYann Gautier } 13857839a050SYann Gautier 13860d21680cSYann Gautier /* Check current clksrc */ 13870d21680cSYann Gautier src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; 13880d21680cSYann Gautier if (src != (clksrc & RCC_SELR_SRC_MASK)) { 13890d21680cSYann Gautier return false; 13900d21680cSYann Gautier } 13910d21680cSYann Gautier 13920d21680cSYann Gautier /* Check Div */ 13930d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; 13940d21680cSYann Gautier 13950d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 13960d21680cSYann Gautier (pllcfg[PLLCFG_M] + 1U); 13970d21680cSYann Gautier 13980d21680cSYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 13990d21680cSYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 14000d21680cSYann Gautier return false; 14010d21680cSYann Gautier } 14020d21680cSYann Gautier 14030d21680cSYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 14040d21680cSYann Gautier ifrge = 1U; 14050d21680cSYann Gautier } 14060d21680cSYann Gautier 14070d21680cSYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 14080d21680cSYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 14090d21680cSYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 14100d21680cSYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 14110d21680cSYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 14120d21680cSYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 14130d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { 14140d21680cSYann Gautier return false; 14150d21680cSYann Gautier } 14160d21680cSYann Gautier 14170d21680cSYann Gautier /* Fractional configuration */ 1418be858cffSAndre Przywara if (fdt_get_address(&fdt) == 1) { 1419be858cffSAndre Przywara fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); 1420be858cffSAndre Przywara } 14210d21680cSYann Gautier 14220d21680cSYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 14230d21680cSYann Gautier value |= RCC_PLLNFRACR_FRACLE; 14240d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { 14250d21680cSYann Gautier return false; 14260d21680cSYann Gautier } 14270d21680cSYann Gautier 14280d21680cSYann Gautier /* Output config */ 14290d21680cSYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 14300d21680cSYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 14310d21680cSYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 14320d21680cSYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 14330d21680cSYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 14340d21680cSYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 14350d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { 14360d21680cSYann Gautier return false; 14370d21680cSYann Gautier } 14380d21680cSYann Gautier 14390d21680cSYann Gautier return true; 14400d21680cSYann Gautier } 14410d21680cSYann Gautier 14420d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) 14437839a050SYann Gautier { 14440d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14450d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 14460d21680cSYann Gautier 1447dd98aec8SYann Gautier /* Preserve RCC_PLLNCR_SSCG_CTRL value */ 1448dd98aec8SYann Gautier mmio_clrsetbits_32(pllxcr, 1449dd98aec8SYann Gautier RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 1450dd98aec8SYann Gautier RCC_PLLNCR_DIVREN, 1451dd98aec8SYann Gautier RCC_PLLNCR_PLLON); 14520d21680cSYann Gautier } 14530d21680cSYann Gautier 14540d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) 14550d21680cSYann Gautier { 14560d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14570d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1458dfdb057aSYann Gautier uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); 14597839a050SYann Gautier 14607839a050SYann Gautier /* Wait PLL lock */ 14617839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { 1462dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 14630d21680cSYann Gautier ERROR("PLL%d start failed @ 0x%lx: 0x%x\n", 14647839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 14657839a050SYann Gautier return -ETIMEDOUT; 14667839a050SYann Gautier } 14677839a050SYann Gautier } 14687839a050SYann Gautier 14697839a050SYann Gautier /* Start the requested output */ 14707839a050SYann Gautier mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); 14717839a050SYann Gautier 14727839a050SYann Gautier return 0; 14737839a050SYann Gautier } 14747839a050SYann Gautier 14750d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) 14767839a050SYann Gautier { 14770d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14780d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1479dfdb057aSYann Gautier uint64_t timeout; 14807839a050SYann Gautier 14817839a050SYann Gautier /* Stop all output */ 14827839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 14837839a050SYann Gautier RCC_PLLNCR_DIVREN); 14847839a050SYann Gautier 14857839a050SYann Gautier /* Stop PLL */ 14867839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); 14877839a050SYann Gautier 1488dfdb057aSYann Gautier timeout = timeout_init_us(PLLRDY_TIMEOUT); 14897839a050SYann Gautier /* Wait PLL stopped */ 14907839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { 1491dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 14920d21680cSYann Gautier ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n", 14937839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 14947839a050SYann Gautier return -ETIMEDOUT; 14957839a050SYann Gautier } 14967839a050SYann Gautier } 14977839a050SYann Gautier 14987839a050SYann Gautier return 0; 14997839a050SYann Gautier } 15007839a050SYann Gautier 15010d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, 15027839a050SYann Gautier uint32_t *pllcfg) 15037839a050SYann Gautier { 15040d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15050d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 15067839a050SYann Gautier uint32_t value; 15077839a050SYann Gautier 15087839a050SYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 15097839a050SYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 15107839a050SYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 15117839a050SYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 15127839a050SYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 15137839a050SYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 15140d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr2, value); 15157839a050SYann Gautier } 15167839a050SYann Gautier 15170d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, 15187839a050SYann Gautier uint32_t *pllcfg, uint32_t fracv) 15197839a050SYann Gautier { 15200d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15210d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 15220d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 15237839a050SYann Gautier unsigned long refclk; 15247839a050SYann Gautier uint32_t ifrge = 0; 15257839a050SYann Gautier uint32_t src, value; 15267839a050SYann Gautier 15270d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & 15287839a050SYann Gautier RCC_SELR_REFCLK_SRC_MASK; 15297839a050SYann Gautier 15300d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 15317839a050SYann Gautier (pllcfg[PLLCFG_M] + 1U); 15327839a050SYann Gautier 15337839a050SYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 15347839a050SYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 15357839a050SYann Gautier return -EINVAL; 15367839a050SYann Gautier } 15377839a050SYann Gautier 15387839a050SYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 15397839a050SYann Gautier ifrge = 1U; 15407839a050SYann Gautier } 15417839a050SYann Gautier 15427839a050SYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 15437839a050SYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 15447839a050SYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 15457839a050SYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 15467839a050SYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 15477839a050SYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 15480d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr1, value); 15497839a050SYann Gautier 15507839a050SYann Gautier /* Fractional configuration */ 15517839a050SYann Gautier value = 0; 15520d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 15537839a050SYann Gautier 15547839a050SYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 15550d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 15567839a050SYann Gautier 15577839a050SYann Gautier value |= RCC_PLLNFRACR_FRACLE; 15580d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 15597839a050SYann Gautier 15600d21680cSYann Gautier stm32mp1_pll_config_output(pll_id, pllcfg); 15617839a050SYann Gautier 15627839a050SYann Gautier return 0; 15637839a050SYann Gautier } 15647839a050SYann Gautier 15650d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) 15667839a050SYann Gautier { 15670d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15687839a050SYann Gautier uint32_t pllxcsg = 0; 15697839a050SYann Gautier 15707839a050SYann Gautier pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & 15717839a050SYann Gautier RCC_PLLNCSGR_MOD_PER_MASK; 15727839a050SYann Gautier 15737839a050SYann Gautier pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & 15747839a050SYann Gautier RCC_PLLNCSGR_INC_STEP_MASK; 15757839a050SYann Gautier 15767839a050SYann Gautier pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & 15777839a050SYann Gautier RCC_PLLNCSGR_SSCG_MODE_MASK; 15787839a050SYann Gautier 15790d21680cSYann Gautier mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); 1580dd98aec8SYann Gautier 1581dd98aec8SYann Gautier mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, 1582dd98aec8SYann Gautier RCC_PLLNCR_SSCG_CTRL); 15837839a050SYann Gautier } 15847839a050SYann Gautier 15850d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc) 15867839a050SYann Gautier { 15870d21680cSYann Gautier uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 1588dfdb057aSYann Gautier uint64_t timeout; 15897839a050SYann Gautier 15900d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, 15917839a050SYann Gautier clksrc & RCC_SELR_SRC_MASK); 15927839a050SYann Gautier 1593dfdb057aSYann Gautier timeout = timeout_init_us(CLKSRC_TIMEOUT); 15940d21680cSYann Gautier while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { 1595dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 15960d21680cSYann Gautier ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, 15970d21680cSYann Gautier clksrc_address, mmio_read_32(clksrc_address)); 15987839a050SYann Gautier return -ETIMEDOUT; 15997839a050SYann Gautier } 16007839a050SYann Gautier } 16017839a050SYann Gautier 16027839a050SYann Gautier return 0; 16037839a050SYann Gautier } 16047839a050SYann Gautier 16050d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) 16067839a050SYann Gautier { 1607dfdb057aSYann Gautier uint64_t timeout; 16087839a050SYann Gautier 16097839a050SYann Gautier mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, 16107839a050SYann Gautier clkdiv & RCC_DIVR_DIV_MASK); 16117839a050SYann Gautier 1612dfdb057aSYann Gautier timeout = timeout_init_us(CLKDIV_TIMEOUT); 16137839a050SYann Gautier while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { 1614dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 16150d21680cSYann Gautier ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", 16167839a050SYann Gautier clkdiv, address, mmio_read_32(address)); 16177839a050SYann Gautier return -ETIMEDOUT; 16187839a050SYann Gautier } 16197839a050SYann Gautier } 16207839a050SYann Gautier 16217839a050SYann Gautier return 0; 16227839a050SYann Gautier } 16237839a050SYann Gautier 16240d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) 16257839a050SYann Gautier { 16260d21680cSYann Gautier uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 16277839a050SYann Gautier 16287839a050SYann Gautier /* 16297839a050SYann Gautier * Binding clksrc : 16307839a050SYann Gautier * bit15-4 offset 16317839a050SYann Gautier * bit3: disable 16327839a050SYann Gautier * bit2-0: MCOSEL[2:0] 16337839a050SYann Gautier */ 16347839a050SYann Gautier if ((clksrc & 0x8U) != 0U) { 16350d21680cSYann Gautier mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); 16367839a050SYann Gautier } else { 16370d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, 16387839a050SYann Gautier RCC_MCOCFG_MCOSRC_MASK, 16397839a050SYann Gautier clksrc & RCC_MCOCFG_MCOSRC_MASK); 16400d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, 16417839a050SYann Gautier RCC_MCOCFG_MCODIV_MASK, 16427839a050SYann Gautier clkdiv << RCC_MCOCFG_MCODIV_SHIFT); 16430d21680cSYann Gautier mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); 16447839a050SYann Gautier } 16457839a050SYann Gautier } 16467839a050SYann Gautier 16470d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) 16487839a050SYann Gautier { 16490d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; 16507839a050SYann Gautier 16517839a050SYann Gautier if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || 16527839a050SYann Gautier (clksrc != (uint32_t)CLK_RTC_DISABLED)) { 16537839a050SYann Gautier mmio_clrsetbits_32(address, 16547839a050SYann Gautier RCC_BDCR_RTCSRC_MASK, 16557839a050SYann Gautier clksrc << RCC_BDCR_RTCSRC_SHIFT); 16567839a050SYann Gautier 16577839a050SYann Gautier mmio_setbits_32(address, RCC_BDCR_RTCCKEN); 16587839a050SYann Gautier } 16597839a050SYann Gautier 16607839a050SYann Gautier if (lse_css) { 16617839a050SYann Gautier mmio_setbits_32(address, RCC_BDCR_LSECSSON); 16627839a050SYann Gautier } 16637839a050SYann Gautier } 16647839a050SYann Gautier 16650d21680cSYann Gautier static void stm32mp1_stgen_config(void) 16667839a050SYann Gautier { 16677839a050SYann Gautier uint32_t cntfid0; 16687839a050SYann Gautier unsigned long rate; 16697839a050SYann Gautier unsigned long long counter; 16707839a050SYann Gautier 1671ade9ce03SYann Gautier cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); 16720d21680cSYann Gautier rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); 16730d21680cSYann Gautier 16740d21680cSYann Gautier if (cntfid0 == rate) { 16750d21680cSYann Gautier return; 16760d21680cSYann Gautier } 16770d21680cSYann Gautier 1678ade9ce03SYann Gautier mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 1679ade9ce03SYann Gautier counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF); 1680ade9ce03SYann Gautier counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32; 16817839a050SYann Gautier counter = (counter * rate / cntfid0); 16820d21680cSYann Gautier 1683ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); 1684ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); 1685ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); 1686ade9ce03SYann Gautier mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 16877839a050SYann Gautier 16887839a050SYann Gautier write_cntfrq((u_register_t)rate); 16897839a050SYann Gautier 16907839a050SYann Gautier /* Need to update timer with new frequency */ 16917839a050SYann Gautier generic_delay_timer_init(); 16927839a050SYann Gautier } 16937839a050SYann Gautier 16947839a050SYann Gautier void stm32mp1_stgen_increment(unsigned long long offset_in_ms) 16957839a050SYann Gautier { 16967839a050SYann Gautier unsigned long long cnt; 16977839a050SYann Gautier 1698ade9ce03SYann Gautier cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | 1699ade9ce03SYann Gautier mmio_read_32(STGEN_BASE + CNTCVL_OFF); 17007839a050SYann Gautier 1701ade9ce03SYann Gautier cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U; 17027839a050SYann Gautier 1703ade9ce03SYann Gautier mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 1704ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); 1705ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); 1706ade9ce03SYann Gautier mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 17077839a050SYann Gautier } 17087839a050SYann Gautier 17090d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs) 17107839a050SYann Gautier { 17110d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); 17127839a050SYann Gautier uint32_t value = pkcs & 0xFU; 17137839a050SYann Gautier uint32_t mask = 0xFU; 17147839a050SYann Gautier 17157839a050SYann Gautier if ((pkcs & BIT(31)) != 0U) { 17167839a050SYann Gautier mask <<= 4; 17177839a050SYann Gautier value <<= 4; 17187839a050SYann Gautier } 17197839a050SYann Gautier 17207839a050SYann Gautier mmio_clrsetbits_32(address, mask, value); 17217839a050SYann Gautier } 17227839a050SYann Gautier 17237839a050SYann Gautier int stm32mp1_clk_init(void) 17247839a050SYann Gautier { 17250d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 17267839a050SYann Gautier unsigned int clksrc[CLKSRC_NB]; 17277839a050SYann Gautier unsigned int clkdiv[CLKDIV_NB]; 17287839a050SYann Gautier unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; 17297839a050SYann Gautier int plloff[_PLL_NB]; 17307839a050SYann Gautier int ret, len; 17317839a050SYann Gautier enum stm32mp1_pll_id i; 17327839a050SYann Gautier bool lse_css = false; 17330d21680cSYann Gautier bool pll3_preserve = false; 17340d21680cSYann Gautier bool pll4_preserve = false; 17350d21680cSYann Gautier bool pll4_bootrom = false; 17363e6fab43SYann Gautier const fdt32_t *pkcs_cell; 173752a616b4SAndre Przywara void *fdt; 173852a616b4SAndre Przywara 173952a616b4SAndre Przywara if (fdt_get_address(&fdt) == 0) { 1740*8f97c4faSYann Gautier return -FDT_ERR_NOTFOUND; 174152a616b4SAndre Przywara } 17427839a050SYann Gautier 17437839a050SYann Gautier /* Check status field to disable security */ 17447839a050SYann Gautier if (!fdt_get_rcc_secure_status()) { 17450d21680cSYann Gautier mmio_write_32(rcc_base + RCC_TZCR, 0); 17467839a050SYann Gautier } 17477839a050SYann Gautier 174852a616b4SAndre Przywara ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, 174952a616b4SAndre Przywara clksrc); 17507839a050SYann Gautier if (ret < 0) { 17517839a050SYann Gautier return -FDT_ERR_NOTFOUND; 17527839a050SYann Gautier } 17537839a050SYann Gautier 175452a616b4SAndre Przywara ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, 175552a616b4SAndre Przywara clkdiv); 17567839a050SYann Gautier if (ret < 0) { 17577839a050SYann Gautier return -FDT_ERR_NOTFOUND; 17587839a050SYann Gautier } 17597839a050SYann Gautier 17607839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 17617839a050SYann Gautier char name[12]; 17627839a050SYann Gautier 176339b6cc66SAntonio Nino Diaz snprintf(name, sizeof(name), "st,pll@%d", i); 17647839a050SYann Gautier plloff[i] = fdt_rcc_subnode_offset(name); 17657839a050SYann Gautier 17667839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 17677839a050SYann Gautier continue; 17687839a050SYann Gautier } 17697839a050SYann Gautier 177052a616b4SAndre Przywara ret = fdt_read_uint32_array(fdt, plloff[i], "cfg", 177152a616b4SAndre Przywara (int)PLLCFG_NB, pllcfg[i]); 17727839a050SYann Gautier if (ret < 0) { 17737839a050SYann Gautier return -FDT_ERR_NOTFOUND; 17747839a050SYann Gautier } 17757839a050SYann Gautier } 17767839a050SYann Gautier 17770d21680cSYann Gautier stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); 17780d21680cSYann Gautier stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); 17797839a050SYann Gautier 17807839a050SYann Gautier /* 17817839a050SYann Gautier * Switch ON oscillator found in device-tree. 17827839a050SYann Gautier * Note: HSI already ON after BootROM stage. 17837839a050SYann Gautier */ 17840d21680cSYann Gautier if (stm32mp1_osc[_LSI] != 0U) { 17850d21680cSYann Gautier stm32mp1_lsi_set(true); 17867839a050SYann Gautier } 17870d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 17880d21680cSYann Gautier bool bypass, digbyp; 17897839a050SYann Gautier uint32_t lsedrv; 17907839a050SYann Gautier 17917839a050SYann Gautier bypass = fdt_osc_read_bool(_LSE, "st,bypass"); 17920d21680cSYann Gautier digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); 17937839a050SYann Gautier lse_css = fdt_osc_read_bool(_LSE, "st,css"); 17947839a050SYann Gautier lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", 17957839a050SYann Gautier LSEDRV_MEDIUM_HIGH); 17960d21680cSYann Gautier stm32mp1_lse_enable(bypass, digbyp, lsedrv); 17977839a050SYann Gautier } 17980d21680cSYann Gautier if (stm32mp1_osc[_HSE] != 0U) { 17990d21680cSYann Gautier bool bypass, digbyp, css; 18007839a050SYann Gautier 18010d21680cSYann Gautier bypass = fdt_osc_read_bool(_HSE, "st,bypass"); 18020d21680cSYann Gautier digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); 18030d21680cSYann Gautier css = fdt_osc_read_bool(_HSE, "st,css"); 18040d21680cSYann Gautier stm32mp1_hse_enable(bypass, digbyp, css); 18057839a050SYann Gautier } 18067839a050SYann Gautier /* 18077839a050SYann Gautier * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) 18087839a050SYann Gautier * => switch on CSI even if node is not present in device tree 18097839a050SYann Gautier */ 18100d21680cSYann Gautier stm32mp1_csi_set(true); 18117839a050SYann Gautier 18127839a050SYann Gautier /* Come back to HSI */ 18130d21680cSYann Gautier ret = stm32mp1_set_clksrc(CLK_MPU_HSI); 18147839a050SYann Gautier if (ret != 0) { 18157839a050SYann Gautier return ret; 18167839a050SYann Gautier } 18170d21680cSYann Gautier ret = stm32mp1_set_clksrc(CLK_AXI_HSI); 18187839a050SYann Gautier if (ret != 0) { 18197839a050SYann Gautier return ret; 18207839a050SYann Gautier } 1821b053a22eSYann Gautier ret = stm32mp1_set_clksrc(CLK_MCU_HSI); 1822b053a22eSYann Gautier if (ret != 0) { 1823b053a22eSYann Gautier return ret; 1824b053a22eSYann Gautier } 18257839a050SYann Gautier 18260d21680cSYann Gautier if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & 18270d21680cSYann Gautier RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { 18280d21680cSYann Gautier pll3_preserve = stm32mp1_check_pll_conf(_PLL3, 18290d21680cSYann Gautier clksrc[CLKSRC_PLL3], 18300d21680cSYann Gautier pllcfg[_PLL3], 18310d21680cSYann Gautier plloff[_PLL3]); 18320d21680cSYann Gautier pll4_preserve = stm32mp1_check_pll_conf(_PLL4, 18330d21680cSYann Gautier clksrc[CLKSRC_PLL4], 18340d21680cSYann Gautier pllcfg[_PLL4], 18350d21680cSYann Gautier plloff[_PLL4]); 18360d21680cSYann Gautier } 18370d21680cSYann Gautier 18387839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 18390d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 18400d21680cSYann Gautier ((i == _PLL4) && pll4_preserve)) { 18417839a050SYann Gautier continue; 18420d21680cSYann Gautier } 18430d21680cSYann Gautier 18440d21680cSYann Gautier ret = stm32mp1_pll_stop(i); 18457839a050SYann Gautier if (ret != 0) { 18467839a050SYann Gautier return ret; 18477839a050SYann Gautier } 18487839a050SYann Gautier } 18497839a050SYann Gautier 18507839a050SYann Gautier /* Configure HSIDIV */ 18510d21680cSYann Gautier if (stm32mp1_osc[_HSI] != 0U) { 18520d21680cSYann Gautier ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); 18537839a050SYann Gautier if (ret != 0) { 18547839a050SYann Gautier return ret; 18557839a050SYann Gautier } 18560d21680cSYann Gautier stm32mp1_stgen_config(); 18577839a050SYann Gautier } 18587839a050SYann Gautier 18597839a050SYann Gautier /* Select DIV */ 18607839a050SYann Gautier /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ 18610d21680cSYann Gautier mmio_write_32(rcc_base + RCC_MPCKDIVR, 18627839a050SYann Gautier clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); 18630d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); 18647839a050SYann Gautier if (ret != 0) { 18657839a050SYann Gautier return ret; 18667839a050SYann Gautier } 18670d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); 18687839a050SYann Gautier if (ret != 0) { 18697839a050SYann Gautier return ret; 18707839a050SYann Gautier } 18710d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); 18727839a050SYann Gautier if (ret != 0) { 18737839a050SYann Gautier return ret; 18747839a050SYann Gautier } 1875b053a22eSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); 1876b053a22eSYann Gautier if (ret != 0) { 1877b053a22eSYann Gautier return ret; 1878b053a22eSYann Gautier } 18790d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); 18807839a050SYann Gautier if (ret != 0) { 18817839a050SYann Gautier return ret; 18827839a050SYann Gautier } 18830d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); 18847839a050SYann Gautier if (ret != 0) { 18857839a050SYann Gautier return ret; 18867839a050SYann Gautier } 18870d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); 18887839a050SYann Gautier if (ret != 0) { 18897839a050SYann Gautier return ret; 18907839a050SYann Gautier } 18917839a050SYann Gautier 18927839a050SYann Gautier /* No ready bit for RTC */ 18930d21680cSYann Gautier mmio_write_32(rcc_base + RCC_RTCDIVR, 18947839a050SYann Gautier clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); 18957839a050SYann Gautier 18967839a050SYann Gautier /* Configure PLLs source */ 18970d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); 18987839a050SYann Gautier if (ret != 0) { 18997839a050SYann Gautier return ret; 19007839a050SYann Gautier } 19017839a050SYann Gautier 19020d21680cSYann Gautier if (!pll3_preserve) { 19030d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); 19047839a050SYann Gautier if (ret != 0) { 19057839a050SYann Gautier return ret; 19067839a050SYann Gautier } 19070d21680cSYann Gautier } 19080d21680cSYann Gautier 19090d21680cSYann Gautier if (!pll4_preserve) { 19100d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); 19110d21680cSYann Gautier if (ret != 0) { 19120d21680cSYann Gautier return ret; 19130d21680cSYann Gautier } 19140d21680cSYann Gautier } 19157839a050SYann Gautier 19167839a050SYann Gautier /* Configure and start PLLs */ 19177839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 19187839a050SYann Gautier uint32_t fracv; 19197839a050SYann Gautier uint32_t csg[PLLCSG_NB]; 19207839a050SYann Gautier 19210d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 19220d21680cSYann Gautier ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { 19230d21680cSYann Gautier continue; 19240d21680cSYann Gautier } 19250d21680cSYann Gautier 19267839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 19277839a050SYann Gautier continue; 19287839a050SYann Gautier } 19297839a050SYann Gautier 19300d21680cSYann Gautier if ((i == _PLL4) && pll4_bootrom) { 19310d21680cSYann Gautier /* Set output divider if not done by the Bootrom */ 19320d21680cSYann Gautier stm32mp1_pll_config_output(i, pllcfg[i]); 19330d21680cSYann Gautier continue; 19340d21680cSYann Gautier } 19350d21680cSYann Gautier 1936be858cffSAndre Przywara fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0); 19377839a050SYann Gautier 19380d21680cSYann Gautier ret = stm32mp1_pll_config(i, pllcfg[i], fracv); 19397839a050SYann Gautier if (ret != 0) { 19407839a050SYann Gautier return ret; 19417839a050SYann Gautier } 194252a616b4SAndre Przywara ret = fdt_read_uint32_array(fdt, plloff[i], "csg", 194352a616b4SAndre Przywara (uint32_t)PLLCSG_NB, csg); 19447839a050SYann Gautier if (ret == 0) { 19450d21680cSYann Gautier stm32mp1_pll_csg(i, csg); 19467839a050SYann Gautier } else if (ret != -FDT_ERR_NOTFOUND) { 19477839a050SYann Gautier return ret; 19487839a050SYann Gautier } 19497839a050SYann Gautier 19500d21680cSYann Gautier stm32mp1_pll_start(i); 19517839a050SYann Gautier } 19527839a050SYann Gautier /* Wait and start PLLs ouptut when ready */ 19537839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 19547839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 19557839a050SYann Gautier continue; 19567839a050SYann Gautier } 19577839a050SYann Gautier 19580d21680cSYann Gautier ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); 19597839a050SYann Gautier if (ret != 0) { 19607839a050SYann Gautier return ret; 19617839a050SYann Gautier } 19627839a050SYann Gautier } 19637839a050SYann Gautier /* Wait LSE ready before to use it */ 19640d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 19650d21680cSYann Gautier stm32mp1_lse_wait(); 19667839a050SYann Gautier } 19677839a050SYann Gautier 19687839a050SYann Gautier /* Configure with expected clock source */ 19690d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); 19707839a050SYann Gautier if (ret != 0) { 19717839a050SYann Gautier return ret; 19727839a050SYann Gautier } 19730d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); 19747839a050SYann Gautier if (ret != 0) { 19757839a050SYann Gautier return ret; 19767839a050SYann Gautier } 1977b053a22eSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); 1978b053a22eSYann Gautier if (ret != 0) { 1979b053a22eSYann Gautier return ret; 1980b053a22eSYann Gautier } 19810d21680cSYann Gautier stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); 19827839a050SYann Gautier 19837839a050SYann Gautier /* Configure PKCK */ 19847839a050SYann Gautier pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); 19857839a050SYann Gautier if (pkcs_cell != NULL) { 19867839a050SYann Gautier bool ckper_disabled = false; 19877839a050SYann Gautier uint32_t j; 19887839a050SYann Gautier 19897839a050SYann Gautier for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { 19903e6fab43SYann Gautier uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); 19917839a050SYann Gautier 19927839a050SYann Gautier if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { 19937839a050SYann Gautier ckper_disabled = true; 19947839a050SYann Gautier continue; 19957839a050SYann Gautier } 19960d21680cSYann Gautier stm32mp1_pkcs_config(pkcs); 19977839a050SYann Gautier } 19987839a050SYann Gautier 19997839a050SYann Gautier /* 20007839a050SYann Gautier * CKPER is source for some peripheral clocks 20017839a050SYann Gautier * (FMC-NAND / QPSI-NOR) and switching source is allowed 20027839a050SYann Gautier * only if previous clock is still ON 20037839a050SYann Gautier * => deactivated CKPER only after switching clock 20047839a050SYann Gautier */ 20057839a050SYann Gautier if (ckper_disabled) { 20060d21680cSYann Gautier stm32mp1_pkcs_config(CLK_CKPER_DISABLED); 20077839a050SYann Gautier } 20087839a050SYann Gautier } 20097839a050SYann Gautier 20107839a050SYann Gautier /* Switch OFF HSI if not found in device-tree */ 20110d21680cSYann Gautier if (stm32mp1_osc[_HSI] == 0U) { 20120d21680cSYann Gautier stm32mp1_hsi_set(false); 20137839a050SYann Gautier } 20140d21680cSYann Gautier stm32mp1_stgen_config(); 20157839a050SYann Gautier 20167839a050SYann Gautier /* Software Self-Refresh mode (SSR) during DDR initilialization */ 20170d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, 20187839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_MASK, 20197839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SSR << 20207839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SHIFT); 20217839a050SYann Gautier 20227839a050SYann Gautier return 0; 20237839a050SYann Gautier } 20247839a050SYann Gautier 20257839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name, 20267839a050SYann Gautier enum stm32mp_osc_id index) 20277839a050SYann Gautier { 20287839a050SYann Gautier uint32_t frequency; 20297839a050SYann Gautier 20300d21680cSYann Gautier if (fdt_osc_read_freq(name, &frequency) == 0) { 20310d21680cSYann Gautier stm32mp1_osc[index] = frequency; 20327839a050SYann Gautier } 20337839a050SYann Gautier } 20347839a050SYann Gautier 20357839a050SYann Gautier static void stm32mp1_osc_init(void) 20367839a050SYann Gautier { 20377839a050SYann Gautier enum stm32mp_osc_id i; 20387839a050SYann Gautier 20397839a050SYann Gautier for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { 20400d21680cSYann Gautier stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); 20417839a050SYann Gautier } 20427839a050SYann Gautier } 20437839a050SYann Gautier 204437e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES 204537e8295aSEtienne Carriere /* 204637e8295aSEtienne Carriere * Get the parent ID of the target parent clock, for tagging as secure 204737e8295aSEtienne Carriere * shared clock dependencies. 204837e8295aSEtienne Carriere */ 204937e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id) 205037e8295aSEtienne Carriere { 205137e8295aSEtienne Carriere enum stm32mp1_parent_sel s = _UNKNOWN_SEL; 205237e8295aSEtienne Carriere enum stm32mp1_pll_id pll_id; 205337e8295aSEtienne Carriere uint32_t p_sel; 205437e8295aSEtienne Carriere uintptr_t rcc_base = stm32mp_rcc_base(); 205537e8295aSEtienne Carriere 205637e8295aSEtienne Carriere switch (parent_id) { 205737e8295aSEtienne Carriere case _ACLK: 205837e8295aSEtienne Carriere case _PCLK4: 205937e8295aSEtienne Carriere case _PCLK5: 206037e8295aSEtienne Carriere s = _AXIS_SEL; 206137e8295aSEtienne Carriere break; 206237e8295aSEtienne Carriere case _PLL1_P: 206337e8295aSEtienne Carriere case _PLL1_Q: 206437e8295aSEtienne Carriere case _PLL1_R: 206537e8295aSEtienne Carriere pll_id = _PLL1; 206637e8295aSEtienne Carriere break; 206737e8295aSEtienne Carriere case _PLL2_P: 206837e8295aSEtienne Carriere case _PLL2_Q: 206937e8295aSEtienne Carriere case _PLL2_R: 207037e8295aSEtienne Carriere pll_id = _PLL2; 207137e8295aSEtienne Carriere break; 207237e8295aSEtienne Carriere case _PLL3_P: 207337e8295aSEtienne Carriere case _PLL3_Q: 207437e8295aSEtienne Carriere case _PLL3_R: 207537e8295aSEtienne Carriere pll_id = _PLL3; 207637e8295aSEtienne Carriere break; 207737e8295aSEtienne Carriere case _PLL4_P: 207837e8295aSEtienne Carriere case _PLL4_Q: 207937e8295aSEtienne Carriere case _PLL4_R: 208037e8295aSEtienne Carriere pll_id = _PLL4; 208137e8295aSEtienne Carriere break; 208237e8295aSEtienne Carriere case _PCLK1: 208337e8295aSEtienne Carriere case _PCLK2: 208437e8295aSEtienne Carriere case _HCLK2: 208537e8295aSEtienne Carriere case _HCLK6: 208637e8295aSEtienne Carriere case _CK_PER: 208737e8295aSEtienne Carriere case _CK_MPU: 208837e8295aSEtienne Carriere case _CK_MCU: 208937e8295aSEtienne Carriere case _USB_PHY_48: 209037e8295aSEtienne Carriere /* We do not expect to access these */ 209137e8295aSEtienne Carriere panic(); 209237e8295aSEtienne Carriere break; 209337e8295aSEtienne Carriere default: 209437e8295aSEtienne Carriere /* Other parents have no parent */ 209537e8295aSEtienne Carriere return -1; 209637e8295aSEtienne Carriere } 209737e8295aSEtienne Carriere 209837e8295aSEtienne Carriere if (s != _UNKNOWN_SEL) { 209937e8295aSEtienne Carriere const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); 210037e8295aSEtienne Carriere 210137e8295aSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & 210237e8295aSEtienne Carriere sel->msk; 210337e8295aSEtienne Carriere 210437e8295aSEtienne Carriere if (p_sel < sel->nb_parent) { 210537e8295aSEtienne Carriere return (int)sel->parent[p_sel]; 210637e8295aSEtienne Carriere } 210737e8295aSEtienne Carriere } else { 210837e8295aSEtienne Carriere const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 210937e8295aSEtienne Carriere 211037e8295aSEtienne Carriere p_sel = mmio_read_32(rcc_base + pll->rckxselr) & 211137e8295aSEtienne Carriere RCC_SELR_REFCLK_SRC_MASK; 211237e8295aSEtienne Carriere 211337e8295aSEtienne Carriere if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { 211437e8295aSEtienne Carriere return (int)pll->refclk[p_sel]; 211537e8295aSEtienne Carriere } 211637e8295aSEtienne Carriere } 211737e8295aSEtienne Carriere 211837e8295aSEtienne Carriere VERBOSE("No parent selected for %s\n", 211937e8295aSEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 212037e8295aSEtienne Carriere 212137e8295aSEtienne Carriere return -1; 212237e8295aSEtienne Carriere } 212337e8295aSEtienne Carriere 212437e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id) 212537e8295aSEtienne Carriere { 212637e8295aSEtienne Carriere int grandparent_id; 212737e8295aSEtienne Carriere 212837e8295aSEtienne Carriere switch (parent_id) { 212937e8295aSEtienne Carriere case _PLL3_P: 213037e8295aSEtienne Carriere case _PLL3_Q: 213137e8295aSEtienne Carriere case _PLL3_R: 213237e8295aSEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 213337e8295aSEtienne Carriere break; 213437e8295aSEtienne Carriere 213537e8295aSEtienne Carriere /* These clocks are always secure when RCC is secure */ 213637e8295aSEtienne Carriere case _ACLK: 213737e8295aSEtienne Carriere case _HCLK2: 213837e8295aSEtienne Carriere case _HCLK6: 213937e8295aSEtienne Carriere case _PCLK4: 214037e8295aSEtienne Carriere case _PCLK5: 214137e8295aSEtienne Carriere case _PLL1_P: 214237e8295aSEtienne Carriere case _PLL1_Q: 214337e8295aSEtienne Carriere case _PLL1_R: 214437e8295aSEtienne Carriere case _PLL2_P: 214537e8295aSEtienne Carriere case _PLL2_Q: 214637e8295aSEtienne Carriere case _PLL2_R: 214737e8295aSEtienne Carriere case _HSI: 214837e8295aSEtienne Carriere case _HSI_KER: 214937e8295aSEtienne Carriere case _LSI: 215037e8295aSEtienne Carriere case _CSI: 215137e8295aSEtienne Carriere case _CSI_KER: 215237e8295aSEtienne Carriere case _HSE: 215337e8295aSEtienne Carriere case _HSE_KER: 215437e8295aSEtienne Carriere case _HSE_KER_DIV2: 215537e8295aSEtienne Carriere case _LSE: 215637e8295aSEtienne Carriere break; 215737e8295aSEtienne Carriere 215837e8295aSEtienne Carriere default: 215937e8295aSEtienne Carriere VERBOSE("Cannot secure parent clock %s\n", 216037e8295aSEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 216137e8295aSEtienne Carriere panic(); 216237e8295aSEtienne Carriere } 216337e8295aSEtienne Carriere 216437e8295aSEtienne Carriere grandparent_id = get_parent_id_parent(parent_id); 216537e8295aSEtienne Carriere if (grandparent_id >= 0) { 216637e8295aSEtienne Carriere secure_parent_clocks(grandparent_id); 216737e8295aSEtienne Carriere } 216837e8295aSEtienne Carriere } 216937e8295aSEtienne Carriere 217037e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id) 217137e8295aSEtienne Carriere { 217237e8295aSEtienne Carriere int parent_id; 217337e8295aSEtienne Carriere 217437e8295aSEtienne Carriere if (!stm32mp1_rcc_is_secure()) { 217537e8295aSEtienne Carriere return; 217637e8295aSEtienne Carriere } 217737e8295aSEtienne Carriere 217837e8295aSEtienne Carriere switch (clock_id) { 217937e8295aSEtienne Carriere case PLL1: 218037e8295aSEtienne Carriere case PLL2: 218137e8295aSEtienne Carriere /* PLL1/PLL2 are always secure: nothing to do */ 218237e8295aSEtienne Carriere break; 218337e8295aSEtienne Carriere case PLL3: 218437e8295aSEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 218537e8295aSEtienne Carriere break; 218637e8295aSEtienne Carriere case PLL4: 218737e8295aSEtienne Carriere ERROR("PLL4 cannot be secured\n"); 218837e8295aSEtienne Carriere panic(); 218937e8295aSEtienne Carriere break; 219037e8295aSEtienne Carriere default: 219137e8295aSEtienne Carriere /* Others are expected gateable clock */ 219237e8295aSEtienne Carriere parent_id = stm32mp1_clk_get_parent(clock_id); 219337e8295aSEtienne Carriere if (parent_id < 0) { 219437e8295aSEtienne Carriere INFO("No parent found for clock %lu\n", clock_id); 219537e8295aSEtienne Carriere } else { 219637e8295aSEtienne Carriere secure_parent_clocks(parent_id); 219737e8295aSEtienne Carriere } 219837e8295aSEtienne Carriere break; 219937e8295aSEtienne Carriere } 220037e8295aSEtienne Carriere } 220137e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */ 220237e8295aSEtienne Carriere 22036cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void) 22046cb45f89SYann Gautier { 2205033b6c3aSEtienne Carriere unsigned int idx; 2206033b6c3aSEtienne Carriere const unsigned long secure_enable[] = { 2207033b6c3aSEtienne Carriere AXIDCG, 2208033b6c3aSEtienne Carriere BSEC, 2209033b6c3aSEtienne Carriere DDRC1, DDRC1LP, 2210033b6c3aSEtienne Carriere DDRC2, DDRC2LP, 2211033b6c3aSEtienne Carriere DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, 2212033b6c3aSEtienne Carriere DDRPHYC, DDRPHYCLP, 2213033b6c3aSEtienne Carriere TZC1, TZC2, 2214033b6c3aSEtienne Carriere TZPC, 2215033b6c3aSEtienne Carriere STGEN_K, 2216033b6c3aSEtienne Carriere }; 2217033b6c3aSEtienne Carriere 2218033b6c3aSEtienne Carriere for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { 2219033b6c3aSEtienne Carriere stm32mp_clk_enable(secure_enable[idx]); 2220033b6c3aSEtienne Carriere } 2221033b6c3aSEtienne Carriere 22226cb45f89SYann Gautier if (!stm32mp_is_single_core()) { 22236cb45f89SYann Gautier stm32mp1_clk_enable_secure(RTCAPB); 22246cb45f89SYann Gautier } 22256cb45f89SYann Gautier } 22266cb45f89SYann Gautier 22277839a050SYann Gautier int stm32mp1_clk_probe(void) 22287839a050SYann Gautier { 22297839a050SYann Gautier stm32mp1_osc_init(); 22307839a050SYann Gautier 22316cb45f89SYann Gautier sync_earlyboot_clocks_state(); 22326cb45f89SYann Gautier 22337839a050SYann Gautier return 0; 22347839a050SYann Gautier } 2235