17839a050SYann Gautier /* 28f97c4faSYann 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> 20*33667d29SYann Gautier #include <drivers/clk.h> 2109d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 2209d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h> 23447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h> 2409d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h> 2509d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h> 2609d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h> 2709d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 280d21680cSYann Gautier #include <lib/spinlock.h> 2909d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 3009d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 3109d40e0eSAntonio Nino Diaz 327839a050SYann Gautier #define MAX_HSI_HZ 64000000 330d21680cSYann Gautier #define USB_PHY_48_MHZ 48000000 347839a050SYann Gautier 35dfdb057aSYann Gautier #define TIMEOUT_US_200MS U(200000) 36dfdb057aSYann Gautier #define TIMEOUT_US_1S U(1000000) 377839a050SYann Gautier 38dfdb057aSYann Gautier #define PLLRDY_TIMEOUT TIMEOUT_US_200MS 39dfdb057aSYann Gautier #define CLKSRC_TIMEOUT TIMEOUT_US_200MS 40dfdb057aSYann Gautier #define CLKDIV_TIMEOUT TIMEOUT_US_200MS 41dfdb057aSYann Gautier #define HSIDIV_TIMEOUT TIMEOUT_US_200MS 42dfdb057aSYann Gautier #define OSCRDY_TIMEOUT TIMEOUT_US_1S 437839a050SYann Gautier 44f66358afSYann Gautier const char *stm32mp_osc_node_label[NB_OSC] = { 45f66358afSYann Gautier [_LSI] = "clk-lsi", 46f66358afSYann Gautier [_LSE] = "clk-lse", 47f66358afSYann Gautier [_HSI] = "clk-hsi", 48f66358afSYann Gautier [_HSE] = "clk-hse", 49f66358afSYann Gautier [_CSI] = "clk-csi", 50f66358afSYann Gautier [_I2S_CKIN] = "i2s_ckin", 51f66358afSYann Gautier }; 52f66358afSYann Gautier 537839a050SYann Gautier enum stm32mp1_parent_id { 547839a050SYann Gautier /* Oscillators are defined in enum stm32mp_osc_id */ 557839a050SYann Gautier 567839a050SYann Gautier /* Other parent source */ 577839a050SYann Gautier _HSI_KER = NB_OSC, 587839a050SYann Gautier _HSE_KER, 597839a050SYann Gautier _HSE_KER_DIV2, 60cbd2e8a6SGabriel Fernandez _HSE_RTC, 617839a050SYann Gautier _CSI_KER, 627839a050SYann Gautier _PLL1_P, 637839a050SYann Gautier _PLL1_Q, 647839a050SYann Gautier _PLL1_R, 657839a050SYann Gautier _PLL2_P, 667839a050SYann Gautier _PLL2_Q, 677839a050SYann Gautier _PLL2_R, 687839a050SYann Gautier _PLL3_P, 697839a050SYann Gautier _PLL3_Q, 707839a050SYann Gautier _PLL3_R, 717839a050SYann Gautier _PLL4_P, 727839a050SYann Gautier _PLL4_Q, 737839a050SYann Gautier _PLL4_R, 747839a050SYann Gautier _ACLK, 757839a050SYann Gautier _PCLK1, 767839a050SYann Gautier _PCLK2, 777839a050SYann Gautier _PCLK3, 787839a050SYann Gautier _PCLK4, 797839a050SYann Gautier _PCLK5, 807839a050SYann Gautier _HCLK6, 817839a050SYann Gautier _HCLK2, 827839a050SYann Gautier _CK_PER, 837839a050SYann Gautier _CK_MPU, 84b053a22eSYann Gautier _CK_MCU, 850d21680cSYann Gautier _USB_PHY_48, 867839a050SYann Gautier _PARENT_NB, 877839a050SYann Gautier _UNKNOWN_ID = 0xff, 887839a050SYann Gautier }; 897839a050SYann Gautier 900d21680cSYann Gautier /* Lists only the parent clock we are interested in */ 917839a050SYann Gautier enum stm32mp1_parent_sel { 920d21680cSYann Gautier _I2C12_SEL, 930d21680cSYann Gautier _I2C35_SEL, 940d21680cSYann Gautier _STGEN_SEL, 957839a050SYann Gautier _I2C46_SEL, 960d21680cSYann Gautier _SPI6_SEL, 97d4151d2fSYann Gautier _UART1_SEL, 980d21680cSYann Gautier _RNG1_SEL, 997839a050SYann Gautier _UART6_SEL, 1007839a050SYann Gautier _UART24_SEL, 1017839a050SYann Gautier _UART35_SEL, 1027839a050SYann Gautier _UART78_SEL, 1037839a050SYann Gautier _SDMMC12_SEL, 1047839a050SYann Gautier _SDMMC3_SEL, 1057839a050SYann Gautier _QSPI_SEL, 1067839a050SYann Gautier _FMC_SEL, 107d4151d2fSYann Gautier _AXIS_SEL, 108d4151d2fSYann Gautier _MCUS_SEL, 1097839a050SYann Gautier _USBPHY_SEL, 1107839a050SYann Gautier _USBO_SEL, 1118fbcd9e4SEtienne Carriere _MPU_SEL, 112288f5cf2SYann Gautier _CKPER_SEL, 113016af006SEtienne Carriere _RTC_SEL, 1147839a050SYann Gautier _PARENT_SEL_NB, 1157839a050SYann Gautier _UNKNOWN_SEL = 0xff, 1167839a050SYann Gautier }; 1177839a050SYann Gautier 1188fbcd9e4SEtienne Carriere /* State the parent clock ID straight related to a clock */ 1198fbcd9e4SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = { 1208fbcd9e4SEtienne Carriere [_HSE] = CK_HSE, 1218fbcd9e4SEtienne Carriere [_HSI] = CK_HSI, 1228fbcd9e4SEtienne Carriere [_CSI] = CK_CSI, 1238fbcd9e4SEtienne Carriere [_LSE] = CK_LSE, 1248fbcd9e4SEtienne Carriere [_LSI] = CK_LSI, 1258fbcd9e4SEtienne Carriere [_I2S_CKIN] = _UNKNOWN_ID, 1268fbcd9e4SEtienne Carriere [_USB_PHY_48] = _UNKNOWN_ID, 1278fbcd9e4SEtienne Carriere [_HSI_KER] = CK_HSI, 1288fbcd9e4SEtienne Carriere [_HSE_KER] = CK_HSE, 1298fbcd9e4SEtienne Carriere [_HSE_KER_DIV2] = CK_HSE_DIV2, 130cbd2e8a6SGabriel Fernandez [_HSE_RTC] = _UNKNOWN_ID, 1318fbcd9e4SEtienne Carriere [_CSI_KER] = CK_CSI, 1328fbcd9e4SEtienne Carriere [_PLL1_P] = PLL1_P, 1338fbcd9e4SEtienne Carriere [_PLL1_Q] = PLL1_Q, 1348fbcd9e4SEtienne Carriere [_PLL1_R] = PLL1_R, 1358fbcd9e4SEtienne Carriere [_PLL2_P] = PLL2_P, 1368fbcd9e4SEtienne Carriere [_PLL2_Q] = PLL2_Q, 1378fbcd9e4SEtienne Carriere [_PLL2_R] = PLL2_R, 1388fbcd9e4SEtienne Carriere [_PLL3_P] = PLL3_P, 1398fbcd9e4SEtienne Carriere [_PLL3_Q] = PLL3_Q, 1408fbcd9e4SEtienne Carriere [_PLL3_R] = PLL3_R, 1418fbcd9e4SEtienne Carriere [_PLL4_P] = PLL4_P, 1428fbcd9e4SEtienne Carriere [_PLL4_Q] = PLL4_Q, 1438fbcd9e4SEtienne Carriere [_PLL4_R] = PLL4_R, 1448fbcd9e4SEtienne Carriere [_ACLK] = CK_AXI, 1458fbcd9e4SEtienne Carriere [_PCLK1] = CK_AXI, 1468fbcd9e4SEtienne Carriere [_PCLK2] = CK_AXI, 1478fbcd9e4SEtienne Carriere [_PCLK3] = CK_AXI, 1488fbcd9e4SEtienne Carriere [_PCLK4] = CK_AXI, 1498fbcd9e4SEtienne Carriere [_PCLK5] = CK_AXI, 1508fbcd9e4SEtienne Carriere [_CK_PER] = CK_PER, 1518fbcd9e4SEtienne Carriere [_CK_MPU] = CK_MPU, 1528fbcd9e4SEtienne Carriere [_CK_MCU] = CK_MCU, 1538fbcd9e4SEtienne Carriere }; 1548fbcd9e4SEtienne Carriere 1558fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id) 1568fbcd9e4SEtienne Carriere { 1578fbcd9e4SEtienne Carriere unsigned int n; 1588fbcd9e4SEtienne Carriere 1598fbcd9e4SEtienne Carriere for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { 1608fbcd9e4SEtienne Carriere if (parent_id_clock_id[n] == id) { 1618fbcd9e4SEtienne Carriere return n; 1628fbcd9e4SEtienne Carriere } 1638fbcd9e4SEtienne Carriere } 1648fbcd9e4SEtienne Carriere 1658fbcd9e4SEtienne Carriere return _UNKNOWN_ID; 1668fbcd9e4SEtienne Carriere } 1678fbcd9e4SEtienne Carriere 1687839a050SYann Gautier enum stm32mp1_pll_id { 1697839a050SYann Gautier _PLL1, 1707839a050SYann Gautier _PLL2, 1717839a050SYann Gautier _PLL3, 1727839a050SYann Gautier _PLL4, 1737839a050SYann Gautier _PLL_NB 1747839a050SYann Gautier }; 1757839a050SYann Gautier 1767839a050SYann Gautier enum stm32mp1_div_id { 1777839a050SYann Gautier _DIV_P, 1787839a050SYann Gautier _DIV_Q, 1797839a050SYann Gautier _DIV_R, 1807839a050SYann Gautier _DIV_NB, 1817839a050SYann Gautier }; 1827839a050SYann Gautier 1837839a050SYann Gautier enum stm32mp1_clksrc_id { 1847839a050SYann Gautier CLKSRC_MPU, 1857839a050SYann Gautier CLKSRC_AXI, 186b053a22eSYann Gautier CLKSRC_MCU, 1877839a050SYann Gautier CLKSRC_PLL12, 1887839a050SYann Gautier CLKSRC_PLL3, 1897839a050SYann Gautier CLKSRC_PLL4, 1907839a050SYann Gautier CLKSRC_RTC, 1917839a050SYann Gautier CLKSRC_MCO1, 1927839a050SYann Gautier CLKSRC_MCO2, 1937839a050SYann Gautier CLKSRC_NB 1947839a050SYann Gautier }; 1957839a050SYann Gautier 1967839a050SYann Gautier enum stm32mp1_clkdiv_id { 1977839a050SYann Gautier CLKDIV_MPU, 1987839a050SYann Gautier CLKDIV_AXI, 199b053a22eSYann Gautier CLKDIV_MCU, 2007839a050SYann Gautier CLKDIV_APB1, 2017839a050SYann Gautier CLKDIV_APB2, 2027839a050SYann Gautier CLKDIV_APB3, 2037839a050SYann Gautier CLKDIV_APB4, 2047839a050SYann Gautier CLKDIV_APB5, 2057839a050SYann Gautier CLKDIV_RTC, 2067839a050SYann Gautier CLKDIV_MCO1, 2077839a050SYann Gautier CLKDIV_MCO2, 2087839a050SYann Gautier CLKDIV_NB 2097839a050SYann Gautier }; 2107839a050SYann Gautier 2117839a050SYann Gautier enum stm32mp1_pllcfg { 2127839a050SYann Gautier PLLCFG_M, 2137839a050SYann Gautier PLLCFG_N, 2147839a050SYann Gautier PLLCFG_P, 2157839a050SYann Gautier PLLCFG_Q, 2167839a050SYann Gautier PLLCFG_R, 2177839a050SYann Gautier PLLCFG_O, 2187839a050SYann Gautier PLLCFG_NB 2197839a050SYann Gautier }; 2207839a050SYann Gautier 2217839a050SYann Gautier enum stm32mp1_pllcsg { 2227839a050SYann Gautier PLLCSG_MOD_PER, 2237839a050SYann Gautier PLLCSG_INC_STEP, 2247839a050SYann Gautier PLLCSG_SSCG_MODE, 2257839a050SYann Gautier PLLCSG_NB 2267839a050SYann Gautier }; 2277839a050SYann Gautier 2287839a050SYann Gautier enum stm32mp1_plltype { 2297839a050SYann Gautier PLL_800, 2307839a050SYann Gautier PLL_1600, 2317839a050SYann Gautier PLL_TYPE_NB 2327839a050SYann Gautier }; 2337839a050SYann Gautier 2347839a050SYann Gautier struct stm32mp1_pll { 2357839a050SYann Gautier uint8_t refclk_min; 2367839a050SYann Gautier uint8_t refclk_max; 2377839a050SYann Gautier uint8_t divn_max; 2387839a050SYann Gautier }; 2397839a050SYann Gautier 2407839a050SYann Gautier struct stm32mp1_clk_gate { 2417839a050SYann Gautier uint16_t offset; 2427839a050SYann Gautier uint8_t bit; 2437839a050SYann Gautier uint8_t index; 2447839a050SYann Gautier uint8_t set_clr; 2450d21680cSYann Gautier uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ 2460d21680cSYann Gautier uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ 2477839a050SYann Gautier }; 2487839a050SYann Gautier 2497839a050SYann Gautier struct stm32mp1_clk_sel { 2507839a050SYann Gautier uint16_t offset; 2517839a050SYann Gautier uint8_t src; 2527839a050SYann Gautier uint8_t msk; 2537839a050SYann Gautier uint8_t nb_parent; 2547839a050SYann Gautier const uint8_t *parent; 2557839a050SYann Gautier }; 2567839a050SYann Gautier 2577839a050SYann Gautier #define REFCLK_SIZE 4 2587839a050SYann Gautier struct stm32mp1_clk_pll { 2597839a050SYann Gautier enum stm32mp1_plltype plltype; 2607839a050SYann Gautier uint16_t rckxselr; 2617839a050SYann Gautier uint16_t pllxcfgr1; 2627839a050SYann Gautier uint16_t pllxcfgr2; 2637839a050SYann Gautier uint16_t pllxfracr; 2647839a050SYann Gautier uint16_t pllxcr; 2657839a050SYann Gautier uint16_t pllxcsgr; 2667839a050SYann Gautier enum stm32mp_osc_id refclk[REFCLK_SIZE]; 2677839a050SYann Gautier }; 2687839a050SYann Gautier 2690d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */ 2700d21680cSYann Gautier #define _CLK_SELEC(off, b, idx, s) \ 2717839a050SYann Gautier { \ 2727839a050SYann Gautier .offset = (off), \ 2737839a050SYann Gautier .bit = (b), \ 2747839a050SYann Gautier .index = (idx), \ 2757839a050SYann Gautier .set_clr = 0, \ 2767839a050SYann Gautier .sel = (s), \ 2777839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 2787839a050SYann Gautier } 2797839a050SYann Gautier 2800d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */ 2810d21680cSYann Gautier #define _CLK_FIXED(off, b, idx, f) \ 2827839a050SYann Gautier { \ 2837839a050SYann Gautier .offset = (off), \ 2847839a050SYann Gautier .bit = (b), \ 2857839a050SYann Gautier .index = (idx), \ 2867839a050SYann Gautier .set_clr = 0, \ 2877839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 2887839a050SYann Gautier .fixed = (f), \ 2897839a050SYann Gautier } 2907839a050SYann Gautier 2910d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */ 2920d21680cSYann Gautier #define _CLK_SC_SELEC(off, b, idx, s) \ 2937839a050SYann Gautier { \ 2947839a050SYann Gautier .offset = (off), \ 2957839a050SYann Gautier .bit = (b), \ 2967839a050SYann Gautier .index = (idx), \ 2977839a050SYann Gautier .set_clr = 1, \ 2987839a050SYann Gautier .sel = (s), \ 2997839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 3007839a050SYann Gautier } 3017839a050SYann Gautier 3020d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */ 3030d21680cSYann Gautier #define _CLK_SC_FIXED(off, b, idx, f) \ 3047839a050SYann Gautier { \ 3057839a050SYann Gautier .offset = (off), \ 3067839a050SYann Gautier .bit = (b), \ 3077839a050SYann Gautier .index = (idx), \ 3087839a050SYann Gautier .set_clr = 1, \ 3097839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 3107839a050SYann Gautier .fixed = (f), \ 3117839a050SYann Gautier } 3127839a050SYann Gautier 313d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ 314d4151d2fSYann Gautier [_ ## _label ## _SEL] = { \ 315d4151d2fSYann Gautier .offset = _rcc_selr, \ 316d4151d2fSYann Gautier .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ 3178ae08dcdSEtienne Carriere .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ 3188ae08dcdSEtienne Carriere (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ 319d4151d2fSYann Gautier .parent = (_parents), \ 320d4151d2fSYann Gautier .nb_parent = ARRAY_SIZE(_parents) \ 3217839a050SYann Gautier } 3227839a050SYann Gautier 3230d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3, \ 3247839a050SYann Gautier off4, off5, off6, \ 3257839a050SYann Gautier p1, p2, p3, p4) \ 3267839a050SYann Gautier [(idx)] = { \ 3277839a050SYann Gautier .plltype = (type), \ 3287839a050SYann Gautier .rckxselr = (off1), \ 3297839a050SYann Gautier .pllxcfgr1 = (off2), \ 3307839a050SYann Gautier .pllxcfgr2 = (off3), \ 3317839a050SYann Gautier .pllxfracr = (off4), \ 3327839a050SYann Gautier .pllxcr = (off5), \ 3337839a050SYann Gautier .pllxcsgr = (off6), \ 3347839a050SYann Gautier .refclk[0] = (p1), \ 3357839a050SYann Gautier .refclk[1] = (p2), \ 3367839a050SYann Gautier .refclk[2] = (p3), \ 3377839a050SYann Gautier .refclk[3] = (p4), \ 3387839a050SYann Gautier } 3397839a050SYann Gautier 3400d21680cSYann Gautier #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) 3410d21680cSYann Gautier 3427839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { 3430d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), 3440d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), 3450d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), 3460d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), 3470d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), 3480d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), 3490d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), 3500d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), 3510d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), 3520d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), 3530d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), 3547839a050SYann Gautier 3550d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), 3560d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), 3570d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), 3580d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), 3590d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), 3600d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), 3610d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), 3620d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), 3630d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), 3640d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), 3650d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), 3667839a050SYann Gautier 3670d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), 3680d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), 3697839a050SYann Gautier 370f33b2433SYann Gautier _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), 371f33b2433SYann Gautier 3720d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), 3730d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), 3740d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), 3757839a050SYann Gautier 3760d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), 3770d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), 3780d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), 379d4151d2fSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), 3800d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), 3810d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), 3820d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), 3830d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), 3840d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), 3850d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), 3860d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), 3877839a050SYann Gautier 3880d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), 3890d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), 3907839a050SYann Gautier 3910d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), 3920d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), 3930d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), 3940d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), 3950d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), 3960d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), 3970d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), 3980d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), 3990d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), 4000d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), 4010d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), 4027839a050SYann Gautier 4030d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), 4040d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), 4050d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), 4060d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), 4070d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), 4087839a050SYann Gautier 4090d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), 4100d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), 4110d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), 4120d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), 4130d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), 4147839a050SYann Gautier 415016af006SEtienne Carriere _CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL), 4160d21680cSYann Gautier _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), 4177839a050SYann Gautier }; 4187839a050SYann Gautier 4190d21680cSYann Gautier static const uint8_t i2c12_parents[] = { 4200d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 4210d21680cSYann Gautier }; 4220d21680cSYann Gautier 4230d21680cSYann Gautier static const uint8_t i2c35_parents[] = { 4240d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 4250d21680cSYann Gautier }; 4260d21680cSYann Gautier 4270d21680cSYann Gautier static const uint8_t stgen_parents[] = { 4280d21680cSYann Gautier _HSI_KER, _HSE_KER 4290d21680cSYann Gautier }; 4300d21680cSYann Gautier 4310d21680cSYann Gautier static const uint8_t i2c46_parents[] = { 4320d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER 4330d21680cSYann Gautier }; 4340d21680cSYann Gautier 4350d21680cSYann Gautier static const uint8_t spi6_parents[] = { 4360d21680cSYann Gautier _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q 4370d21680cSYann Gautier }; 4380d21680cSYann Gautier 4390d21680cSYann Gautier static const uint8_t usart1_parents[] = { 4400d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER 4410d21680cSYann Gautier }; 4420d21680cSYann Gautier 4430d21680cSYann Gautier static const uint8_t rng1_parents[] = { 4440d21680cSYann Gautier _CSI, _PLL4_R, _LSE, _LSI 4450d21680cSYann Gautier }; 4460d21680cSYann Gautier 4470d21680cSYann Gautier static const uint8_t uart6_parents[] = { 4480d21680cSYann Gautier _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 4490d21680cSYann Gautier }; 4500d21680cSYann Gautier 4510d21680cSYann Gautier static const uint8_t uart234578_parents[] = { 4520d21680cSYann Gautier _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 4530d21680cSYann Gautier }; 4540d21680cSYann Gautier 4550d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = { 4560d21680cSYann Gautier _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER 4570d21680cSYann Gautier }; 4580d21680cSYann Gautier 4590d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = { 4600d21680cSYann Gautier _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER 4610d21680cSYann Gautier }; 4620d21680cSYann Gautier 4630d21680cSYann Gautier static const uint8_t qspi_parents[] = { 4640d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 4650d21680cSYann Gautier }; 4660d21680cSYann Gautier 4670d21680cSYann Gautier static const uint8_t fmc_parents[] = { 4680d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 4690d21680cSYann Gautier }; 4700d21680cSYann Gautier 471b8fe48b6SEtienne Carriere static const uint8_t axiss_parents[] = { 472b8fe48b6SEtienne Carriere _HSI, _HSE, _PLL2_P 4730d21680cSYann Gautier }; 4740d21680cSYann Gautier 475b8fe48b6SEtienne Carriere static const uint8_t mcuss_parents[] = { 476b8fe48b6SEtienne Carriere _HSI, _HSE, _CSI, _PLL3_P 477b053a22eSYann Gautier }; 478b053a22eSYann Gautier 4790d21680cSYann Gautier static const uint8_t usbphy_parents[] = { 4800d21680cSYann Gautier _HSE_KER, _PLL4_R, _HSE_KER_DIV2 4810d21680cSYann Gautier }; 4820d21680cSYann Gautier 4830d21680cSYann Gautier static const uint8_t usbo_parents[] = { 4840d21680cSYann Gautier _PLL4_R, _USB_PHY_48 4850d21680cSYann Gautier }; 4867839a050SYann Gautier 4878fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = { 4888fbcd9e4SEtienne Carriere _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ 4898fbcd9e4SEtienne Carriere }; 4908fbcd9e4SEtienne Carriere 4918fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = { 4928fbcd9e4SEtienne Carriere _HSI, _HSE, _CSI, 4938fbcd9e4SEtienne Carriere }; 4948fbcd9e4SEtienne Carriere 495016af006SEtienne Carriere static const uint8_t rtc_parents[] = { 496cbd2e8a6SGabriel Fernandez _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC 497016af006SEtienne Carriere }; 498016af006SEtienne Carriere 4997839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { 500d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), 501d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), 502d4151d2fSYann Gautier _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), 503d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), 504d4151d2fSYann Gautier _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), 505d4151d2fSYann Gautier _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), 506d4151d2fSYann Gautier _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), 5078fbcd9e4SEtienne Carriere _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), 508288f5cf2SYann Gautier _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents), 509016af006SEtienne Carriere _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), 510d4151d2fSYann Gautier _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), 511d4151d2fSYann Gautier _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), 512d4151d2fSYann Gautier _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), 513d4151d2fSYann Gautier _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), 514d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), 515d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), 516d4151d2fSYann Gautier _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), 517d4151d2fSYann Gautier _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), 518b8fe48b6SEtienne Carriere _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents), 519b8fe48b6SEtienne Carriere _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), 520d4151d2fSYann Gautier _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), 521d4151d2fSYann Gautier _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), 5227839a050SYann Gautier }; 5237839a050SYann Gautier 5247839a050SYann Gautier /* Define characteristic of PLL according type */ 5257839a050SYann Gautier #define DIVN_MIN 24 5267839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { 5277839a050SYann Gautier [PLL_800] = { 5287839a050SYann Gautier .refclk_min = 4, 5297839a050SYann Gautier .refclk_max = 16, 5307839a050SYann Gautier .divn_max = 99, 5317839a050SYann Gautier }, 5327839a050SYann Gautier [PLL_1600] = { 5337839a050SYann Gautier .refclk_min = 8, 5347839a050SYann Gautier .refclk_max = 16, 5357839a050SYann Gautier .divn_max = 199, 5367839a050SYann Gautier }, 5377839a050SYann Gautier }; 5387839a050SYann Gautier 5397839a050SYann Gautier /* PLLNCFGR2 register divider by output */ 5407839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = { 5417839a050SYann Gautier [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, 5427839a050SYann Gautier [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, 5430d21680cSYann Gautier [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, 5447839a050SYann Gautier }; 5457839a050SYann Gautier 5467839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { 5470d21680cSYann Gautier _CLK_PLL(_PLL1, PLL_1600, 5487839a050SYann Gautier RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, 5497839a050SYann Gautier RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, 5507839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 5510d21680cSYann Gautier _CLK_PLL(_PLL2, PLL_1600, 5527839a050SYann Gautier RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, 5537839a050SYann Gautier RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, 5547839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 5550d21680cSYann Gautier _CLK_PLL(_PLL3, PLL_800, 5567839a050SYann Gautier RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, 5577839a050SYann Gautier RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, 5587839a050SYann Gautier _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), 5590d21680cSYann Gautier _CLK_PLL(_PLL4, PLL_800, 5607839a050SYann Gautier RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, 5617839a050SYann Gautier RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, 5627839a050SYann Gautier _HSI, _HSE, _CSI, _I2S_CKIN), 5637839a050SYann Gautier }; 5647839a050SYann Gautier 5657839a050SYann Gautier /* Prescaler table lookups for clock computation */ 566b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ 567b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = { 568b053a22eSYann Gautier 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 569b053a22eSYann Gautier }; 5707839a050SYann Gautier 5717839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ 5727839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div 5737839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div 5747839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = { 5757839a050SYann Gautier 0, 1, 2, 3, 4, 4, 4, 4 5767839a050SYann Gautier }; 5777839a050SYann Gautier 5787839a050SYann Gautier /* div = /1 /2 /3 /4 */ 5797839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = { 5807839a050SYann Gautier 1, 2, 3, 4, 4, 4, 4, 4 5817839a050SYann Gautier }; 5827839a050SYann Gautier 58337e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { 58437e8295aSEtienne Carriere [_HSI] = "HSI", 58537e8295aSEtienne Carriere [_HSE] = "HSE", 58637e8295aSEtienne Carriere [_CSI] = "CSI", 58737e8295aSEtienne Carriere [_LSI] = "LSI", 58837e8295aSEtienne Carriere [_LSE] = "LSE", 58937e8295aSEtienne Carriere [_I2S_CKIN] = "I2S_CKIN", 59037e8295aSEtienne Carriere [_HSI_KER] = "HSI_KER", 59137e8295aSEtienne Carriere [_HSE_KER] = "HSE_KER", 59237e8295aSEtienne Carriere [_HSE_KER_DIV2] = "HSE_KER_DIV2", 593cbd2e8a6SGabriel Fernandez [_HSE_RTC] = "HSE_RTC", 59437e8295aSEtienne Carriere [_CSI_KER] = "CSI_KER", 59537e8295aSEtienne Carriere [_PLL1_P] = "PLL1_P", 59637e8295aSEtienne Carriere [_PLL1_Q] = "PLL1_Q", 59737e8295aSEtienne Carriere [_PLL1_R] = "PLL1_R", 59837e8295aSEtienne Carriere [_PLL2_P] = "PLL2_P", 59937e8295aSEtienne Carriere [_PLL2_Q] = "PLL2_Q", 60037e8295aSEtienne Carriere [_PLL2_R] = "PLL2_R", 60137e8295aSEtienne Carriere [_PLL3_P] = "PLL3_P", 60237e8295aSEtienne Carriere [_PLL3_Q] = "PLL3_Q", 60337e8295aSEtienne Carriere [_PLL3_R] = "PLL3_R", 60437e8295aSEtienne Carriere [_PLL4_P] = "PLL4_P", 60537e8295aSEtienne Carriere [_PLL4_Q] = "PLL4_Q", 60637e8295aSEtienne Carriere [_PLL4_R] = "PLL4_R", 60737e8295aSEtienne Carriere [_ACLK] = "ACLK", 60837e8295aSEtienne Carriere [_PCLK1] = "PCLK1", 60937e8295aSEtienne Carriere [_PCLK2] = "PCLK2", 61037e8295aSEtienne Carriere [_PCLK3] = "PCLK3", 61137e8295aSEtienne Carriere [_PCLK4] = "PCLK4", 61237e8295aSEtienne Carriere [_PCLK5] = "PCLK5", 61337e8295aSEtienne Carriere [_HCLK6] = "KCLK6", 61437e8295aSEtienne Carriere [_HCLK2] = "HCLK2", 61537e8295aSEtienne Carriere [_CK_PER] = "CK_PER", 61637e8295aSEtienne Carriere [_CK_MPU] = "CK_MPU", 61737e8295aSEtienne Carriere [_CK_MCU] = "CK_MCU", 61837e8295aSEtienne Carriere [_USB_PHY_48] = "USB_PHY_48", 61937e8295aSEtienne Carriere }; 62037e8295aSEtienne Carriere 6210d21680cSYann Gautier /* RCC clock device driver private */ 6220d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC]; 6230d21680cSYann Gautier static struct spinlock reg_lock; 6240d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES]; 6250d21680cSYann Gautier static struct spinlock refcount_lock; 6267839a050SYann Gautier 6270d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) 6280d21680cSYann Gautier { 6290d21680cSYann Gautier return &stm32mp1_clk_gate[idx]; 6300d21680cSYann Gautier } 6317839a050SYann Gautier 6320d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) 6330d21680cSYann Gautier { 6340d21680cSYann Gautier return &stm32mp1_clk_sel[idx]; 6350d21680cSYann Gautier } 6360d21680cSYann Gautier 6370d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) 6380d21680cSYann Gautier { 6390d21680cSYann Gautier return &stm32mp1_clk_pll[idx]; 6400d21680cSYann Gautier } 6410d21680cSYann Gautier 6420d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock) 6430d21680cSYann Gautier { 644e463d3f4SYann Gautier if (stm32mp_lock_available()) { 6450d21680cSYann Gautier /* Assume interrupts are masked */ 6460d21680cSYann Gautier spin_lock(lock); 6470d21680cSYann Gautier } 648e463d3f4SYann Gautier } 6490d21680cSYann Gautier 6500d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock) 6510d21680cSYann Gautier { 652e463d3f4SYann Gautier if (stm32mp_lock_available()) { 6530d21680cSYann Gautier spin_unlock(lock); 6540d21680cSYann Gautier } 655e463d3f4SYann Gautier } 6560d21680cSYann Gautier 6570d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void) 6580d21680cSYann Gautier { 6590d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 6601bb9072aSEtienne Carriere uint32_t mask = RCC_TZCR_TZEN; 6610d21680cSYann Gautier 6621bb9072aSEtienne Carriere return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 6630d21680cSYann Gautier } 6640d21680cSYann Gautier 665b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void) 666b053a22eSYann Gautier { 667b053a22eSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 6681bb9072aSEtienne Carriere uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; 669b053a22eSYann Gautier 6701bb9072aSEtienne Carriere return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; 671b053a22eSYann Gautier } 672b053a22eSYann Gautier 6730d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void) 6740d21680cSYann Gautier { 6750d21680cSYann Gautier stm32mp1_clk_lock(®_lock); 6760d21680cSYann Gautier } 6770d21680cSYann Gautier 6780d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void) 6790d21680cSYann Gautier { 6800d21680cSYann Gautier stm32mp1_clk_unlock(®_lock); 6810d21680cSYann Gautier } 6820d21680cSYann Gautier 6830d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) 6847839a050SYann Gautier { 6857839a050SYann Gautier if (idx >= NB_OSC) { 6867839a050SYann Gautier return 0; 6877839a050SYann Gautier } 6887839a050SYann Gautier 6890d21680cSYann Gautier return stm32mp1_osc[idx]; 6907839a050SYann Gautier } 6917839a050SYann Gautier 6920d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id) 6937839a050SYann Gautier { 6940d21680cSYann Gautier unsigned int i; 6957839a050SYann Gautier 6960d21680cSYann Gautier for (i = 0U; i < NB_GATES; i++) { 6970d21680cSYann Gautier if (gate_ref(i)->index == id) { 6987839a050SYann Gautier return i; 6997839a050SYann Gautier } 7007839a050SYann Gautier } 7017839a050SYann Gautier 7027839a050SYann Gautier ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id); 7037839a050SYann Gautier 7047839a050SYann Gautier return -EINVAL; 7057839a050SYann Gautier } 7067839a050SYann Gautier 7070d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) 7087839a050SYann Gautier { 7090d21680cSYann Gautier return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); 7107839a050SYann Gautier } 7117839a050SYann Gautier 7120d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) 7137839a050SYann Gautier { 7140d21680cSYann Gautier return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); 7157839a050SYann Gautier } 7167839a050SYann Gautier 7170d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id) 7187839a050SYann Gautier { 7190d21680cSYann Gautier const struct stm32mp1_clk_sel *sel; 7208fbcd9e4SEtienne Carriere uint32_t p_sel; 7217839a050SYann Gautier int i; 7227839a050SYann Gautier enum stm32mp1_parent_id p; 7237839a050SYann Gautier enum stm32mp1_parent_sel s; 7240d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 7257839a050SYann Gautier 7268fbcd9e4SEtienne Carriere /* Few non gateable clock have a static parent ID, find them */ 7278fbcd9e4SEtienne Carriere i = (int)clock_id2parent_id(id); 7288fbcd9e4SEtienne Carriere if (i != _UNKNOWN_ID) { 7298fbcd9e4SEtienne Carriere return i; 7307839a050SYann Gautier } 7317839a050SYann Gautier 7320d21680cSYann Gautier i = stm32mp1_clk_get_gated_id(id); 7337839a050SYann Gautier if (i < 0) { 7340d21680cSYann Gautier panic(); 7357839a050SYann Gautier } 7367839a050SYann Gautier 7370d21680cSYann Gautier p = stm32mp1_clk_get_fixed_parent(i); 7387839a050SYann Gautier if (p < _PARENT_NB) { 7397839a050SYann Gautier return (int)p; 7407839a050SYann Gautier } 7417839a050SYann Gautier 7420d21680cSYann Gautier s = stm32mp1_clk_get_sel(i); 7430d21680cSYann Gautier if (s == _UNKNOWN_SEL) { 7440d21680cSYann Gautier return -EINVAL; 7450d21680cSYann Gautier } 7467839a050SYann Gautier if (s >= _PARENT_SEL_NB) { 7470d21680cSYann Gautier panic(); 7487839a050SYann Gautier } 7497839a050SYann Gautier 7500d21680cSYann Gautier sel = clk_sel_ref(s); 7518ae08dcdSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) & 7528ae08dcdSEtienne Carriere (sel->msk << sel->src)) >> sel->src; 7530d21680cSYann Gautier if (p_sel < sel->nb_parent) { 7540d21680cSYann Gautier return (int)sel->parent[p_sel]; 7557839a050SYann Gautier } 7567839a050SYann Gautier 7577839a050SYann Gautier return -EINVAL; 7587839a050SYann Gautier } 7597839a050SYann Gautier 7600d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) 7617839a050SYann Gautier { 7620d21680cSYann Gautier uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); 7630d21680cSYann Gautier uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; 7647839a050SYann Gautier 7650d21680cSYann Gautier return stm32mp1_clk_get_fixed(pll->refclk[src]); 7667839a050SYann Gautier } 7677839a050SYann Gautier 7687839a050SYann Gautier /* 7697839a050SYann Gautier * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL 7707839a050SYann Gautier * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) 7717839a050SYann Gautier * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) 7727839a050SYann Gautier * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) 7737839a050SYann Gautier */ 7740d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) 7757839a050SYann Gautier { 7767839a050SYann Gautier unsigned long refclk, fvco; 7777839a050SYann Gautier uint32_t cfgr1, fracr, divm, divn; 7780d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 7797839a050SYann Gautier 7800d21680cSYann Gautier cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); 7810d21680cSYann Gautier fracr = mmio_read_32(rcc_base + pll->pllxfracr); 7827839a050SYann Gautier 7837839a050SYann Gautier divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; 7847839a050SYann Gautier divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; 7857839a050SYann Gautier 7860d21680cSYann Gautier refclk = stm32mp1_pll_get_fref(pll); 7877839a050SYann Gautier 7887839a050SYann Gautier /* 7897839a050SYann Gautier * With FRACV : 7907839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) 7917839a050SYann Gautier * Without FRACV 7927839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) 7937839a050SYann Gautier */ 7947839a050SYann Gautier if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { 7950d21680cSYann Gautier uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> 7960d21680cSYann Gautier RCC_PLLNFRACR_FRACV_SHIFT; 7977839a050SYann Gautier unsigned long long numerator, denominator; 7987839a050SYann Gautier 7990d21680cSYann Gautier numerator = (((unsigned long long)divn + 1U) << 13) + fracv; 8000d21680cSYann Gautier numerator = refclk * numerator; 8017839a050SYann Gautier denominator = ((unsigned long long)divm + 1U) << 13; 8027839a050SYann Gautier fvco = (unsigned long)(numerator / denominator); 8037839a050SYann Gautier } else { 8047839a050SYann Gautier fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); 8057839a050SYann Gautier } 8067839a050SYann Gautier 8077839a050SYann Gautier return fvco; 8087839a050SYann Gautier } 8097839a050SYann Gautier 8100d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, 8117839a050SYann Gautier enum stm32mp1_div_id div_id) 8127839a050SYann Gautier { 8130d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 8147839a050SYann Gautier unsigned long dfout; 8157839a050SYann Gautier uint32_t cfgr2, divy; 8167839a050SYann Gautier 8177839a050SYann Gautier if (div_id >= _DIV_NB) { 8187839a050SYann Gautier return 0; 8197839a050SYann Gautier } 8207839a050SYann Gautier 8210d21680cSYann Gautier cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); 8227839a050SYann Gautier divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; 8237839a050SYann Gautier 8240d21680cSYann Gautier dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); 8257839a050SYann Gautier 8267839a050SYann Gautier return dfout; 8277839a050SYann Gautier } 8287839a050SYann Gautier 8290d21680cSYann Gautier static unsigned long get_clock_rate(int p) 8307839a050SYann Gautier { 8317839a050SYann Gautier uint32_t reg, clkdiv; 8327839a050SYann Gautier unsigned long clock = 0; 8330d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 8347839a050SYann Gautier 8357839a050SYann Gautier switch (p) { 8367839a050SYann Gautier case _CK_MPU: 8377839a050SYann Gautier /* MPU sub system */ 8380d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKSELR); 8397839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 8407839a050SYann Gautier case RCC_MPCKSELR_HSI: 8410d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 8427839a050SYann Gautier break; 8437839a050SYann Gautier case RCC_MPCKSELR_HSE: 8440d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 8457839a050SYann Gautier break; 8467839a050SYann Gautier case RCC_MPCKSELR_PLL: 8470d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 8487839a050SYann Gautier break; 8497839a050SYann Gautier case RCC_MPCKSELR_PLL_MPUDIV: 8500d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 8517839a050SYann Gautier 8520d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); 8537839a050SYann Gautier clkdiv = reg & RCC_MPUDIV_MASK; 854602ae2f2SGabriel Fernandez clock >>= stm32mp1_mpu_div[clkdiv]; 8557839a050SYann Gautier break; 8567839a050SYann Gautier default: 8577839a050SYann Gautier break; 8587839a050SYann Gautier } 8597839a050SYann Gautier break; 8607839a050SYann Gautier /* AXI sub system */ 8617839a050SYann Gautier case _ACLK: 8627839a050SYann Gautier case _HCLK2: 8637839a050SYann Gautier case _HCLK6: 8647839a050SYann Gautier case _PCLK4: 8657839a050SYann Gautier case _PCLK5: 8660d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); 8677839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 8687839a050SYann Gautier case RCC_ASSCKSELR_HSI: 8690d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 8707839a050SYann Gautier break; 8717839a050SYann Gautier case RCC_ASSCKSELR_HSE: 8720d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 8737839a050SYann Gautier break; 8747839a050SYann Gautier case RCC_ASSCKSELR_PLL: 8750d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 8767839a050SYann Gautier break; 8777839a050SYann Gautier default: 8787839a050SYann Gautier break; 8797839a050SYann Gautier } 8807839a050SYann Gautier 8817839a050SYann Gautier /* System clock divider */ 8820d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_AXIDIVR); 8837839a050SYann Gautier clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; 8847839a050SYann Gautier 8857839a050SYann Gautier switch (p) { 8867839a050SYann Gautier case _PCLK4: 8870d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB4DIVR); 8887839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 8897839a050SYann Gautier break; 8907839a050SYann Gautier case _PCLK5: 8910d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB5DIVR); 8927839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 8937839a050SYann Gautier break; 8947839a050SYann Gautier default: 8957839a050SYann Gautier break; 8967839a050SYann Gautier } 8977839a050SYann Gautier break; 898b053a22eSYann Gautier /* MCU sub system */ 899b053a22eSYann Gautier case _CK_MCU: 900b053a22eSYann Gautier case _PCLK1: 901b053a22eSYann Gautier case _PCLK2: 902b053a22eSYann Gautier case _PCLK3: 903b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); 904b053a22eSYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 905b053a22eSYann Gautier case RCC_MSSCKSELR_HSI: 906b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 907b053a22eSYann Gautier break; 908b053a22eSYann Gautier case RCC_MSSCKSELR_HSE: 909b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 910b053a22eSYann Gautier break; 911b053a22eSYann Gautier case RCC_MSSCKSELR_CSI: 912b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 913b053a22eSYann Gautier break; 914b053a22eSYann Gautier case RCC_MSSCKSELR_PLL: 915b053a22eSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 916b053a22eSYann Gautier break; 917b053a22eSYann Gautier default: 918b053a22eSYann Gautier break; 919b053a22eSYann Gautier } 920b053a22eSYann Gautier 921b053a22eSYann Gautier /* MCU clock divider */ 922b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MCUDIVR); 923b053a22eSYann Gautier clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; 924b053a22eSYann Gautier 925b053a22eSYann Gautier switch (p) { 926b053a22eSYann Gautier case _PCLK1: 927b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB1DIVR); 928b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 929b053a22eSYann Gautier break; 930b053a22eSYann Gautier case _PCLK2: 931b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB2DIVR); 932b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 933b053a22eSYann Gautier break; 934b053a22eSYann Gautier case _PCLK3: 935b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB3DIVR); 936b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 937b053a22eSYann Gautier break; 938b053a22eSYann Gautier case _CK_MCU: 939b053a22eSYann Gautier default: 940b053a22eSYann Gautier break; 941b053a22eSYann Gautier } 942b053a22eSYann Gautier break; 9437839a050SYann Gautier case _CK_PER: 9440d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); 9457839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 9467839a050SYann Gautier case RCC_CPERCKSELR_HSI: 9470d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 9487839a050SYann Gautier break; 9497839a050SYann Gautier case RCC_CPERCKSELR_HSE: 9500d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 9517839a050SYann Gautier break; 9527839a050SYann Gautier case RCC_CPERCKSELR_CSI: 9530d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 9547839a050SYann Gautier break; 9557839a050SYann Gautier default: 9567839a050SYann Gautier break; 9577839a050SYann Gautier } 9587839a050SYann Gautier break; 9597839a050SYann Gautier case _HSI: 9607839a050SYann Gautier case _HSI_KER: 9610d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 9627839a050SYann Gautier break; 9637839a050SYann Gautier case _CSI: 9647839a050SYann Gautier case _CSI_KER: 9650d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 9667839a050SYann Gautier break; 9677839a050SYann Gautier case _HSE: 9687839a050SYann Gautier case _HSE_KER: 9690d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 9707839a050SYann Gautier break; 9717839a050SYann Gautier case _HSE_KER_DIV2: 9720d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE) >> 1; 9737839a050SYann Gautier break; 974cbd2e8a6SGabriel Fernandez case _HSE_RTC: 975cbd2e8a6SGabriel Fernandez clock = stm32mp1_clk_get_fixed(_HSE); 976cbd2e8a6SGabriel Fernandez clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; 977cbd2e8a6SGabriel Fernandez break; 9787839a050SYann Gautier case _LSI: 9790d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSI); 9807839a050SYann Gautier break; 9817839a050SYann Gautier case _LSE: 9820d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSE); 9837839a050SYann Gautier break; 9847839a050SYann Gautier /* PLL */ 9857839a050SYann Gautier case _PLL1_P: 9860d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 9877839a050SYann Gautier break; 9887839a050SYann Gautier case _PLL1_Q: 9890d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); 9907839a050SYann Gautier break; 9917839a050SYann Gautier case _PLL1_R: 9920d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); 9937839a050SYann Gautier break; 9947839a050SYann Gautier case _PLL2_P: 9950d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 9967839a050SYann Gautier break; 9977839a050SYann Gautier case _PLL2_Q: 9980d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); 9997839a050SYann Gautier break; 10007839a050SYann Gautier case _PLL2_R: 10010d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); 10027839a050SYann Gautier break; 10037839a050SYann Gautier case _PLL3_P: 10040d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 10057839a050SYann Gautier break; 10067839a050SYann Gautier case _PLL3_Q: 10070d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); 10087839a050SYann Gautier break; 10097839a050SYann Gautier case _PLL3_R: 10100d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); 10117839a050SYann Gautier break; 10127839a050SYann Gautier case _PLL4_P: 10130d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); 10147839a050SYann Gautier break; 10157839a050SYann Gautier case _PLL4_Q: 10160d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); 10177839a050SYann Gautier break; 10187839a050SYann Gautier case _PLL4_R: 10190d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); 10207839a050SYann Gautier break; 10217839a050SYann Gautier /* Other */ 10227839a050SYann Gautier case _USB_PHY_48: 10230d21680cSYann Gautier clock = USB_PHY_48_MHZ; 10247839a050SYann Gautier break; 10257839a050SYann Gautier default: 10267839a050SYann Gautier break; 10277839a050SYann Gautier } 10287839a050SYann Gautier 10297839a050SYann Gautier return clock; 10307839a050SYann Gautier } 10317839a050SYann Gautier 10320d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate) 10330d21680cSYann Gautier { 10340d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10350d21680cSYann Gautier 103625be845eSEtienne Carriere VERBOSE("Enable clock %u\n", gate->index); 103725be845eSEtienne Carriere 10380d21680cSYann Gautier if (gate->set_clr != 0U) { 10390d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); 10400d21680cSYann Gautier } else { 10410d21680cSYann Gautier mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); 10420d21680cSYann Gautier } 10430d21680cSYann Gautier } 10440d21680cSYann Gautier 10450d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate) 10460d21680cSYann Gautier { 10470d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10480d21680cSYann Gautier 104925be845eSEtienne Carriere VERBOSE("Disable clock %u\n", gate->index); 105025be845eSEtienne Carriere 10510d21680cSYann Gautier if (gate->set_clr != 0U) { 10520d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, 10530d21680cSYann Gautier BIT(gate->bit)); 10540d21680cSYann Gautier } else { 10550d21680cSYann Gautier mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); 10560d21680cSYann Gautier } 10570d21680cSYann Gautier } 10580d21680cSYann Gautier 10590d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) 10600d21680cSYann Gautier { 10610d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10620d21680cSYann Gautier 10630d21680cSYann Gautier return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); 10640d21680cSYann Gautier } 10650d21680cSYann Gautier 10660d21680cSYann Gautier unsigned int stm32mp1_clk_get_refcount(unsigned long id) 10670d21680cSYann Gautier { 10680d21680cSYann Gautier int i = stm32mp1_clk_get_gated_id(id); 10690d21680cSYann Gautier 10700d21680cSYann Gautier if (i < 0) { 10710d21680cSYann Gautier panic(); 10720d21680cSYann Gautier } 10730d21680cSYann Gautier 10740d21680cSYann Gautier return gate_refcounts[i]; 10750d21680cSYann Gautier } 10760d21680cSYann Gautier 107735848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */ 107835848200SEtienne Carriere static bool clock_is_always_on(unsigned long id) 107935848200SEtienne Carriere { 108035848200SEtienne Carriere switch (id) { 108135848200SEtienne Carriere case CK_HSE: 108235848200SEtienne Carriere case CK_CSI: 108335848200SEtienne Carriere case CK_LSI: 108435848200SEtienne Carriere case CK_LSE: 108535848200SEtienne Carriere case CK_HSI: 108635848200SEtienne Carriere case CK_HSE_DIV2: 108735848200SEtienne Carriere case PLL1_Q: 108835848200SEtienne Carriere case PLL1_R: 108935848200SEtienne Carriere case PLL2_P: 109035848200SEtienne Carriere case PLL2_Q: 109135848200SEtienne Carriere case PLL2_R: 109235848200SEtienne Carriere case PLL3_P: 109335848200SEtienne Carriere case PLL3_Q: 109435848200SEtienne Carriere case PLL3_R: 1095bf39318dSYann Gautier case CK_AXI: 1096bf39318dSYann Gautier case CK_MPU: 1097bf39318dSYann Gautier case CK_MCU: 10985b111c74SHE Shushan case RTC: 109935848200SEtienne Carriere return true; 110035848200SEtienne Carriere default: 110135848200SEtienne Carriere return false; 110235848200SEtienne Carriere } 110335848200SEtienne Carriere } 110435848200SEtienne Carriere 11050d21680cSYann Gautier void __stm32mp1_clk_enable(unsigned long id, bool secure) 11060d21680cSYann Gautier { 11070d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 110835848200SEtienne Carriere int i; 11090d21680cSYann Gautier unsigned int *refcnt; 11100d21680cSYann Gautier 111135848200SEtienne Carriere if (clock_is_always_on(id)) { 111235848200SEtienne Carriere return; 111335848200SEtienne Carriere } 111435848200SEtienne Carriere 111535848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11160d21680cSYann Gautier if (i < 0) { 11170d21680cSYann Gautier ERROR("Clock %d can't be enabled\n", (uint32_t)id); 11180d21680cSYann Gautier panic(); 11190d21680cSYann Gautier } 11200d21680cSYann Gautier 11210d21680cSYann Gautier gate = gate_ref(i); 11220d21680cSYann Gautier refcnt = &gate_refcounts[i]; 11230d21680cSYann Gautier 11240d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 11250d21680cSYann Gautier 11260d21680cSYann Gautier if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { 11270d21680cSYann Gautier __clk_enable(gate); 11280d21680cSYann Gautier } 11290d21680cSYann Gautier 11300d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 11310d21680cSYann Gautier } 11320d21680cSYann Gautier 11330d21680cSYann Gautier void __stm32mp1_clk_disable(unsigned long id, bool secure) 11340d21680cSYann Gautier { 11350d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 113635848200SEtienne Carriere int i; 11370d21680cSYann Gautier unsigned int *refcnt; 11380d21680cSYann Gautier 113935848200SEtienne Carriere if (clock_is_always_on(id)) { 114035848200SEtienne Carriere return; 114135848200SEtienne Carriere } 114235848200SEtienne Carriere 114335848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11440d21680cSYann Gautier if (i < 0) { 11450d21680cSYann Gautier ERROR("Clock %d can't be disabled\n", (uint32_t)id); 11460d21680cSYann Gautier panic(); 11470d21680cSYann Gautier } 11480d21680cSYann Gautier 11490d21680cSYann Gautier gate = gate_ref(i); 11500d21680cSYann Gautier refcnt = &gate_refcounts[i]; 11510d21680cSYann Gautier 11520d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 11530d21680cSYann Gautier 11540d21680cSYann Gautier if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { 11550d21680cSYann Gautier __clk_disable(gate); 11560d21680cSYann Gautier } 11570d21680cSYann Gautier 11580d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 11590d21680cSYann Gautier } 11600d21680cSYann Gautier 1161*33667d29SYann Gautier static int stm32mp_clk_enable(unsigned long id) 11620d21680cSYann Gautier { 11630d21680cSYann Gautier __stm32mp1_clk_enable(id, true); 1164*33667d29SYann Gautier 1165*33667d29SYann Gautier return 0; 11660d21680cSYann Gautier } 11670d21680cSYann Gautier 1168*33667d29SYann Gautier static void stm32mp_clk_disable(unsigned long id) 11690d21680cSYann Gautier { 11700d21680cSYann Gautier __stm32mp1_clk_disable(id, true); 11710d21680cSYann Gautier } 11720d21680cSYann Gautier 1173*33667d29SYann Gautier static bool stm32mp_clk_is_enabled(unsigned long id) 11747839a050SYann Gautier { 117535848200SEtienne Carriere int i; 11767839a050SYann Gautier 117735848200SEtienne Carriere if (clock_is_always_on(id)) { 117835848200SEtienne Carriere return true; 117935848200SEtienne Carriere } 118035848200SEtienne Carriere 118135848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11827839a050SYann Gautier if (i < 0) { 11830d21680cSYann Gautier panic(); 11847839a050SYann Gautier } 11857839a050SYann Gautier 11860d21680cSYann Gautier return __clk_is_enabled(gate_ref(i)); 11877839a050SYann Gautier } 11887839a050SYann Gautier 1189*33667d29SYann Gautier static unsigned long stm32mp_clk_get_rate(unsigned long id) 11907839a050SYann Gautier { 1191*33667d29SYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 11920d21680cSYann Gautier int p = stm32mp1_clk_get_parent(id); 1193*33667d29SYann Gautier uint32_t prescaler, timpre; 1194*33667d29SYann Gautier unsigned long parent_rate; 11957839a050SYann Gautier 11967839a050SYann Gautier if (p < 0) { 11977839a050SYann Gautier return 0; 11987839a050SYann Gautier } 11997839a050SYann Gautier 1200*33667d29SYann Gautier parent_rate = get_clock_rate(p); 1201*33667d29SYann Gautier 1202*33667d29SYann Gautier switch (id) { 1203*33667d29SYann Gautier case TIM2_K: 1204*33667d29SYann Gautier case TIM3_K: 1205*33667d29SYann Gautier case TIM4_K: 1206*33667d29SYann Gautier case TIM5_K: 1207*33667d29SYann Gautier case TIM6_K: 1208*33667d29SYann Gautier case TIM7_K: 1209*33667d29SYann Gautier case TIM12_K: 1210*33667d29SYann Gautier case TIM13_K: 1211*33667d29SYann Gautier case TIM14_K: 1212*33667d29SYann Gautier prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & 1213*33667d29SYann Gautier RCC_APBXDIV_MASK; 1214*33667d29SYann Gautier timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & 1215*33667d29SYann Gautier RCC_TIMGXPRER_TIMGXPRE; 1216*33667d29SYann Gautier break; 1217*33667d29SYann Gautier 1218*33667d29SYann Gautier case TIM1_K: 1219*33667d29SYann Gautier case TIM8_K: 1220*33667d29SYann Gautier case TIM15_K: 1221*33667d29SYann Gautier case TIM16_K: 1222*33667d29SYann Gautier case TIM17_K: 1223*33667d29SYann Gautier prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & 1224*33667d29SYann Gautier RCC_APBXDIV_MASK; 1225*33667d29SYann Gautier timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & 1226*33667d29SYann Gautier RCC_TIMGXPRER_TIMGXPRE; 1227*33667d29SYann Gautier break; 1228*33667d29SYann Gautier 1229*33667d29SYann Gautier default: 1230*33667d29SYann Gautier return parent_rate; 1231*33667d29SYann Gautier } 1232*33667d29SYann Gautier 1233*33667d29SYann Gautier if (prescaler == 0U) { 1234*33667d29SYann Gautier return parent_rate; 1235*33667d29SYann Gautier } 1236*33667d29SYann Gautier 1237*33667d29SYann Gautier return parent_rate * (timpre + 1U) * 2U; 12387839a050SYann Gautier } 12397839a050SYann Gautier 12400d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) 12417839a050SYann Gautier { 12420d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 12437839a050SYann Gautier 12440d21680cSYann Gautier if (enable) { 12457839a050SYann Gautier mmio_setbits_32(address, mask_on); 12467839a050SYann Gautier } else { 12477839a050SYann Gautier mmio_clrbits_32(address, mask_on); 12487839a050SYann Gautier } 12497839a050SYann Gautier } 12507839a050SYann Gautier 12510d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) 12527839a050SYann Gautier { 12530d21680cSYann Gautier uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; 12540d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 12550d21680cSYann Gautier 12560d21680cSYann Gautier mmio_write_32(address, mask_on); 12577839a050SYann Gautier } 12587839a050SYann Gautier 12590d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) 12607839a050SYann Gautier { 1261dfdb057aSYann Gautier uint64_t timeout; 12627839a050SYann Gautier uint32_t mask_test; 12630d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 12647839a050SYann Gautier 12650d21680cSYann Gautier if (enable) { 12667839a050SYann Gautier mask_test = mask_rdy; 12677839a050SYann Gautier } else { 12687839a050SYann Gautier mask_test = 0; 12697839a050SYann Gautier } 12707839a050SYann Gautier 1271dfdb057aSYann Gautier timeout = timeout_init_us(OSCRDY_TIMEOUT); 12727839a050SYann Gautier while ((mmio_read_32(address) & mask_rdy) != mask_test) { 1273dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 12740d21680cSYann Gautier ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", 12757839a050SYann Gautier mask_rdy, address, enable, mmio_read_32(address)); 12767839a050SYann Gautier return -ETIMEDOUT; 12777839a050SYann Gautier } 12787839a050SYann Gautier } 12797839a050SYann Gautier 12807839a050SYann Gautier return 0; 12817839a050SYann Gautier } 12827839a050SYann Gautier 12830d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) 12847839a050SYann Gautier { 12857839a050SYann Gautier uint32_t value; 12860d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 12877839a050SYann Gautier 12880d21680cSYann Gautier if (digbyp) { 12890d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); 12900d21680cSYann Gautier } 12910d21680cSYann Gautier 12920d21680cSYann Gautier if (bypass || digbyp) { 12930d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); 12947839a050SYann Gautier } 12957839a050SYann Gautier 12967839a050SYann Gautier /* 12977839a050SYann Gautier * Warning: not recommended to switch directly from "high drive" 12987839a050SYann Gautier * to "medium low drive", and vice-versa. 12997839a050SYann Gautier */ 13000d21680cSYann Gautier value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> 13017839a050SYann Gautier RCC_BDCR_LSEDRV_SHIFT; 13027839a050SYann Gautier 13037839a050SYann Gautier while (value != lsedrv) { 13047839a050SYann Gautier if (value > lsedrv) { 13057839a050SYann Gautier value--; 13067839a050SYann Gautier } else { 13077839a050SYann Gautier value++; 13087839a050SYann Gautier } 13097839a050SYann Gautier 13100d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_BDCR, 13117839a050SYann Gautier RCC_BDCR_LSEDRV_MASK, 13127839a050SYann Gautier value << RCC_BDCR_LSEDRV_SHIFT); 13137839a050SYann Gautier } 13147839a050SYann Gautier 13150d21680cSYann Gautier stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); 13167839a050SYann Gautier } 13177839a050SYann Gautier 13180d21680cSYann Gautier static void stm32mp1_lse_wait(void) 13197839a050SYann Gautier { 13200d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { 13217839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13227839a050SYann Gautier } 13237839a050SYann Gautier } 13247839a050SYann Gautier 13250d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable) 13267839a050SYann Gautier { 13270d21680cSYann Gautier stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); 13280d21680cSYann Gautier 13290d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { 13307839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13317839a050SYann Gautier } 13327839a050SYann Gautier } 13337839a050SYann Gautier 13340d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) 13357839a050SYann Gautier { 13360d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13370d21680cSYann Gautier 13380d21680cSYann Gautier if (digbyp) { 13390d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); 13407839a050SYann Gautier } 13417839a050SYann Gautier 13420d21680cSYann Gautier if (bypass || digbyp) { 13430d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); 13440d21680cSYann Gautier } 13450d21680cSYann Gautier 13460d21680cSYann Gautier stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); 13470d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { 13487839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13497839a050SYann Gautier } 13507839a050SYann Gautier 13517839a050SYann Gautier if (css) { 13520d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); 13537839a050SYann Gautier } 13547839a050SYann Gautier } 13557839a050SYann Gautier 13560d21680cSYann Gautier static void stm32mp1_csi_set(bool enable) 13577839a050SYann Gautier { 13580d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); 13590d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { 13607839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13617839a050SYann Gautier } 13627839a050SYann Gautier } 13637839a050SYann Gautier 13640d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable) 13657839a050SYann Gautier { 13660d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); 13670d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { 13687839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 13697839a050SYann Gautier } 13707839a050SYann Gautier } 13717839a050SYann Gautier 13720d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv) 13737839a050SYann Gautier { 1374dfdb057aSYann Gautier uint64_t timeout; 13750d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13760d21680cSYann Gautier uintptr_t address = rcc_base + RCC_OCRDYR; 13777839a050SYann Gautier 13780d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, 13797839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK, 13807839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); 13817839a050SYann Gautier 1382dfdb057aSYann Gautier timeout = timeout_init_us(HSIDIV_TIMEOUT); 13837839a050SYann Gautier while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { 1384dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 13850d21680cSYann Gautier ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", 13867839a050SYann Gautier address, mmio_read_32(address)); 13877839a050SYann Gautier return -ETIMEDOUT; 13887839a050SYann Gautier } 13897839a050SYann Gautier } 13907839a050SYann Gautier 13917839a050SYann Gautier return 0; 13927839a050SYann Gautier } 13937839a050SYann Gautier 13940d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq) 13957839a050SYann Gautier { 13967839a050SYann Gautier uint8_t hsidiv; 13977839a050SYann Gautier uint32_t hsidivfreq = MAX_HSI_HZ; 13987839a050SYann Gautier 13997839a050SYann Gautier for (hsidiv = 0; hsidiv < 4U; hsidiv++) { 14007839a050SYann Gautier if (hsidivfreq == hsifreq) { 14017839a050SYann Gautier break; 14027839a050SYann Gautier } 14037839a050SYann Gautier 14047839a050SYann Gautier hsidivfreq /= 2U; 14057839a050SYann Gautier } 14067839a050SYann Gautier 14077839a050SYann Gautier if (hsidiv == 4U) { 14087839a050SYann Gautier ERROR("Invalid clk-hsi frequency\n"); 14097839a050SYann Gautier return -1; 14107839a050SYann Gautier } 14117839a050SYann Gautier 14127839a050SYann Gautier if (hsidiv != 0U) { 14130d21680cSYann Gautier return stm32mp1_set_hsidiv(hsidiv); 14147839a050SYann Gautier } 14157839a050SYann Gautier 14167839a050SYann Gautier return 0; 14177839a050SYann Gautier } 14187839a050SYann Gautier 14190d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, 14200d21680cSYann Gautier unsigned int clksrc, 14210d21680cSYann Gautier uint32_t *pllcfg, int plloff) 14227839a050SYann Gautier { 14230d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14240d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 14250d21680cSYann Gautier uintptr_t pllxcr = rcc_base + pll->pllxcr; 14260d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 14270d21680cSYann Gautier uintptr_t clksrc_address = rcc_base + (clksrc >> 4); 14280d21680cSYann Gautier unsigned long refclk; 14290d21680cSYann Gautier uint32_t ifrge = 0U; 1430be858cffSAndre Przywara uint32_t src, value, fracv = 0; 1431be858cffSAndre Przywara void *fdt; 14327839a050SYann Gautier 14330d21680cSYann Gautier /* Check PLL output */ 14340d21680cSYann Gautier if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { 14350d21680cSYann Gautier return false; 14367839a050SYann Gautier } 14377839a050SYann Gautier 14380d21680cSYann Gautier /* Check current clksrc */ 14390d21680cSYann Gautier src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; 14400d21680cSYann Gautier if (src != (clksrc & RCC_SELR_SRC_MASK)) { 14410d21680cSYann Gautier return false; 14420d21680cSYann Gautier } 14430d21680cSYann Gautier 14440d21680cSYann Gautier /* Check Div */ 14450d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; 14460d21680cSYann Gautier 14470d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 14480d21680cSYann Gautier (pllcfg[PLLCFG_M] + 1U); 14490d21680cSYann Gautier 14500d21680cSYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 14510d21680cSYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 14520d21680cSYann Gautier return false; 14530d21680cSYann Gautier } 14540d21680cSYann Gautier 14550d21680cSYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 14560d21680cSYann Gautier ifrge = 1U; 14570d21680cSYann Gautier } 14580d21680cSYann Gautier 14590d21680cSYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 14600d21680cSYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 14610d21680cSYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 14620d21680cSYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 14630d21680cSYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 14640d21680cSYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 14650d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { 14660d21680cSYann Gautier return false; 14670d21680cSYann Gautier } 14680d21680cSYann Gautier 14690d21680cSYann Gautier /* Fractional configuration */ 1470be858cffSAndre Przywara if (fdt_get_address(&fdt) == 1) { 1471be858cffSAndre Przywara fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); 1472be858cffSAndre Przywara } 14730d21680cSYann Gautier 14740d21680cSYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 14750d21680cSYann Gautier value |= RCC_PLLNFRACR_FRACLE; 14760d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { 14770d21680cSYann Gautier return false; 14780d21680cSYann Gautier } 14790d21680cSYann Gautier 14800d21680cSYann Gautier /* Output config */ 14810d21680cSYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 14820d21680cSYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 14830d21680cSYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 14840d21680cSYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 14850d21680cSYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 14860d21680cSYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 14870d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { 14880d21680cSYann Gautier return false; 14890d21680cSYann Gautier } 14900d21680cSYann Gautier 14910d21680cSYann Gautier return true; 14920d21680cSYann Gautier } 14930d21680cSYann Gautier 14940d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) 14957839a050SYann Gautier { 14960d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14970d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 14980d21680cSYann Gautier 1499dd98aec8SYann Gautier /* Preserve RCC_PLLNCR_SSCG_CTRL value */ 1500dd98aec8SYann Gautier mmio_clrsetbits_32(pllxcr, 1501dd98aec8SYann Gautier RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 1502dd98aec8SYann Gautier RCC_PLLNCR_DIVREN, 1503dd98aec8SYann Gautier RCC_PLLNCR_PLLON); 15040d21680cSYann Gautier } 15050d21680cSYann Gautier 15060d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) 15070d21680cSYann Gautier { 15080d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15090d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1510dfdb057aSYann Gautier uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); 15117839a050SYann Gautier 15127839a050SYann Gautier /* Wait PLL lock */ 15137839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { 1514dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 15150d21680cSYann Gautier ERROR("PLL%d start failed @ 0x%lx: 0x%x\n", 15167839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 15177839a050SYann Gautier return -ETIMEDOUT; 15187839a050SYann Gautier } 15197839a050SYann Gautier } 15207839a050SYann Gautier 15217839a050SYann Gautier /* Start the requested output */ 15227839a050SYann Gautier mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); 15237839a050SYann Gautier 15247839a050SYann Gautier return 0; 15257839a050SYann Gautier } 15267839a050SYann Gautier 15270d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) 15287839a050SYann Gautier { 15290d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15300d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1531dfdb057aSYann Gautier uint64_t timeout; 15327839a050SYann Gautier 15337839a050SYann Gautier /* Stop all output */ 15347839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 15357839a050SYann Gautier RCC_PLLNCR_DIVREN); 15367839a050SYann Gautier 15377839a050SYann Gautier /* Stop PLL */ 15387839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); 15397839a050SYann Gautier 1540dfdb057aSYann Gautier timeout = timeout_init_us(PLLRDY_TIMEOUT); 15417839a050SYann Gautier /* Wait PLL stopped */ 15427839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { 1543dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 15440d21680cSYann Gautier ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n", 15457839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 15467839a050SYann Gautier return -ETIMEDOUT; 15477839a050SYann Gautier } 15487839a050SYann Gautier } 15497839a050SYann Gautier 15507839a050SYann Gautier return 0; 15517839a050SYann Gautier } 15527839a050SYann Gautier 15530d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, 15547839a050SYann Gautier uint32_t *pllcfg) 15557839a050SYann Gautier { 15560d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15570d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 15587839a050SYann Gautier uint32_t value; 15597839a050SYann Gautier 15607839a050SYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 15617839a050SYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 15627839a050SYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 15637839a050SYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 15647839a050SYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 15657839a050SYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 15660d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr2, value); 15677839a050SYann Gautier } 15687839a050SYann Gautier 15690d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, 15707839a050SYann Gautier uint32_t *pllcfg, uint32_t fracv) 15717839a050SYann Gautier { 15720d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15730d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 15740d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 15757839a050SYann Gautier unsigned long refclk; 15767839a050SYann Gautier uint32_t ifrge = 0; 15777839a050SYann Gautier uint32_t src, value; 15787839a050SYann Gautier 15790d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & 15807839a050SYann Gautier RCC_SELR_REFCLK_SRC_MASK; 15817839a050SYann Gautier 15820d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 15837839a050SYann Gautier (pllcfg[PLLCFG_M] + 1U); 15847839a050SYann Gautier 15857839a050SYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 15867839a050SYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 15877839a050SYann Gautier return -EINVAL; 15887839a050SYann Gautier } 15897839a050SYann Gautier 15907839a050SYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 15917839a050SYann Gautier ifrge = 1U; 15927839a050SYann Gautier } 15937839a050SYann Gautier 15947839a050SYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 15957839a050SYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 15967839a050SYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 15977839a050SYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 15987839a050SYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 15997839a050SYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 16000d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr1, value); 16017839a050SYann Gautier 16027839a050SYann Gautier /* Fractional configuration */ 16037839a050SYann Gautier value = 0; 16040d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 16057839a050SYann Gautier 16067839a050SYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 16070d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 16087839a050SYann Gautier 16097839a050SYann Gautier value |= RCC_PLLNFRACR_FRACLE; 16100d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 16117839a050SYann Gautier 16120d21680cSYann Gautier stm32mp1_pll_config_output(pll_id, pllcfg); 16137839a050SYann Gautier 16147839a050SYann Gautier return 0; 16157839a050SYann Gautier } 16167839a050SYann Gautier 16170d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) 16187839a050SYann Gautier { 16190d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 16207839a050SYann Gautier uint32_t pllxcsg = 0; 16217839a050SYann Gautier 16227839a050SYann Gautier pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & 16237839a050SYann Gautier RCC_PLLNCSGR_MOD_PER_MASK; 16247839a050SYann Gautier 16257839a050SYann Gautier pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & 16267839a050SYann Gautier RCC_PLLNCSGR_INC_STEP_MASK; 16277839a050SYann Gautier 16287839a050SYann Gautier pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & 16297839a050SYann Gautier RCC_PLLNCSGR_SSCG_MODE_MASK; 16307839a050SYann Gautier 16310d21680cSYann Gautier mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); 1632dd98aec8SYann Gautier 1633dd98aec8SYann Gautier mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, 1634dd98aec8SYann Gautier RCC_PLLNCR_SSCG_CTRL); 16357839a050SYann Gautier } 16367839a050SYann Gautier 16370d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc) 16387839a050SYann Gautier { 16390d21680cSYann Gautier uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 1640dfdb057aSYann Gautier uint64_t timeout; 16417839a050SYann Gautier 16420d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, 16437839a050SYann Gautier clksrc & RCC_SELR_SRC_MASK); 16447839a050SYann Gautier 1645dfdb057aSYann Gautier timeout = timeout_init_us(CLKSRC_TIMEOUT); 16460d21680cSYann Gautier while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { 1647dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 16480d21680cSYann Gautier ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, 16490d21680cSYann Gautier clksrc_address, mmio_read_32(clksrc_address)); 16507839a050SYann Gautier return -ETIMEDOUT; 16517839a050SYann Gautier } 16527839a050SYann Gautier } 16537839a050SYann Gautier 16547839a050SYann Gautier return 0; 16557839a050SYann Gautier } 16567839a050SYann Gautier 16570d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) 16587839a050SYann Gautier { 1659dfdb057aSYann Gautier uint64_t timeout; 16607839a050SYann Gautier 16617839a050SYann Gautier mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, 16627839a050SYann Gautier clkdiv & RCC_DIVR_DIV_MASK); 16637839a050SYann Gautier 1664dfdb057aSYann Gautier timeout = timeout_init_us(CLKDIV_TIMEOUT); 16657839a050SYann Gautier while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { 1666dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 16670d21680cSYann Gautier ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", 16687839a050SYann Gautier clkdiv, address, mmio_read_32(address)); 16697839a050SYann Gautier return -ETIMEDOUT; 16707839a050SYann Gautier } 16717839a050SYann Gautier } 16727839a050SYann Gautier 16737839a050SYann Gautier return 0; 16747839a050SYann Gautier } 16757839a050SYann Gautier 16760d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) 16777839a050SYann Gautier { 16780d21680cSYann Gautier uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 16797839a050SYann Gautier 16807839a050SYann Gautier /* 16817839a050SYann Gautier * Binding clksrc : 16827839a050SYann Gautier * bit15-4 offset 16837839a050SYann Gautier * bit3: disable 16847839a050SYann Gautier * bit2-0: MCOSEL[2:0] 16857839a050SYann Gautier */ 16867839a050SYann Gautier if ((clksrc & 0x8U) != 0U) { 16870d21680cSYann Gautier mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); 16887839a050SYann Gautier } else { 16890d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, 16907839a050SYann Gautier RCC_MCOCFG_MCOSRC_MASK, 16917839a050SYann Gautier clksrc & RCC_MCOCFG_MCOSRC_MASK); 16920d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, 16937839a050SYann Gautier RCC_MCOCFG_MCODIV_MASK, 16947839a050SYann Gautier clkdiv << RCC_MCOCFG_MCODIV_SHIFT); 16950d21680cSYann Gautier mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); 16967839a050SYann Gautier } 16977839a050SYann Gautier } 16987839a050SYann Gautier 16990d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) 17007839a050SYann Gautier { 17010d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; 17027839a050SYann Gautier 17037839a050SYann Gautier if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || 17047839a050SYann Gautier (clksrc != (uint32_t)CLK_RTC_DISABLED)) { 17057839a050SYann Gautier mmio_clrsetbits_32(address, 17067839a050SYann Gautier RCC_BDCR_RTCSRC_MASK, 170715509093SYann Gautier (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); 17087839a050SYann Gautier 17097839a050SYann Gautier mmio_setbits_32(address, RCC_BDCR_RTCCKEN); 17107839a050SYann Gautier } 17117839a050SYann Gautier 17127839a050SYann Gautier if (lse_css) { 17137839a050SYann Gautier mmio_setbits_32(address, RCC_BDCR_LSECSSON); 17147839a050SYann Gautier } 17157839a050SYann Gautier } 17167839a050SYann Gautier 17170d21680cSYann Gautier static void stm32mp1_stgen_config(void) 17187839a050SYann Gautier { 17197839a050SYann Gautier uint32_t cntfid0; 17207839a050SYann Gautier unsigned long rate; 17217839a050SYann Gautier unsigned long long counter; 17227839a050SYann Gautier 1723ade9ce03SYann Gautier cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); 17240d21680cSYann Gautier rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); 17250d21680cSYann Gautier 17260d21680cSYann Gautier if (cntfid0 == rate) { 17270d21680cSYann Gautier return; 17280d21680cSYann Gautier } 17290d21680cSYann Gautier 1730ade9ce03SYann Gautier mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 1731ade9ce03SYann Gautier counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF); 1732ade9ce03SYann Gautier counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32; 17337839a050SYann Gautier counter = (counter * rate / cntfid0); 17340d21680cSYann Gautier 1735ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); 1736ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); 1737ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); 1738ade9ce03SYann Gautier mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 17397839a050SYann Gautier 17407839a050SYann Gautier write_cntfrq((u_register_t)rate); 17417839a050SYann Gautier 17427839a050SYann Gautier /* Need to update timer with new frequency */ 17437839a050SYann Gautier generic_delay_timer_init(); 17447839a050SYann Gautier } 17457839a050SYann Gautier 17467839a050SYann Gautier void stm32mp1_stgen_increment(unsigned long long offset_in_ms) 17477839a050SYann Gautier { 17487839a050SYann Gautier unsigned long long cnt; 17497839a050SYann Gautier 1750ade9ce03SYann Gautier cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | 1751ade9ce03SYann Gautier mmio_read_32(STGEN_BASE + CNTCVL_OFF); 17527839a050SYann Gautier 1753ade9ce03SYann Gautier cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U; 17547839a050SYann Gautier 1755ade9ce03SYann Gautier mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 1756ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); 1757ade9ce03SYann Gautier mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); 1758ade9ce03SYann Gautier mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); 17597839a050SYann Gautier } 17607839a050SYann Gautier 17610d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs) 17627839a050SYann Gautier { 17630d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); 17647839a050SYann Gautier uint32_t value = pkcs & 0xFU; 17657839a050SYann Gautier uint32_t mask = 0xFU; 17667839a050SYann Gautier 17677839a050SYann Gautier if ((pkcs & BIT(31)) != 0U) { 17687839a050SYann Gautier mask <<= 4; 17697839a050SYann Gautier value <<= 4; 17707839a050SYann Gautier } 17717839a050SYann Gautier 17727839a050SYann Gautier mmio_clrsetbits_32(address, mask, value); 17737839a050SYann Gautier } 17747839a050SYann Gautier 17757839a050SYann Gautier int stm32mp1_clk_init(void) 17767839a050SYann Gautier { 17770d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 17787839a050SYann Gautier unsigned int clksrc[CLKSRC_NB]; 17797839a050SYann Gautier unsigned int clkdiv[CLKDIV_NB]; 17807839a050SYann Gautier unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; 17817839a050SYann Gautier int plloff[_PLL_NB]; 17827839a050SYann Gautier int ret, len; 17837839a050SYann Gautier enum stm32mp1_pll_id i; 17847839a050SYann Gautier bool lse_css = false; 17850d21680cSYann Gautier bool pll3_preserve = false; 17860d21680cSYann Gautier bool pll4_preserve = false; 17870d21680cSYann Gautier bool pll4_bootrom = false; 17883e6fab43SYann Gautier const fdt32_t *pkcs_cell; 178952a616b4SAndre Przywara void *fdt; 1790bf1af154SPatrick Delaunay int stgen_p = stm32mp1_clk_get_parent(STGEN_K); 1791bf1af154SPatrick Delaunay int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K); 179252a616b4SAndre Przywara 179352a616b4SAndre Przywara if (fdt_get_address(&fdt) == 0) { 17948f97c4faSYann Gautier return -FDT_ERR_NOTFOUND; 179552a616b4SAndre Przywara } 17967839a050SYann Gautier 17977839a050SYann Gautier /* Check status field to disable security */ 17987839a050SYann Gautier if (!fdt_get_rcc_secure_status()) { 17990d21680cSYann Gautier mmio_write_32(rcc_base + RCC_TZCR, 0); 18007839a050SYann Gautier } 18017839a050SYann Gautier 180252a616b4SAndre Przywara ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, 180352a616b4SAndre Przywara clksrc); 18047839a050SYann Gautier if (ret < 0) { 18057839a050SYann Gautier return -FDT_ERR_NOTFOUND; 18067839a050SYann Gautier } 18077839a050SYann Gautier 180852a616b4SAndre Przywara ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, 180952a616b4SAndre Przywara clkdiv); 18107839a050SYann Gautier if (ret < 0) { 18117839a050SYann Gautier return -FDT_ERR_NOTFOUND; 18127839a050SYann Gautier } 18137839a050SYann Gautier 18147839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 18157839a050SYann Gautier char name[12]; 18167839a050SYann Gautier 181739b6cc66SAntonio Nino Diaz snprintf(name, sizeof(name), "st,pll@%d", i); 18187839a050SYann Gautier plloff[i] = fdt_rcc_subnode_offset(name); 18197839a050SYann Gautier 18207839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 18217839a050SYann Gautier continue; 18227839a050SYann Gautier } 18237839a050SYann Gautier 182452a616b4SAndre Przywara ret = fdt_read_uint32_array(fdt, plloff[i], "cfg", 182552a616b4SAndre Przywara (int)PLLCFG_NB, pllcfg[i]); 18267839a050SYann Gautier if (ret < 0) { 18277839a050SYann Gautier return -FDT_ERR_NOTFOUND; 18287839a050SYann Gautier } 18297839a050SYann Gautier } 18307839a050SYann Gautier 18310d21680cSYann Gautier stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); 18320d21680cSYann Gautier stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); 18337839a050SYann Gautier 18347839a050SYann Gautier /* 18357839a050SYann Gautier * Switch ON oscillator found in device-tree. 18367839a050SYann Gautier * Note: HSI already ON after BootROM stage. 18377839a050SYann Gautier */ 18380d21680cSYann Gautier if (stm32mp1_osc[_LSI] != 0U) { 18390d21680cSYann Gautier stm32mp1_lsi_set(true); 18407839a050SYann Gautier } 18410d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 18420d21680cSYann Gautier bool bypass, digbyp; 18437839a050SYann Gautier uint32_t lsedrv; 18447839a050SYann Gautier 18457839a050SYann Gautier bypass = fdt_osc_read_bool(_LSE, "st,bypass"); 18460d21680cSYann Gautier digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); 18477839a050SYann Gautier lse_css = fdt_osc_read_bool(_LSE, "st,css"); 18487839a050SYann Gautier lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", 18497839a050SYann Gautier LSEDRV_MEDIUM_HIGH); 18500d21680cSYann Gautier stm32mp1_lse_enable(bypass, digbyp, lsedrv); 18517839a050SYann Gautier } 18520d21680cSYann Gautier if (stm32mp1_osc[_HSE] != 0U) { 18530d21680cSYann Gautier bool bypass, digbyp, css; 18547839a050SYann Gautier 18550d21680cSYann Gautier bypass = fdt_osc_read_bool(_HSE, "st,bypass"); 18560d21680cSYann Gautier digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); 18570d21680cSYann Gautier css = fdt_osc_read_bool(_HSE, "st,css"); 18580d21680cSYann Gautier stm32mp1_hse_enable(bypass, digbyp, css); 18597839a050SYann Gautier } 18607839a050SYann Gautier /* 18617839a050SYann Gautier * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) 18627839a050SYann Gautier * => switch on CSI even if node is not present in device tree 18637839a050SYann Gautier */ 18640d21680cSYann Gautier stm32mp1_csi_set(true); 18657839a050SYann Gautier 18667839a050SYann Gautier /* Come back to HSI */ 18670d21680cSYann Gautier ret = stm32mp1_set_clksrc(CLK_MPU_HSI); 18687839a050SYann Gautier if (ret != 0) { 18697839a050SYann Gautier return ret; 18707839a050SYann Gautier } 18710d21680cSYann Gautier ret = stm32mp1_set_clksrc(CLK_AXI_HSI); 18727839a050SYann Gautier if (ret != 0) { 18737839a050SYann Gautier return ret; 18747839a050SYann Gautier } 1875b053a22eSYann Gautier ret = stm32mp1_set_clksrc(CLK_MCU_HSI); 1876b053a22eSYann Gautier if (ret != 0) { 1877b053a22eSYann Gautier return ret; 1878b053a22eSYann Gautier } 18797839a050SYann Gautier 18800d21680cSYann Gautier if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & 18810d21680cSYann Gautier RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { 18820d21680cSYann Gautier pll3_preserve = stm32mp1_check_pll_conf(_PLL3, 18830d21680cSYann Gautier clksrc[CLKSRC_PLL3], 18840d21680cSYann Gautier pllcfg[_PLL3], 18850d21680cSYann Gautier plloff[_PLL3]); 18860d21680cSYann Gautier pll4_preserve = stm32mp1_check_pll_conf(_PLL4, 18870d21680cSYann Gautier clksrc[CLKSRC_PLL4], 18880d21680cSYann Gautier pllcfg[_PLL4], 18890d21680cSYann Gautier plloff[_PLL4]); 18900d21680cSYann Gautier } 1891bf1af154SPatrick Delaunay /* Don't initialize PLL4, when used by BOOTROM */ 1892bf1af154SPatrick Delaunay if ((stm32mp_get_boot_itf_selected() == 1893bf1af154SPatrick Delaunay BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && 1894bf1af154SPatrick Delaunay ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { 1895bf1af154SPatrick Delaunay pll4_bootrom = true; 1896bf1af154SPatrick Delaunay pll4_preserve = true; 1897bf1af154SPatrick Delaunay } 18980d21680cSYann Gautier 18997839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 19000d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 19010d21680cSYann Gautier ((i == _PLL4) && pll4_preserve)) { 19027839a050SYann Gautier continue; 19030d21680cSYann Gautier } 19040d21680cSYann Gautier 19050d21680cSYann Gautier ret = stm32mp1_pll_stop(i); 19067839a050SYann Gautier if (ret != 0) { 19077839a050SYann Gautier return ret; 19087839a050SYann Gautier } 19097839a050SYann Gautier } 19107839a050SYann Gautier 19117839a050SYann Gautier /* Configure HSIDIV */ 19120d21680cSYann Gautier if (stm32mp1_osc[_HSI] != 0U) { 19130d21680cSYann Gautier ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); 19147839a050SYann Gautier if (ret != 0) { 19157839a050SYann Gautier return ret; 19167839a050SYann Gautier } 19170d21680cSYann Gautier stm32mp1_stgen_config(); 19187839a050SYann Gautier } 19197839a050SYann Gautier 19207839a050SYann Gautier /* Select DIV */ 19217839a050SYann Gautier /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ 19220d21680cSYann Gautier mmio_write_32(rcc_base + RCC_MPCKDIVR, 19237839a050SYann Gautier clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); 19240d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); 19257839a050SYann Gautier if (ret != 0) { 19267839a050SYann Gautier return ret; 19277839a050SYann Gautier } 19280d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); 19297839a050SYann Gautier if (ret != 0) { 19307839a050SYann Gautier return ret; 19317839a050SYann Gautier } 19320d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); 19337839a050SYann Gautier if (ret != 0) { 19347839a050SYann Gautier return ret; 19357839a050SYann Gautier } 1936b053a22eSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); 1937b053a22eSYann Gautier if (ret != 0) { 1938b053a22eSYann Gautier return ret; 1939b053a22eSYann Gautier } 19400d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); 19417839a050SYann Gautier if (ret != 0) { 19427839a050SYann Gautier return ret; 19437839a050SYann Gautier } 19440d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); 19457839a050SYann Gautier if (ret != 0) { 19467839a050SYann Gautier return ret; 19477839a050SYann Gautier } 19480d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); 19497839a050SYann Gautier if (ret != 0) { 19507839a050SYann Gautier return ret; 19517839a050SYann Gautier } 19527839a050SYann Gautier 19537839a050SYann Gautier /* No ready bit for RTC */ 19540d21680cSYann Gautier mmio_write_32(rcc_base + RCC_RTCDIVR, 19557839a050SYann Gautier clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); 19567839a050SYann Gautier 19577839a050SYann Gautier /* Configure PLLs source */ 19580d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); 19597839a050SYann Gautier if (ret != 0) { 19607839a050SYann Gautier return ret; 19617839a050SYann Gautier } 19627839a050SYann Gautier 19630d21680cSYann Gautier if (!pll3_preserve) { 19640d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); 19657839a050SYann Gautier if (ret != 0) { 19667839a050SYann Gautier return ret; 19677839a050SYann Gautier } 19680d21680cSYann Gautier } 19690d21680cSYann Gautier 19700d21680cSYann Gautier if (!pll4_preserve) { 19710d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); 19720d21680cSYann Gautier if (ret != 0) { 19730d21680cSYann Gautier return ret; 19740d21680cSYann Gautier } 19750d21680cSYann Gautier } 19767839a050SYann Gautier 19777839a050SYann Gautier /* Configure and start PLLs */ 19787839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 19797839a050SYann Gautier uint32_t fracv; 19807839a050SYann Gautier uint32_t csg[PLLCSG_NB]; 19817839a050SYann Gautier 19820d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 19830d21680cSYann Gautier ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { 19840d21680cSYann Gautier continue; 19850d21680cSYann Gautier } 19860d21680cSYann Gautier 19877839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 19887839a050SYann Gautier continue; 19897839a050SYann Gautier } 19907839a050SYann Gautier 19910d21680cSYann Gautier if ((i == _PLL4) && pll4_bootrom) { 19920d21680cSYann Gautier /* Set output divider if not done by the Bootrom */ 19930d21680cSYann Gautier stm32mp1_pll_config_output(i, pllcfg[i]); 19940d21680cSYann Gautier continue; 19950d21680cSYann Gautier } 19960d21680cSYann Gautier 1997be858cffSAndre Przywara fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0); 19987839a050SYann Gautier 19990d21680cSYann Gautier ret = stm32mp1_pll_config(i, pllcfg[i], fracv); 20007839a050SYann Gautier if (ret != 0) { 20017839a050SYann Gautier return ret; 20027839a050SYann Gautier } 200352a616b4SAndre Przywara ret = fdt_read_uint32_array(fdt, plloff[i], "csg", 200452a616b4SAndre Przywara (uint32_t)PLLCSG_NB, csg); 20057839a050SYann Gautier if (ret == 0) { 20060d21680cSYann Gautier stm32mp1_pll_csg(i, csg); 20077839a050SYann Gautier } else if (ret != -FDT_ERR_NOTFOUND) { 20087839a050SYann Gautier return ret; 20097839a050SYann Gautier } 20107839a050SYann Gautier 20110d21680cSYann Gautier stm32mp1_pll_start(i); 20127839a050SYann Gautier } 20137839a050SYann Gautier /* Wait and start PLLs ouptut when ready */ 20147839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 20157839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 20167839a050SYann Gautier continue; 20177839a050SYann Gautier } 20187839a050SYann Gautier 20190d21680cSYann Gautier ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); 20207839a050SYann Gautier if (ret != 0) { 20217839a050SYann Gautier return ret; 20227839a050SYann Gautier } 20237839a050SYann Gautier } 20247839a050SYann Gautier /* Wait LSE ready before to use it */ 20250d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 20260d21680cSYann Gautier stm32mp1_lse_wait(); 20277839a050SYann Gautier } 20287839a050SYann Gautier 20297839a050SYann Gautier /* Configure with expected clock source */ 20300d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); 20317839a050SYann Gautier if (ret != 0) { 20327839a050SYann Gautier return ret; 20337839a050SYann Gautier } 20340d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); 20357839a050SYann Gautier if (ret != 0) { 20367839a050SYann Gautier return ret; 20377839a050SYann Gautier } 2038b053a22eSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); 2039b053a22eSYann Gautier if (ret != 0) { 2040b053a22eSYann Gautier return ret; 2041b053a22eSYann Gautier } 20420d21680cSYann Gautier stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); 20437839a050SYann Gautier 20447839a050SYann Gautier /* Configure PKCK */ 20457839a050SYann Gautier pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); 20467839a050SYann Gautier if (pkcs_cell != NULL) { 20477839a050SYann Gautier bool ckper_disabled = false; 20487839a050SYann Gautier uint32_t j; 2049bf1af154SPatrick Delaunay uint32_t usbreg_bootrom = 0U; 2050bf1af154SPatrick Delaunay 2051bf1af154SPatrick Delaunay if (pll4_bootrom) { 2052bf1af154SPatrick Delaunay usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR); 2053bf1af154SPatrick Delaunay } 20547839a050SYann Gautier 20557839a050SYann Gautier for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { 20563e6fab43SYann Gautier uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); 20577839a050SYann Gautier 20587839a050SYann Gautier if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { 20597839a050SYann Gautier ckper_disabled = true; 20607839a050SYann Gautier continue; 20617839a050SYann Gautier } 20620d21680cSYann Gautier stm32mp1_pkcs_config(pkcs); 20637839a050SYann Gautier } 20647839a050SYann Gautier 20657839a050SYann Gautier /* 20667839a050SYann Gautier * CKPER is source for some peripheral clocks 20677839a050SYann Gautier * (FMC-NAND / QPSI-NOR) and switching source is allowed 20687839a050SYann Gautier * only if previous clock is still ON 20697839a050SYann Gautier * => deactivated CKPER only after switching clock 20707839a050SYann Gautier */ 20717839a050SYann Gautier if (ckper_disabled) { 20720d21680cSYann Gautier stm32mp1_pkcs_config(CLK_CKPER_DISABLED); 20737839a050SYann Gautier } 2074bf1af154SPatrick Delaunay 2075bf1af154SPatrick Delaunay if (pll4_bootrom) { 2076bf1af154SPatrick Delaunay uint32_t usbreg_value, usbreg_mask; 2077bf1af154SPatrick Delaunay const struct stm32mp1_clk_sel *sel; 2078bf1af154SPatrick Delaunay 2079bf1af154SPatrick Delaunay sel = clk_sel_ref(_USBPHY_SEL); 2080bf1af154SPatrick Delaunay usbreg_mask = (uint32_t)sel->msk << sel->src; 2081bf1af154SPatrick Delaunay sel = clk_sel_ref(_USBO_SEL); 2082bf1af154SPatrick Delaunay usbreg_mask |= (uint32_t)sel->msk << sel->src; 2083bf1af154SPatrick Delaunay 2084bf1af154SPatrick Delaunay usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) & 2085bf1af154SPatrick Delaunay usbreg_mask; 2086bf1af154SPatrick Delaunay usbreg_bootrom &= usbreg_mask; 2087bf1af154SPatrick Delaunay if (usbreg_bootrom != usbreg_value) { 2088bf1af154SPatrick Delaunay VERBOSE("forbidden new USB clk path\n"); 2089bf1af154SPatrick Delaunay VERBOSE("vs bootrom on USB boot\n"); 2090bf1af154SPatrick Delaunay return -FDT_ERR_BADVALUE; 2091bf1af154SPatrick Delaunay } 2092bf1af154SPatrick Delaunay } 20937839a050SYann Gautier } 20947839a050SYann Gautier 20957839a050SYann Gautier /* Switch OFF HSI if not found in device-tree */ 20960d21680cSYann Gautier if (stm32mp1_osc[_HSI] == 0U) { 20970d21680cSYann Gautier stm32mp1_hsi_set(false); 20987839a050SYann Gautier } 20990d21680cSYann Gautier stm32mp1_stgen_config(); 21007839a050SYann Gautier 21017839a050SYann Gautier /* Software Self-Refresh mode (SSR) during DDR initilialization */ 21020d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, 21037839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_MASK, 21047839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SSR << 21057839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SHIFT); 21067839a050SYann Gautier 21077839a050SYann Gautier return 0; 21087839a050SYann Gautier } 21097839a050SYann Gautier 21107839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name, 21117839a050SYann Gautier enum stm32mp_osc_id index) 21127839a050SYann Gautier { 21137839a050SYann Gautier uint32_t frequency; 21147839a050SYann Gautier 21150d21680cSYann Gautier if (fdt_osc_read_freq(name, &frequency) == 0) { 21160d21680cSYann Gautier stm32mp1_osc[index] = frequency; 21177839a050SYann Gautier } 21187839a050SYann Gautier } 21197839a050SYann Gautier 21207839a050SYann Gautier static void stm32mp1_osc_init(void) 21217839a050SYann Gautier { 21227839a050SYann Gautier enum stm32mp_osc_id i; 21237839a050SYann Gautier 21247839a050SYann Gautier for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { 21250d21680cSYann Gautier stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); 21267839a050SYann Gautier } 21277839a050SYann Gautier } 21287839a050SYann Gautier 212937e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES 213037e8295aSEtienne Carriere /* 213137e8295aSEtienne Carriere * Get the parent ID of the target parent clock, for tagging as secure 213237e8295aSEtienne Carriere * shared clock dependencies. 213337e8295aSEtienne Carriere */ 213437e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id) 213537e8295aSEtienne Carriere { 213637e8295aSEtienne Carriere enum stm32mp1_parent_sel s = _UNKNOWN_SEL; 213737e8295aSEtienne Carriere enum stm32mp1_pll_id pll_id; 213837e8295aSEtienne Carriere uint32_t p_sel; 213937e8295aSEtienne Carriere uintptr_t rcc_base = stm32mp_rcc_base(); 214037e8295aSEtienne Carriere 214137e8295aSEtienne Carriere switch (parent_id) { 214237e8295aSEtienne Carriere case _ACLK: 214337e8295aSEtienne Carriere case _PCLK4: 214437e8295aSEtienne Carriere case _PCLK5: 214537e8295aSEtienne Carriere s = _AXIS_SEL; 214637e8295aSEtienne Carriere break; 214737e8295aSEtienne Carriere case _PLL1_P: 214837e8295aSEtienne Carriere case _PLL1_Q: 214937e8295aSEtienne Carriere case _PLL1_R: 215037e8295aSEtienne Carriere pll_id = _PLL1; 215137e8295aSEtienne Carriere break; 215237e8295aSEtienne Carriere case _PLL2_P: 215337e8295aSEtienne Carriere case _PLL2_Q: 215437e8295aSEtienne Carriere case _PLL2_R: 215537e8295aSEtienne Carriere pll_id = _PLL2; 215637e8295aSEtienne Carriere break; 215737e8295aSEtienne Carriere case _PLL3_P: 215837e8295aSEtienne Carriere case _PLL3_Q: 215937e8295aSEtienne Carriere case _PLL3_R: 216037e8295aSEtienne Carriere pll_id = _PLL3; 216137e8295aSEtienne Carriere break; 216237e8295aSEtienne Carriere case _PLL4_P: 216337e8295aSEtienne Carriere case _PLL4_Q: 216437e8295aSEtienne Carriere case _PLL4_R: 216537e8295aSEtienne Carriere pll_id = _PLL4; 216637e8295aSEtienne Carriere break; 216737e8295aSEtienne Carriere case _PCLK1: 216837e8295aSEtienne Carriere case _PCLK2: 216937e8295aSEtienne Carriere case _HCLK2: 217037e8295aSEtienne Carriere case _HCLK6: 217137e8295aSEtienne Carriere case _CK_PER: 217237e8295aSEtienne Carriere case _CK_MPU: 217337e8295aSEtienne Carriere case _CK_MCU: 217437e8295aSEtienne Carriere case _USB_PHY_48: 217537e8295aSEtienne Carriere /* We do not expect to access these */ 217637e8295aSEtienne Carriere panic(); 217737e8295aSEtienne Carriere break; 217837e8295aSEtienne Carriere default: 217937e8295aSEtienne Carriere /* Other parents have no parent */ 218037e8295aSEtienne Carriere return -1; 218137e8295aSEtienne Carriere } 218237e8295aSEtienne Carriere 218337e8295aSEtienne Carriere if (s != _UNKNOWN_SEL) { 218437e8295aSEtienne Carriere const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); 218537e8295aSEtienne Carriere 218637e8295aSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & 218737e8295aSEtienne Carriere sel->msk; 218837e8295aSEtienne Carriere 218937e8295aSEtienne Carriere if (p_sel < sel->nb_parent) { 219037e8295aSEtienne Carriere return (int)sel->parent[p_sel]; 219137e8295aSEtienne Carriere } 219237e8295aSEtienne Carriere } else { 219337e8295aSEtienne Carriere const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 219437e8295aSEtienne Carriere 219537e8295aSEtienne Carriere p_sel = mmio_read_32(rcc_base + pll->rckxselr) & 219637e8295aSEtienne Carriere RCC_SELR_REFCLK_SRC_MASK; 219737e8295aSEtienne Carriere 219837e8295aSEtienne Carriere if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { 219937e8295aSEtienne Carriere return (int)pll->refclk[p_sel]; 220037e8295aSEtienne Carriere } 220137e8295aSEtienne Carriere } 220237e8295aSEtienne Carriere 220337e8295aSEtienne Carriere VERBOSE("No parent selected for %s\n", 220437e8295aSEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 220537e8295aSEtienne Carriere 220637e8295aSEtienne Carriere return -1; 220737e8295aSEtienne Carriere } 220837e8295aSEtienne Carriere 220937e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id) 221037e8295aSEtienne Carriere { 221137e8295aSEtienne Carriere int grandparent_id; 221237e8295aSEtienne Carriere 221337e8295aSEtienne Carriere switch (parent_id) { 221437e8295aSEtienne Carriere case _PLL3_P: 221537e8295aSEtienne Carriere case _PLL3_Q: 221637e8295aSEtienne Carriere case _PLL3_R: 221737e8295aSEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 221837e8295aSEtienne Carriere break; 221937e8295aSEtienne Carriere 222037e8295aSEtienne Carriere /* These clocks are always secure when RCC is secure */ 222137e8295aSEtienne Carriere case _ACLK: 222237e8295aSEtienne Carriere case _HCLK2: 222337e8295aSEtienne Carriere case _HCLK6: 222437e8295aSEtienne Carriere case _PCLK4: 222537e8295aSEtienne Carriere case _PCLK5: 222637e8295aSEtienne Carriere case _PLL1_P: 222737e8295aSEtienne Carriere case _PLL1_Q: 222837e8295aSEtienne Carriere case _PLL1_R: 222937e8295aSEtienne Carriere case _PLL2_P: 223037e8295aSEtienne Carriere case _PLL2_Q: 223137e8295aSEtienne Carriere case _PLL2_R: 223237e8295aSEtienne Carriere case _HSI: 223337e8295aSEtienne Carriere case _HSI_KER: 223437e8295aSEtienne Carriere case _LSI: 223537e8295aSEtienne Carriere case _CSI: 223637e8295aSEtienne Carriere case _CSI_KER: 223737e8295aSEtienne Carriere case _HSE: 223837e8295aSEtienne Carriere case _HSE_KER: 223937e8295aSEtienne Carriere case _HSE_KER_DIV2: 2240cbd2e8a6SGabriel Fernandez case _HSE_RTC: 224137e8295aSEtienne Carriere case _LSE: 224237e8295aSEtienne Carriere break; 224337e8295aSEtienne Carriere 224437e8295aSEtienne Carriere default: 224537e8295aSEtienne Carriere VERBOSE("Cannot secure parent clock %s\n", 224637e8295aSEtienne Carriere stm32mp1_clk_parent_name[parent_id]); 224737e8295aSEtienne Carriere panic(); 224837e8295aSEtienne Carriere } 224937e8295aSEtienne Carriere 225037e8295aSEtienne Carriere grandparent_id = get_parent_id_parent(parent_id); 225137e8295aSEtienne Carriere if (grandparent_id >= 0) { 225237e8295aSEtienne Carriere secure_parent_clocks(grandparent_id); 225337e8295aSEtienne Carriere } 225437e8295aSEtienne Carriere } 225537e8295aSEtienne Carriere 225637e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id) 225737e8295aSEtienne Carriere { 225837e8295aSEtienne Carriere int parent_id; 225937e8295aSEtienne Carriere 226037e8295aSEtienne Carriere if (!stm32mp1_rcc_is_secure()) { 226137e8295aSEtienne Carriere return; 226237e8295aSEtienne Carriere } 226337e8295aSEtienne Carriere 226437e8295aSEtienne Carriere switch (clock_id) { 226537e8295aSEtienne Carriere case PLL1: 226637e8295aSEtienne Carriere case PLL2: 226737e8295aSEtienne Carriere /* PLL1/PLL2 are always secure: nothing to do */ 226837e8295aSEtienne Carriere break; 226937e8295aSEtienne Carriere case PLL3: 227037e8295aSEtienne Carriere stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); 227137e8295aSEtienne Carriere break; 227237e8295aSEtienne Carriere case PLL4: 227337e8295aSEtienne Carriere ERROR("PLL4 cannot be secured\n"); 227437e8295aSEtienne Carriere panic(); 227537e8295aSEtienne Carriere break; 227637e8295aSEtienne Carriere default: 227737e8295aSEtienne Carriere /* Others are expected gateable clock */ 227837e8295aSEtienne Carriere parent_id = stm32mp1_clk_get_parent(clock_id); 227937e8295aSEtienne Carriere if (parent_id < 0) { 228037e8295aSEtienne Carriere INFO("No parent found for clock %lu\n", clock_id); 228137e8295aSEtienne Carriere } else { 228237e8295aSEtienne Carriere secure_parent_clocks(parent_id); 228337e8295aSEtienne Carriere } 228437e8295aSEtienne Carriere break; 228537e8295aSEtienne Carriere } 228637e8295aSEtienne Carriere } 228737e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */ 228837e8295aSEtienne Carriere 22896cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void) 22906cb45f89SYann Gautier { 2291033b6c3aSEtienne Carriere unsigned int idx; 2292033b6c3aSEtienne Carriere const unsigned long secure_enable[] = { 2293033b6c3aSEtienne Carriere AXIDCG, 2294033b6c3aSEtienne Carriere BSEC, 2295033b6c3aSEtienne Carriere DDRC1, DDRC1LP, 2296033b6c3aSEtienne Carriere DDRC2, DDRC2LP, 2297033b6c3aSEtienne Carriere DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, 2298033b6c3aSEtienne Carriere DDRPHYC, DDRPHYCLP, 2299373f06beSLionel Debieve RTCAPB, 2300033b6c3aSEtienne Carriere TZC1, TZC2, 2301033b6c3aSEtienne Carriere TZPC, 2302033b6c3aSEtienne Carriere STGEN_K, 2303033b6c3aSEtienne Carriere }; 2304033b6c3aSEtienne Carriere 2305033b6c3aSEtienne Carriere for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { 2306033b6c3aSEtienne Carriere stm32mp_clk_enable(secure_enable[idx]); 2307033b6c3aSEtienne Carriere } 23086cb45f89SYann Gautier } 23096cb45f89SYann Gautier 2310*33667d29SYann Gautier static const struct clk_ops stm32mp_clk_ops = { 2311*33667d29SYann Gautier .enable = stm32mp_clk_enable, 2312*33667d29SYann Gautier .disable = stm32mp_clk_disable, 2313*33667d29SYann Gautier .is_enabled = stm32mp_clk_is_enabled, 2314*33667d29SYann Gautier .get_rate = stm32mp_clk_get_rate, 2315*33667d29SYann Gautier .get_parent = stm32mp1_clk_get_parent, 2316*33667d29SYann Gautier }; 2317*33667d29SYann Gautier 23187839a050SYann Gautier int stm32mp1_clk_probe(void) 23197839a050SYann Gautier { 23207839a050SYann Gautier stm32mp1_osc_init(); 23217839a050SYann Gautier 23226cb45f89SYann Gautier sync_earlyboot_clocks_state(); 23236cb45f89SYann Gautier 2324*33667d29SYann Gautier clk_register(&stm32mp_clk_ops); 2325*33667d29SYann Gautier 23267839a050SYann Gautier return 0; 23277839a050SYann Gautier } 2328