17839a050SYann Gautier /* 23f9c9784SYann Gautier * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved 37839a050SYann Gautier * 47839a050SYann Gautier * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 57839a050SYann Gautier */ 67839a050SYann Gautier 77839a050SYann Gautier #include <assert.h> 87839a050SYann Gautier #include <errno.h> 97839a050SYann Gautier #include <stdint.h> 1039b6cc66SAntonio Nino Diaz #include <stdio.h> 1109d40e0eSAntonio Nino Diaz 1209d40e0eSAntonio Nino Diaz #include <libfdt.h> 1309d40e0eSAntonio Nino Diaz 146e6ab282SYann Gautier #include <platform_def.h> 156e6ab282SYann Gautier 1609d40e0eSAntonio Nino Diaz #include <arch.h> 1709d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1809d40e0eSAntonio Nino Diaz #include <common/debug.h> 1952a616b4SAndre Przywara #include <common/fdt_wrappers.h> 2009d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 2109d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h> 22447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h> 2309d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h> 2409d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h> 2509d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h> 2609d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 270d21680cSYann Gautier #include <lib/spinlock.h> 2809d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 2909d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 3009d40e0eSAntonio Nino Diaz 317839a050SYann Gautier #define MAX_HSI_HZ 64000000 320d21680cSYann Gautier #define USB_PHY_48_MHZ 48000000 337839a050SYann Gautier 34dfdb057aSYann Gautier #define TIMEOUT_US_200MS U(200000) 35dfdb057aSYann Gautier #define TIMEOUT_US_1S U(1000000) 367839a050SYann Gautier 37dfdb057aSYann Gautier #define PLLRDY_TIMEOUT TIMEOUT_US_200MS 38dfdb057aSYann Gautier #define CLKSRC_TIMEOUT TIMEOUT_US_200MS 39dfdb057aSYann Gautier #define CLKDIV_TIMEOUT TIMEOUT_US_200MS 40dfdb057aSYann Gautier #define HSIDIV_TIMEOUT TIMEOUT_US_200MS 41dfdb057aSYann Gautier #define OSCRDY_TIMEOUT TIMEOUT_US_1S 427839a050SYann Gautier 43f66358afSYann Gautier const char *stm32mp_osc_node_label[NB_OSC] = { 44f66358afSYann Gautier [_LSI] = "clk-lsi", 45f66358afSYann Gautier [_LSE] = "clk-lse", 46f66358afSYann Gautier [_HSI] = "clk-hsi", 47f66358afSYann Gautier [_HSE] = "clk-hse", 48f66358afSYann Gautier [_CSI] = "clk-csi", 49f66358afSYann Gautier [_I2S_CKIN] = "i2s_ckin", 50f66358afSYann Gautier }; 51f66358afSYann Gautier 527839a050SYann Gautier enum stm32mp1_parent_id { 537839a050SYann Gautier /* Oscillators are defined in enum stm32mp_osc_id */ 547839a050SYann Gautier 557839a050SYann Gautier /* Other parent source */ 567839a050SYann Gautier _HSI_KER = NB_OSC, 577839a050SYann Gautier _HSE_KER, 587839a050SYann Gautier _HSE_KER_DIV2, 597839a050SYann Gautier _CSI_KER, 607839a050SYann Gautier _PLL1_P, 617839a050SYann Gautier _PLL1_Q, 627839a050SYann Gautier _PLL1_R, 637839a050SYann Gautier _PLL2_P, 647839a050SYann Gautier _PLL2_Q, 657839a050SYann Gautier _PLL2_R, 667839a050SYann Gautier _PLL3_P, 677839a050SYann Gautier _PLL3_Q, 687839a050SYann Gautier _PLL3_R, 697839a050SYann Gautier _PLL4_P, 707839a050SYann Gautier _PLL4_Q, 717839a050SYann Gautier _PLL4_R, 727839a050SYann Gautier _ACLK, 737839a050SYann Gautier _PCLK1, 747839a050SYann Gautier _PCLK2, 757839a050SYann Gautier _PCLK3, 767839a050SYann Gautier _PCLK4, 777839a050SYann Gautier _PCLK5, 787839a050SYann Gautier _HCLK6, 797839a050SYann Gautier _HCLK2, 807839a050SYann Gautier _CK_PER, 817839a050SYann Gautier _CK_MPU, 82b053a22eSYann Gautier _CK_MCU, 830d21680cSYann Gautier _USB_PHY_48, 847839a050SYann Gautier _PARENT_NB, 857839a050SYann Gautier _UNKNOWN_ID = 0xff, 867839a050SYann Gautier }; 877839a050SYann Gautier 880d21680cSYann Gautier /* Lists only the parent clock we are interested in */ 897839a050SYann Gautier enum stm32mp1_parent_sel { 900d21680cSYann Gautier _I2C12_SEL, 910d21680cSYann Gautier _I2C35_SEL, 920d21680cSYann Gautier _STGEN_SEL, 937839a050SYann Gautier _I2C46_SEL, 940d21680cSYann Gautier _SPI6_SEL, 95d4151d2fSYann Gautier _UART1_SEL, 960d21680cSYann Gautier _RNG1_SEL, 977839a050SYann Gautier _UART6_SEL, 987839a050SYann Gautier _UART24_SEL, 997839a050SYann Gautier _UART35_SEL, 1007839a050SYann Gautier _UART78_SEL, 1017839a050SYann Gautier _SDMMC12_SEL, 1027839a050SYann Gautier _SDMMC3_SEL, 1037839a050SYann Gautier _QSPI_SEL, 1047839a050SYann Gautier _FMC_SEL, 105d4151d2fSYann Gautier _AXIS_SEL, 106d4151d2fSYann Gautier _MCUS_SEL, 1077839a050SYann Gautier _USBPHY_SEL, 1087839a050SYann Gautier _USBO_SEL, 1098fbcd9e4SEtienne Carriere _MPU_SEL, 1108fbcd9e4SEtienne Carriere _PER_SEL, 111016af006SEtienne Carriere _RTC_SEL, 1127839a050SYann Gautier _PARENT_SEL_NB, 1137839a050SYann Gautier _UNKNOWN_SEL = 0xff, 1147839a050SYann Gautier }; 1157839a050SYann Gautier 1168fbcd9e4SEtienne Carriere /* State the parent clock ID straight related to a clock */ 1178fbcd9e4SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = { 1188fbcd9e4SEtienne Carriere [_HSE] = CK_HSE, 1198fbcd9e4SEtienne Carriere [_HSI] = CK_HSI, 1208fbcd9e4SEtienne Carriere [_CSI] = CK_CSI, 1218fbcd9e4SEtienne Carriere [_LSE] = CK_LSE, 1228fbcd9e4SEtienne Carriere [_LSI] = CK_LSI, 1238fbcd9e4SEtienne Carriere [_I2S_CKIN] = _UNKNOWN_ID, 1248fbcd9e4SEtienne Carriere [_USB_PHY_48] = _UNKNOWN_ID, 1258fbcd9e4SEtienne Carriere [_HSI_KER] = CK_HSI, 1268fbcd9e4SEtienne Carriere [_HSE_KER] = CK_HSE, 1278fbcd9e4SEtienne Carriere [_HSE_KER_DIV2] = CK_HSE_DIV2, 1288fbcd9e4SEtienne Carriere [_CSI_KER] = CK_CSI, 1298fbcd9e4SEtienne Carriere [_PLL1_P] = PLL1_P, 1308fbcd9e4SEtienne Carriere [_PLL1_Q] = PLL1_Q, 1318fbcd9e4SEtienne Carriere [_PLL1_R] = PLL1_R, 1328fbcd9e4SEtienne Carriere [_PLL2_P] = PLL2_P, 1338fbcd9e4SEtienne Carriere [_PLL2_Q] = PLL2_Q, 1348fbcd9e4SEtienne Carriere [_PLL2_R] = PLL2_R, 1358fbcd9e4SEtienne Carriere [_PLL3_P] = PLL3_P, 1368fbcd9e4SEtienne Carriere [_PLL3_Q] = PLL3_Q, 1378fbcd9e4SEtienne Carriere [_PLL3_R] = PLL3_R, 1388fbcd9e4SEtienne Carriere [_PLL4_P] = PLL4_P, 1398fbcd9e4SEtienne Carriere [_PLL4_Q] = PLL4_Q, 1408fbcd9e4SEtienne Carriere [_PLL4_R] = PLL4_R, 1418fbcd9e4SEtienne Carriere [_ACLK] = CK_AXI, 1428fbcd9e4SEtienne Carriere [_PCLK1] = CK_AXI, 1438fbcd9e4SEtienne Carriere [_PCLK2] = CK_AXI, 1448fbcd9e4SEtienne Carriere [_PCLK3] = CK_AXI, 1458fbcd9e4SEtienne Carriere [_PCLK4] = CK_AXI, 1468fbcd9e4SEtienne Carriere [_PCLK5] = CK_AXI, 1478fbcd9e4SEtienne Carriere [_CK_PER] = CK_PER, 1488fbcd9e4SEtienne Carriere [_CK_MPU] = CK_MPU, 1498fbcd9e4SEtienne Carriere [_CK_MCU] = CK_MCU, 1508fbcd9e4SEtienne Carriere }; 1518fbcd9e4SEtienne Carriere 1528fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id) 1538fbcd9e4SEtienne Carriere { 1548fbcd9e4SEtienne Carriere unsigned int n; 1558fbcd9e4SEtienne Carriere 1568fbcd9e4SEtienne Carriere for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { 1578fbcd9e4SEtienne Carriere if (parent_id_clock_id[n] == id) { 1588fbcd9e4SEtienne Carriere return n; 1598fbcd9e4SEtienne Carriere } 1608fbcd9e4SEtienne Carriere } 1618fbcd9e4SEtienne Carriere 1628fbcd9e4SEtienne Carriere return _UNKNOWN_ID; 1638fbcd9e4SEtienne Carriere } 1648fbcd9e4SEtienne Carriere 1657839a050SYann Gautier enum stm32mp1_pll_id { 1667839a050SYann Gautier _PLL1, 1677839a050SYann Gautier _PLL2, 1687839a050SYann Gautier _PLL3, 1697839a050SYann Gautier _PLL4, 1707839a050SYann Gautier _PLL_NB 1717839a050SYann Gautier }; 1727839a050SYann Gautier 1737839a050SYann Gautier enum stm32mp1_div_id { 1747839a050SYann Gautier _DIV_P, 1757839a050SYann Gautier _DIV_Q, 1767839a050SYann Gautier _DIV_R, 1777839a050SYann Gautier _DIV_NB, 1787839a050SYann Gautier }; 1797839a050SYann Gautier 1807839a050SYann Gautier enum stm32mp1_clksrc_id { 1817839a050SYann Gautier CLKSRC_MPU, 1827839a050SYann Gautier CLKSRC_AXI, 183b053a22eSYann Gautier CLKSRC_MCU, 1847839a050SYann Gautier CLKSRC_PLL12, 1857839a050SYann Gautier CLKSRC_PLL3, 1867839a050SYann Gautier CLKSRC_PLL4, 1877839a050SYann Gautier CLKSRC_RTC, 1887839a050SYann Gautier CLKSRC_MCO1, 1897839a050SYann Gautier CLKSRC_MCO2, 1907839a050SYann Gautier CLKSRC_NB 1917839a050SYann Gautier }; 1927839a050SYann Gautier 1937839a050SYann Gautier enum stm32mp1_clkdiv_id { 1947839a050SYann Gautier CLKDIV_MPU, 1957839a050SYann Gautier CLKDIV_AXI, 196b053a22eSYann Gautier CLKDIV_MCU, 1977839a050SYann Gautier CLKDIV_APB1, 1987839a050SYann Gautier CLKDIV_APB2, 1997839a050SYann Gautier CLKDIV_APB3, 2007839a050SYann Gautier CLKDIV_APB4, 2017839a050SYann Gautier CLKDIV_APB5, 2027839a050SYann Gautier CLKDIV_RTC, 2037839a050SYann Gautier CLKDIV_MCO1, 2047839a050SYann Gautier CLKDIV_MCO2, 2057839a050SYann Gautier CLKDIV_NB 2067839a050SYann Gautier }; 2077839a050SYann Gautier 2087839a050SYann Gautier enum stm32mp1_pllcfg { 2097839a050SYann Gautier PLLCFG_M, 2107839a050SYann Gautier PLLCFG_N, 2117839a050SYann Gautier PLLCFG_P, 2127839a050SYann Gautier PLLCFG_Q, 2137839a050SYann Gautier PLLCFG_R, 2147839a050SYann Gautier PLLCFG_O, 2157839a050SYann Gautier PLLCFG_NB 2167839a050SYann Gautier }; 2177839a050SYann Gautier 2187839a050SYann Gautier enum stm32mp1_pllcsg { 2197839a050SYann Gautier PLLCSG_MOD_PER, 2207839a050SYann Gautier PLLCSG_INC_STEP, 2217839a050SYann Gautier PLLCSG_SSCG_MODE, 2227839a050SYann Gautier PLLCSG_NB 2237839a050SYann Gautier }; 2247839a050SYann Gautier 2257839a050SYann Gautier enum stm32mp1_plltype { 2267839a050SYann Gautier PLL_800, 2277839a050SYann Gautier PLL_1600, 2287839a050SYann Gautier PLL_TYPE_NB 2297839a050SYann Gautier }; 2307839a050SYann Gautier 2317839a050SYann Gautier struct stm32mp1_pll { 2327839a050SYann Gautier uint8_t refclk_min; 2337839a050SYann Gautier uint8_t refclk_max; 2347839a050SYann Gautier uint8_t divn_max; 2357839a050SYann Gautier }; 2367839a050SYann Gautier 2377839a050SYann Gautier struct stm32mp1_clk_gate { 2387839a050SYann Gautier uint16_t offset; 2397839a050SYann Gautier uint8_t bit; 2407839a050SYann Gautier uint8_t index; 2417839a050SYann Gautier uint8_t set_clr; 2420d21680cSYann Gautier uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ 2430d21680cSYann Gautier uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ 2447839a050SYann Gautier }; 2457839a050SYann Gautier 2467839a050SYann Gautier struct stm32mp1_clk_sel { 2477839a050SYann Gautier uint16_t offset; 2487839a050SYann Gautier uint8_t src; 2497839a050SYann Gautier uint8_t msk; 2507839a050SYann Gautier uint8_t nb_parent; 2517839a050SYann Gautier const uint8_t *parent; 2527839a050SYann Gautier }; 2537839a050SYann Gautier 2547839a050SYann Gautier #define REFCLK_SIZE 4 2557839a050SYann Gautier struct stm32mp1_clk_pll { 2567839a050SYann Gautier enum stm32mp1_plltype plltype; 2577839a050SYann Gautier uint16_t rckxselr; 2587839a050SYann Gautier uint16_t pllxcfgr1; 2597839a050SYann Gautier uint16_t pllxcfgr2; 2607839a050SYann Gautier uint16_t pllxfracr; 2617839a050SYann Gautier uint16_t pllxcr; 2627839a050SYann Gautier uint16_t pllxcsgr; 2637839a050SYann Gautier enum stm32mp_osc_id refclk[REFCLK_SIZE]; 2647839a050SYann Gautier }; 2657839a050SYann Gautier 2660d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */ 2670d21680cSYann Gautier #define _CLK_SELEC(off, b, idx, s) \ 2687839a050SYann Gautier { \ 2697839a050SYann Gautier .offset = (off), \ 2707839a050SYann Gautier .bit = (b), \ 2717839a050SYann Gautier .index = (idx), \ 2727839a050SYann Gautier .set_clr = 0, \ 2737839a050SYann Gautier .sel = (s), \ 2747839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 2757839a050SYann Gautier } 2767839a050SYann Gautier 2770d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */ 2780d21680cSYann Gautier #define _CLK_FIXED(off, b, idx, f) \ 2797839a050SYann Gautier { \ 2807839a050SYann Gautier .offset = (off), \ 2817839a050SYann Gautier .bit = (b), \ 2827839a050SYann Gautier .index = (idx), \ 2837839a050SYann Gautier .set_clr = 0, \ 2847839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 2857839a050SYann Gautier .fixed = (f), \ 2867839a050SYann Gautier } 2877839a050SYann Gautier 2880d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */ 2890d21680cSYann Gautier #define _CLK_SC_SELEC(off, b, idx, s) \ 2907839a050SYann Gautier { \ 2917839a050SYann Gautier .offset = (off), \ 2927839a050SYann Gautier .bit = (b), \ 2937839a050SYann Gautier .index = (idx), \ 2947839a050SYann Gautier .set_clr = 1, \ 2957839a050SYann Gautier .sel = (s), \ 2967839a050SYann Gautier .fixed = _UNKNOWN_ID, \ 2977839a050SYann Gautier } 2987839a050SYann Gautier 2990d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */ 3000d21680cSYann Gautier #define _CLK_SC_FIXED(off, b, idx, f) \ 3017839a050SYann Gautier { \ 3027839a050SYann Gautier .offset = (off), \ 3037839a050SYann Gautier .bit = (b), \ 3047839a050SYann Gautier .index = (idx), \ 3057839a050SYann Gautier .set_clr = 1, \ 3067839a050SYann Gautier .sel = _UNKNOWN_SEL, \ 3077839a050SYann Gautier .fixed = (f), \ 3087839a050SYann Gautier } 3097839a050SYann Gautier 310d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ 311d4151d2fSYann Gautier [_ ## _label ## _SEL] = { \ 312d4151d2fSYann Gautier .offset = _rcc_selr, \ 313d4151d2fSYann Gautier .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ 3148ae08dcdSEtienne Carriere .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ 3158ae08dcdSEtienne Carriere (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ 316d4151d2fSYann Gautier .parent = (_parents), \ 317d4151d2fSYann Gautier .nb_parent = ARRAY_SIZE(_parents) \ 3187839a050SYann Gautier } 3197839a050SYann Gautier 3200d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3, \ 3217839a050SYann Gautier off4, off5, off6, \ 3227839a050SYann Gautier p1, p2, p3, p4) \ 3237839a050SYann Gautier [(idx)] = { \ 3247839a050SYann Gautier .plltype = (type), \ 3257839a050SYann Gautier .rckxselr = (off1), \ 3267839a050SYann Gautier .pllxcfgr1 = (off2), \ 3277839a050SYann Gautier .pllxcfgr2 = (off3), \ 3287839a050SYann Gautier .pllxfracr = (off4), \ 3297839a050SYann Gautier .pllxcr = (off5), \ 3307839a050SYann Gautier .pllxcsgr = (off6), \ 3317839a050SYann Gautier .refclk[0] = (p1), \ 3327839a050SYann Gautier .refclk[1] = (p2), \ 3337839a050SYann Gautier .refclk[2] = (p3), \ 3347839a050SYann Gautier .refclk[3] = (p4), \ 3357839a050SYann Gautier } 3367839a050SYann Gautier 3370d21680cSYann Gautier #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) 3380d21680cSYann Gautier 3397839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { 3400d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), 3410d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), 3420d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), 3430d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), 3440d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), 3450d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), 3460d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), 3470d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), 3480d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), 3490d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), 3500d21680cSYann Gautier _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), 3517839a050SYann Gautier 3520d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), 3530d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), 3540d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), 3550d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), 3560d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), 3570d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), 3580d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), 3590d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), 3600d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), 3610d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), 3620d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), 3637839a050SYann Gautier 3640d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), 3650d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), 3667839a050SYann Gautier 367f33b2433SYann Gautier _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), 368f33b2433SYann Gautier 3690d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), 3700d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), 3710d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), 3727839a050SYann Gautier 3730d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), 3740d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), 3750d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), 376d4151d2fSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), 3770d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), 3780d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), 3790d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), 3800d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), 3810d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), 3820d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), 3830d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), 3847839a050SYann Gautier 3850d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), 3860d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), 3877839a050SYann Gautier 3880d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), 3890d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), 3900d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), 3910d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), 3920d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), 3930d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), 3940d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), 3950d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), 3960d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), 3970d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), 3980d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), 3997839a050SYann Gautier 4000d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), 4010d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), 4020d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), 4030d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), 4040d21680cSYann Gautier _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), 4057839a050SYann Gautier 4060d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), 4070d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), 4080d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), 4090d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), 4100d21680cSYann Gautier _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), 4117839a050SYann Gautier 412016af006SEtienne Carriere _CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL), 4130d21680cSYann Gautier _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), 4147839a050SYann Gautier }; 4157839a050SYann Gautier 4160d21680cSYann Gautier static const uint8_t i2c12_parents[] = { 4170d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 4180d21680cSYann Gautier }; 4190d21680cSYann Gautier 4200d21680cSYann Gautier static const uint8_t i2c35_parents[] = { 4210d21680cSYann Gautier _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER 4220d21680cSYann Gautier }; 4230d21680cSYann Gautier 4240d21680cSYann Gautier static const uint8_t stgen_parents[] = { 4250d21680cSYann Gautier _HSI_KER, _HSE_KER 4260d21680cSYann Gautier }; 4270d21680cSYann Gautier 4280d21680cSYann Gautier static const uint8_t i2c46_parents[] = { 4290d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER 4300d21680cSYann Gautier }; 4310d21680cSYann Gautier 4320d21680cSYann Gautier static const uint8_t spi6_parents[] = { 4330d21680cSYann Gautier _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q 4340d21680cSYann Gautier }; 4350d21680cSYann Gautier 4360d21680cSYann Gautier static const uint8_t usart1_parents[] = { 4370d21680cSYann Gautier _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER 4380d21680cSYann Gautier }; 4390d21680cSYann Gautier 4400d21680cSYann Gautier static const uint8_t rng1_parents[] = { 4410d21680cSYann Gautier _CSI, _PLL4_R, _LSE, _LSI 4420d21680cSYann Gautier }; 4430d21680cSYann Gautier 4440d21680cSYann Gautier static const uint8_t uart6_parents[] = { 4450d21680cSYann Gautier _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 4460d21680cSYann Gautier }; 4470d21680cSYann Gautier 4480d21680cSYann Gautier static const uint8_t uart234578_parents[] = { 4490d21680cSYann Gautier _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER 4500d21680cSYann Gautier }; 4510d21680cSYann Gautier 4520d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = { 4530d21680cSYann Gautier _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER 4540d21680cSYann Gautier }; 4550d21680cSYann Gautier 4560d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = { 4570d21680cSYann Gautier _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER 4580d21680cSYann Gautier }; 4590d21680cSYann Gautier 4600d21680cSYann Gautier static const uint8_t qspi_parents[] = { 4610d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 4620d21680cSYann Gautier }; 4630d21680cSYann Gautier 4640d21680cSYann Gautier static const uint8_t fmc_parents[] = { 4650d21680cSYann Gautier _ACLK, _PLL3_R, _PLL4_P, _CK_PER 4660d21680cSYann Gautier }; 4670d21680cSYann Gautier 4680d21680cSYann Gautier static const uint8_t ass_parents[] = { 4690d21680cSYann Gautier _HSI, _HSE, _PLL2 4700d21680cSYann Gautier }; 4710d21680cSYann Gautier 472b053a22eSYann Gautier static const uint8_t mss_parents[] = { 473b053a22eSYann Gautier _HSI, _HSE, _CSI, _PLL3 474b053a22eSYann Gautier }; 475b053a22eSYann Gautier 4760d21680cSYann Gautier static const uint8_t usbphy_parents[] = { 4770d21680cSYann Gautier _HSE_KER, _PLL4_R, _HSE_KER_DIV2 4780d21680cSYann Gautier }; 4790d21680cSYann Gautier 4800d21680cSYann Gautier static const uint8_t usbo_parents[] = { 4810d21680cSYann Gautier _PLL4_R, _USB_PHY_48 4820d21680cSYann Gautier }; 4837839a050SYann Gautier 4848fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = { 4858fbcd9e4SEtienne Carriere _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ 4868fbcd9e4SEtienne Carriere }; 4878fbcd9e4SEtienne Carriere 4888fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = { 4898fbcd9e4SEtienne Carriere _HSI, _HSE, _CSI, 4908fbcd9e4SEtienne Carriere }; 4918fbcd9e4SEtienne Carriere 492016af006SEtienne Carriere static const uint8_t rtc_parents[] = { 493016af006SEtienne Carriere _UNKNOWN_ID, _LSE, _LSI, _HSE 494016af006SEtienne Carriere }; 495016af006SEtienne Carriere 4967839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { 497d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), 498d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), 499d4151d2fSYann Gautier _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), 500d4151d2fSYann Gautier _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), 501d4151d2fSYann Gautier _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), 502d4151d2fSYann Gautier _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), 503d4151d2fSYann Gautier _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), 5048fbcd9e4SEtienne Carriere _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), 5058fbcd9e4SEtienne Carriere _CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents), 506016af006SEtienne Carriere _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), 507d4151d2fSYann Gautier _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), 508d4151d2fSYann Gautier _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), 509d4151d2fSYann Gautier _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), 510d4151d2fSYann Gautier _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), 511d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), 512d4151d2fSYann Gautier _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), 513d4151d2fSYann Gautier _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), 514d4151d2fSYann Gautier _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), 515d4151d2fSYann Gautier _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents), 516d4151d2fSYann Gautier _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents), 517d4151d2fSYann Gautier _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), 518d4151d2fSYann Gautier _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), 5197839a050SYann Gautier }; 5207839a050SYann Gautier 5217839a050SYann Gautier /* Define characteristic of PLL according type */ 5227839a050SYann Gautier #define DIVN_MIN 24 5237839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { 5247839a050SYann Gautier [PLL_800] = { 5257839a050SYann Gautier .refclk_min = 4, 5267839a050SYann Gautier .refclk_max = 16, 5277839a050SYann Gautier .divn_max = 99, 5287839a050SYann Gautier }, 5297839a050SYann Gautier [PLL_1600] = { 5307839a050SYann Gautier .refclk_min = 8, 5317839a050SYann Gautier .refclk_max = 16, 5327839a050SYann Gautier .divn_max = 199, 5337839a050SYann Gautier }, 5347839a050SYann Gautier }; 5357839a050SYann Gautier 5367839a050SYann Gautier /* PLLNCFGR2 register divider by output */ 5377839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = { 5387839a050SYann Gautier [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, 5397839a050SYann Gautier [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, 5400d21680cSYann Gautier [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, 5417839a050SYann Gautier }; 5427839a050SYann Gautier 5437839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { 5440d21680cSYann Gautier _CLK_PLL(_PLL1, PLL_1600, 5457839a050SYann Gautier RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, 5467839a050SYann Gautier RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, 5477839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 5480d21680cSYann Gautier _CLK_PLL(_PLL2, PLL_1600, 5497839a050SYann Gautier RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, 5507839a050SYann Gautier RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, 5517839a050SYann Gautier _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), 5520d21680cSYann Gautier _CLK_PLL(_PLL3, PLL_800, 5537839a050SYann Gautier RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, 5547839a050SYann Gautier RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, 5557839a050SYann Gautier _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), 5560d21680cSYann Gautier _CLK_PLL(_PLL4, PLL_800, 5577839a050SYann Gautier RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, 5587839a050SYann Gautier RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, 5597839a050SYann Gautier _HSI, _HSE, _CSI, _I2S_CKIN), 5607839a050SYann Gautier }; 5617839a050SYann Gautier 5627839a050SYann Gautier /* Prescaler table lookups for clock computation */ 563b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ 564b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = { 565b053a22eSYann Gautier 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 566b053a22eSYann Gautier }; 5677839a050SYann Gautier 5687839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ 5697839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div 5707839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div 5717839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = { 5727839a050SYann Gautier 0, 1, 2, 3, 4, 4, 4, 4 5737839a050SYann Gautier }; 5747839a050SYann Gautier 5757839a050SYann Gautier /* div = /1 /2 /3 /4 */ 5767839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = { 5777839a050SYann Gautier 1, 2, 3, 4, 4, 4, 4, 4 5787839a050SYann Gautier }; 5797839a050SYann Gautier 5800d21680cSYann Gautier /* RCC clock device driver private */ 5810d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC]; 5820d21680cSYann Gautier static struct spinlock reg_lock; 5830d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES]; 5840d21680cSYann Gautier static struct spinlock refcount_lock; 5857839a050SYann Gautier 5860d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) 5870d21680cSYann Gautier { 5880d21680cSYann Gautier return &stm32mp1_clk_gate[idx]; 5890d21680cSYann Gautier } 5907839a050SYann Gautier 5910d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) 5920d21680cSYann Gautier { 5930d21680cSYann Gautier return &stm32mp1_clk_sel[idx]; 5940d21680cSYann Gautier } 5950d21680cSYann Gautier 5960d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) 5970d21680cSYann Gautier { 5980d21680cSYann Gautier return &stm32mp1_clk_pll[idx]; 5990d21680cSYann Gautier } 6000d21680cSYann Gautier 6010d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock) 6020d21680cSYann Gautier { 603e463d3f4SYann Gautier if (stm32mp_lock_available()) { 6040d21680cSYann Gautier /* Assume interrupts are masked */ 6050d21680cSYann Gautier spin_lock(lock); 6060d21680cSYann Gautier } 607e463d3f4SYann Gautier } 6080d21680cSYann Gautier 6090d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock) 6100d21680cSYann Gautier { 611e463d3f4SYann Gautier if (stm32mp_lock_available()) { 6120d21680cSYann Gautier spin_unlock(lock); 6130d21680cSYann Gautier } 614e463d3f4SYann Gautier } 6150d21680cSYann Gautier 6160d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void) 6170d21680cSYann Gautier { 6180d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 6190d21680cSYann Gautier 6200d21680cSYann Gautier return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0; 6210d21680cSYann Gautier } 6220d21680cSYann Gautier 623b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void) 624b053a22eSYann Gautier { 625b053a22eSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 626b053a22eSYann Gautier 627b053a22eSYann Gautier return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0; 628b053a22eSYann Gautier } 629b053a22eSYann Gautier 6300d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void) 6310d21680cSYann Gautier { 6320d21680cSYann Gautier stm32mp1_clk_lock(®_lock); 6330d21680cSYann Gautier } 6340d21680cSYann Gautier 6350d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void) 6360d21680cSYann Gautier { 6370d21680cSYann Gautier stm32mp1_clk_unlock(®_lock); 6380d21680cSYann Gautier } 6390d21680cSYann Gautier 6400d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) 6417839a050SYann Gautier { 6427839a050SYann Gautier if (idx >= NB_OSC) { 6437839a050SYann Gautier return 0; 6447839a050SYann Gautier } 6457839a050SYann Gautier 6460d21680cSYann Gautier return stm32mp1_osc[idx]; 6477839a050SYann Gautier } 6487839a050SYann Gautier 6490d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id) 6507839a050SYann Gautier { 6510d21680cSYann Gautier unsigned int i; 6527839a050SYann Gautier 6530d21680cSYann Gautier for (i = 0U; i < NB_GATES; i++) { 6540d21680cSYann Gautier if (gate_ref(i)->index == id) { 6557839a050SYann Gautier return i; 6567839a050SYann Gautier } 6577839a050SYann Gautier } 6587839a050SYann Gautier 6597839a050SYann Gautier ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id); 6607839a050SYann Gautier 6617839a050SYann Gautier return -EINVAL; 6627839a050SYann Gautier } 6637839a050SYann Gautier 6640d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) 6657839a050SYann Gautier { 6660d21680cSYann Gautier return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); 6677839a050SYann Gautier } 6687839a050SYann Gautier 6690d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) 6707839a050SYann Gautier { 6710d21680cSYann Gautier return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); 6727839a050SYann Gautier } 6737839a050SYann Gautier 6740d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id) 6757839a050SYann Gautier { 6760d21680cSYann Gautier const struct stm32mp1_clk_sel *sel; 6778fbcd9e4SEtienne Carriere uint32_t p_sel; 6787839a050SYann Gautier int i; 6797839a050SYann Gautier enum stm32mp1_parent_id p; 6807839a050SYann Gautier enum stm32mp1_parent_sel s; 6810d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 6827839a050SYann Gautier 6838fbcd9e4SEtienne Carriere /* Few non gateable clock have a static parent ID, find them */ 6848fbcd9e4SEtienne Carriere i = (int)clock_id2parent_id(id); 6858fbcd9e4SEtienne Carriere if (i != _UNKNOWN_ID) { 6868fbcd9e4SEtienne Carriere return i; 6877839a050SYann Gautier } 6887839a050SYann Gautier 6890d21680cSYann Gautier i = stm32mp1_clk_get_gated_id(id); 6907839a050SYann Gautier if (i < 0) { 6910d21680cSYann Gautier panic(); 6927839a050SYann Gautier } 6937839a050SYann Gautier 6940d21680cSYann Gautier p = stm32mp1_clk_get_fixed_parent(i); 6957839a050SYann Gautier if (p < _PARENT_NB) { 6967839a050SYann Gautier return (int)p; 6977839a050SYann Gautier } 6987839a050SYann Gautier 6990d21680cSYann Gautier s = stm32mp1_clk_get_sel(i); 7000d21680cSYann Gautier if (s == _UNKNOWN_SEL) { 7010d21680cSYann Gautier return -EINVAL; 7020d21680cSYann Gautier } 7037839a050SYann Gautier if (s >= _PARENT_SEL_NB) { 7040d21680cSYann Gautier panic(); 7057839a050SYann Gautier } 7067839a050SYann Gautier 7070d21680cSYann Gautier sel = clk_sel_ref(s); 7088ae08dcdSEtienne Carriere p_sel = (mmio_read_32(rcc_base + sel->offset) & 7098ae08dcdSEtienne Carriere (sel->msk << sel->src)) >> sel->src; 7100d21680cSYann Gautier if (p_sel < sel->nb_parent) { 7110d21680cSYann Gautier return (int)sel->parent[p_sel]; 7127839a050SYann Gautier } 7137839a050SYann Gautier 7147839a050SYann Gautier return -EINVAL; 7157839a050SYann Gautier } 7167839a050SYann Gautier 7170d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) 7187839a050SYann Gautier { 7190d21680cSYann Gautier uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); 7200d21680cSYann Gautier uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; 7217839a050SYann Gautier 7220d21680cSYann Gautier return stm32mp1_clk_get_fixed(pll->refclk[src]); 7237839a050SYann Gautier } 7247839a050SYann Gautier 7257839a050SYann Gautier /* 7267839a050SYann Gautier * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL 7277839a050SYann Gautier * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) 7287839a050SYann Gautier * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) 7297839a050SYann Gautier * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) 7307839a050SYann Gautier */ 7310d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) 7327839a050SYann Gautier { 7337839a050SYann Gautier unsigned long refclk, fvco; 7347839a050SYann Gautier uint32_t cfgr1, fracr, divm, divn; 7350d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 7367839a050SYann Gautier 7370d21680cSYann Gautier cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); 7380d21680cSYann Gautier fracr = mmio_read_32(rcc_base + pll->pllxfracr); 7397839a050SYann Gautier 7407839a050SYann Gautier divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; 7417839a050SYann Gautier divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; 7427839a050SYann Gautier 7430d21680cSYann Gautier refclk = stm32mp1_pll_get_fref(pll); 7447839a050SYann Gautier 7457839a050SYann Gautier /* 7467839a050SYann Gautier * With FRACV : 7477839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) 7487839a050SYann Gautier * Without FRACV 7497839a050SYann Gautier * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) 7507839a050SYann Gautier */ 7517839a050SYann Gautier if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { 7520d21680cSYann Gautier uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> 7530d21680cSYann Gautier RCC_PLLNFRACR_FRACV_SHIFT; 7547839a050SYann Gautier unsigned long long numerator, denominator; 7557839a050SYann Gautier 7560d21680cSYann Gautier numerator = (((unsigned long long)divn + 1U) << 13) + fracv; 7570d21680cSYann Gautier numerator = refclk * numerator; 7587839a050SYann Gautier denominator = ((unsigned long long)divm + 1U) << 13; 7597839a050SYann Gautier fvco = (unsigned long)(numerator / denominator); 7607839a050SYann Gautier } else { 7617839a050SYann Gautier fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); 7627839a050SYann Gautier } 7637839a050SYann Gautier 7647839a050SYann Gautier return fvco; 7657839a050SYann Gautier } 7667839a050SYann Gautier 7670d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, 7687839a050SYann Gautier enum stm32mp1_div_id div_id) 7697839a050SYann Gautier { 7700d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 7717839a050SYann Gautier unsigned long dfout; 7727839a050SYann Gautier uint32_t cfgr2, divy; 7737839a050SYann Gautier 7747839a050SYann Gautier if (div_id >= _DIV_NB) { 7757839a050SYann Gautier return 0; 7767839a050SYann Gautier } 7777839a050SYann Gautier 7780d21680cSYann Gautier cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); 7797839a050SYann Gautier divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; 7807839a050SYann Gautier 7810d21680cSYann Gautier dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); 7827839a050SYann Gautier 7837839a050SYann Gautier return dfout; 7847839a050SYann Gautier } 7857839a050SYann Gautier 7860d21680cSYann Gautier static unsigned long get_clock_rate(int p) 7877839a050SYann Gautier { 7887839a050SYann Gautier uint32_t reg, clkdiv; 7897839a050SYann Gautier unsigned long clock = 0; 7900d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 7917839a050SYann Gautier 7927839a050SYann Gautier switch (p) { 7937839a050SYann Gautier case _CK_MPU: 7947839a050SYann Gautier /* MPU sub system */ 7950d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKSELR); 7967839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 7977839a050SYann Gautier case RCC_MPCKSELR_HSI: 7980d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 7997839a050SYann Gautier break; 8007839a050SYann Gautier case RCC_MPCKSELR_HSE: 8010d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 8027839a050SYann Gautier break; 8037839a050SYann Gautier case RCC_MPCKSELR_PLL: 8040d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 8057839a050SYann Gautier break; 8067839a050SYann Gautier case RCC_MPCKSELR_PLL_MPUDIV: 8070d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 8087839a050SYann Gautier 8090d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); 8107839a050SYann Gautier clkdiv = reg & RCC_MPUDIV_MASK; 8117839a050SYann Gautier if (clkdiv != 0U) { 8127839a050SYann Gautier clock /= stm32mp1_mpu_div[clkdiv]; 8137839a050SYann Gautier } 8147839a050SYann Gautier break; 8157839a050SYann Gautier default: 8167839a050SYann Gautier break; 8177839a050SYann Gautier } 8187839a050SYann Gautier break; 8197839a050SYann Gautier /* AXI sub system */ 8207839a050SYann Gautier case _ACLK: 8217839a050SYann Gautier case _HCLK2: 8227839a050SYann Gautier case _HCLK6: 8237839a050SYann Gautier case _PCLK4: 8247839a050SYann Gautier case _PCLK5: 8250d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); 8267839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 8277839a050SYann Gautier case RCC_ASSCKSELR_HSI: 8280d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 8297839a050SYann Gautier break; 8307839a050SYann Gautier case RCC_ASSCKSELR_HSE: 8310d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 8327839a050SYann Gautier break; 8337839a050SYann Gautier case RCC_ASSCKSELR_PLL: 8340d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 8357839a050SYann Gautier break; 8367839a050SYann Gautier default: 8377839a050SYann Gautier break; 8387839a050SYann Gautier } 8397839a050SYann Gautier 8407839a050SYann Gautier /* System clock divider */ 8410d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_AXIDIVR); 8427839a050SYann Gautier clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; 8437839a050SYann Gautier 8447839a050SYann Gautier switch (p) { 8457839a050SYann Gautier case _PCLK4: 8460d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB4DIVR); 8477839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 8487839a050SYann Gautier break; 8497839a050SYann Gautier case _PCLK5: 8500d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB5DIVR); 8517839a050SYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 8527839a050SYann Gautier break; 8537839a050SYann Gautier default: 8547839a050SYann Gautier break; 8557839a050SYann Gautier } 8567839a050SYann Gautier break; 857b053a22eSYann Gautier /* MCU sub system */ 858b053a22eSYann Gautier case _CK_MCU: 859b053a22eSYann Gautier case _PCLK1: 860b053a22eSYann Gautier case _PCLK2: 861b053a22eSYann Gautier case _PCLK3: 862b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); 863b053a22eSYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 864b053a22eSYann Gautier case RCC_MSSCKSELR_HSI: 865b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 866b053a22eSYann Gautier break; 867b053a22eSYann Gautier case RCC_MSSCKSELR_HSE: 868b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 869b053a22eSYann Gautier break; 870b053a22eSYann Gautier case RCC_MSSCKSELR_CSI: 871b053a22eSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 872b053a22eSYann Gautier break; 873b053a22eSYann Gautier case RCC_MSSCKSELR_PLL: 874b053a22eSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 875b053a22eSYann Gautier break; 876b053a22eSYann Gautier default: 877b053a22eSYann Gautier break; 878b053a22eSYann Gautier } 879b053a22eSYann Gautier 880b053a22eSYann Gautier /* MCU clock divider */ 881b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_MCUDIVR); 882b053a22eSYann Gautier clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; 883b053a22eSYann Gautier 884b053a22eSYann Gautier switch (p) { 885b053a22eSYann Gautier case _PCLK1: 886b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB1DIVR); 887b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 888b053a22eSYann Gautier break; 889b053a22eSYann Gautier case _PCLK2: 890b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB2DIVR); 891b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 892b053a22eSYann Gautier break; 893b053a22eSYann Gautier case _PCLK3: 894b053a22eSYann Gautier reg = mmio_read_32(rcc_base + RCC_APB3DIVR); 895b053a22eSYann Gautier clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; 896b053a22eSYann Gautier break; 897b053a22eSYann Gautier case _CK_MCU: 898b053a22eSYann Gautier default: 899b053a22eSYann Gautier break; 900b053a22eSYann Gautier } 901b053a22eSYann Gautier break; 9027839a050SYann Gautier case _CK_PER: 9030d21680cSYann Gautier reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); 9047839a050SYann Gautier switch (reg & RCC_SELR_SRC_MASK) { 9057839a050SYann Gautier case RCC_CPERCKSELR_HSI: 9060d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 9077839a050SYann Gautier break; 9087839a050SYann Gautier case RCC_CPERCKSELR_HSE: 9090d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 9107839a050SYann Gautier break; 9117839a050SYann Gautier case RCC_CPERCKSELR_CSI: 9120d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 9137839a050SYann Gautier break; 9147839a050SYann Gautier default: 9157839a050SYann Gautier break; 9167839a050SYann Gautier } 9177839a050SYann Gautier break; 9187839a050SYann Gautier case _HSI: 9197839a050SYann Gautier case _HSI_KER: 9200d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSI); 9217839a050SYann Gautier break; 9227839a050SYann Gautier case _CSI: 9237839a050SYann Gautier case _CSI_KER: 9240d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_CSI); 9257839a050SYann Gautier break; 9267839a050SYann Gautier case _HSE: 9277839a050SYann Gautier case _HSE_KER: 9280d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE); 9297839a050SYann Gautier break; 9307839a050SYann Gautier case _HSE_KER_DIV2: 9310d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_HSE) >> 1; 9327839a050SYann Gautier break; 9337839a050SYann Gautier case _LSI: 9340d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSI); 9357839a050SYann Gautier break; 9367839a050SYann Gautier case _LSE: 9370d21680cSYann Gautier clock = stm32mp1_clk_get_fixed(_LSE); 9387839a050SYann Gautier break; 9397839a050SYann Gautier /* PLL */ 9407839a050SYann Gautier case _PLL1_P: 9410d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); 9427839a050SYann Gautier break; 9437839a050SYann Gautier case _PLL1_Q: 9440d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); 9457839a050SYann Gautier break; 9467839a050SYann Gautier case _PLL1_R: 9470d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); 9487839a050SYann Gautier break; 9497839a050SYann Gautier case _PLL2_P: 9500d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); 9517839a050SYann Gautier break; 9527839a050SYann Gautier case _PLL2_Q: 9530d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); 9547839a050SYann Gautier break; 9557839a050SYann Gautier case _PLL2_R: 9560d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); 9577839a050SYann Gautier break; 9587839a050SYann Gautier case _PLL3_P: 9590d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); 9607839a050SYann Gautier break; 9617839a050SYann Gautier case _PLL3_Q: 9620d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); 9637839a050SYann Gautier break; 9647839a050SYann Gautier case _PLL3_R: 9650d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); 9667839a050SYann Gautier break; 9677839a050SYann Gautier case _PLL4_P: 9680d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); 9697839a050SYann Gautier break; 9707839a050SYann Gautier case _PLL4_Q: 9710d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); 9727839a050SYann Gautier break; 9737839a050SYann Gautier case _PLL4_R: 9740d21680cSYann Gautier clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); 9757839a050SYann Gautier break; 9767839a050SYann Gautier /* Other */ 9777839a050SYann Gautier case _USB_PHY_48: 9780d21680cSYann Gautier clock = USB_PHY_48_MHZ; 9797839a050SYann Gautier break; 9807839a050SYann Gautier default: 9817839a050SYann Gautier break; 9827839a050SYann Gautier } 9837839a050SYann Gautier 9847839a050SYann Gautier return clock; 9857839a050SYann Gautier } 9867839a050SYann Gautier 9870d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate) 9880d21680cSYann Gautier { 9890d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 9900d21680cSYann Gautier 991*25be845eSEtienne Carriere VERBOSE("Enable clock %u\n", gate->index); 992*25be845eSEtienne Carriere 9930d21680cSYann Gautier if (gate->set_clr != 0U) { 9940d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); 9950d21680cSYann Gautier } else { 9960d21680cSYann Gautier mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); 9970d21680cSYann Gautier } 9980d21680cSYann Gautier } 9990d21680cSYann Gautier 10000d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate) 10010d21680cSYann Gautier { 10020d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10030d21680cSYann Gautier 1004*25be845eSEtienne Carriere VERBOSE("Disable clock %u\n", gate->index); 1005*25be845eSEtienne Carriere 10060d21680cSYann Gautier if (gate->set_clr != 0U) { 10070d21680cSYann Gautier mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, 10080d21680cSYann Gautier BIT(gate->bit)); 10090d21680cSYann Gautier } else { 10100d21680cSYann Gautier mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); 10110d21680cSYann Gautier } 10120d21680cSYann Gautier } 10130d21680cSYann Gautier 10140d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) 10150d21680cSYann Gautier { 10160d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 10170d21680cSYann Gautier 10180d21680cSYann Gautier return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); 10190d21680cSYann Gautier } 10200d21680cSYann Gautier 10210d21680cSYann Gautier unsigned int stm32mp1_clk_get_refcount(unsigned long id) 10220d21680cSYann Gautier { 10230d21680cSYann Gautier int i = stm32mp1_clk_get_gated_id(id); 10240d21680cSYann Gautier 10250d21680cSYann Gautier if (i < 0) { 10260d21680cSYann Gautier panic(); 10270d21680cSYann Gautier } 10280d21680cSYann Gautier 10290d21680cSYann Gautier return gate_refcounts[i]; 10300d21680cSYann Gautier } 10310d21680cSYann Gautier 103235848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */ 103335848200SEtienne Carriere static bool clock_is_always_on(unsigned long id) 103435848200SEtienne Carriere { 103535848200SEtienne Carriere switch (id) { 103635848200SEtienne Carriere case CK_HSE: 103735848200SEtienne Carriere case CK_CSI: 103835848200SEtienne Carriere case CK_LSI: 103935848200SEtienne Carriere case CK_LSE: 104035848200SEtienne Carriere case CK_HSI: 104135848200SEtienne Carriere case CK_HSE_DIV2: 104235848200SEtienne Carriere case PLL1_Q: 104335848200SEtienne Carriere case PLL1_R: 104435848200SEtienne Carriere case PLL2_P: 104535848200SEtienne Carriere case PLL2_Q: 104635848200SEtienne Carriere case PLL2_R: 104735848200SEtienne Carriere case PLL3_P: 104835848200SEtienne Carriere case PLL3_Q: 104935848200SEtienne Carriere case PLL3_R: 105035848200SEtienne Carriere return true; 105135848200SEtienne Carriere default: 105235848200SEtienne Carriere return false; 105335848200SEtienne Carriere } 105435848200SEtienne Carriere } 105535848200SEtienne Carriere 10560d21680cSYann Gautier void __stm32mp1_clk_enable(unsigned long id, bool secure) 10570d21680cSYann Gautier { 10580d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 105935848200SEtienne Carriere int i; 10600d21680cSYann Gautier unsigned int *refcnt; 10610d21680cSYann Gautier 106235848200SEtienne Carriere if (clock_is_always_on(id)) { 106335848200SEtienne Carriere return; 106435848200SEtienne Carriere } 106535848200SEtienne Carriere 106635848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 10670d21680cSYann Gautier if (i < 0) { 10680d21680cSYann Gautier ERROR("Clock %d can't be enabled\n", (uint32_t)id); 10690d21680cSYann Gautier panic(); 10700d21680cSYann Gautier } 10710d21680cSYann Gautier 10720d21680cSYann Gautier gate = gate_ref(i); 10730d21680cSYann Gautier refcnt = &gate_refcounts[i]; 10740d21680cSYann Gautier 10750d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 10760d21680cSYann Gautier 10770d21680cSYann Gautier if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { 10780d21680cSYann Gautier __clk_enable(gate); 10790d21680cSYann Gautier } 10800d21680cSYann Gautier 10810d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 10820d21680cSYann Gautier } 10830d21680cSYann Gautier 10840d21680cSYann Gautier void __stm32mp1_clk_disable(unsigned long id, bool secure) 10850d21680cSYann Gautier { 10860d21680cSYann Gautier const struct stm32mp1_clk_gate *gate; 108735848200SEtienne Carriere int i; 10880d21680cSYann Gautier unsigned int *refcnt; 10890d21680cSYann Gautier 109035848200SEtienne Carriere if (clock_is_always_on(id)) { 109135848200SEtienne Carriere return; 109235848200SEtienne Carriere } 109335848200SEtienne Carriere 109435848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 10950d21680cSYann Gautier if (i < 0) { 10960d21680cSYann Gautier ERROR("Clock %d can't be disabled\n", (uint32_t)id); 10970d21680cSYann Gautier panic(); 10980d21680cSYann Gautier } 10990d21680cSYann Gautier 11000d21680cSYann Gautier gate = gate_ref(i); 11010d21680cSYann Gautier refcnt = &gate_refcounts[i]; 11020d21680cSYann Gautier 11030d21680cSYann Gautier stm32mp1_clk_lock(&refcount_lock); 11040d21680cSYann Gautier 11050d21680cSYann Gautier if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { 11060d21680cSYann Gautier __clk_disable(gate); 11070d21680cSYann Gautier } 11080d21680cSYann Gautier 11090d21680cSYann Gautier stm32mp1_clk_unlock(&refcount_lock); 11100d21680cSYann Gautier } 11110d21680cSYann Gautier 11120d21680cSYann Gautier void stm32mp_clk_enable(unsigned long id) 11130d21680cSYann Gautier { 11140d21680cSYann Gautier __stm32mp1_clk_enable(id, true); 11150d21680cSYann Gautier } 11160d21680cSYann Gautier 11170d21680cSYann Gautier void stm32mp_clk_disable(unsigned long id) 11180d21680cSYann Gautier { 11190d21680cSYann Gautier __stm32mp1_clk_disable(id, true); 11200d21680cSYann Gautier } 11210d21680cSYann Gautier 11223f9c9784SYann Gautier bool stm32mp_clk_is_enabled(unsigned long id) 11237839a050SYann Gautier { 112435848200SEtienne Carriere int i; 11257839a050SYann Gautier 112635848200SEtienne Carriere if (clock_is_always_on(id)) { 112735848200SEtienne Carriere return true; 112835848200SEtienne Carriere } 112935848200SEtienne Carriere 113035848200SEtienne Carriere i = stm32mp1_clk_get_gated_id(id); 11317839a050SYann Gautier if (i < 0) { 11320d21680cSYann Gautier panic(); 11337839a050SYann Gautier } 11347839a050SYann Gautier 11350d21680cSYann Gautier return __clk_is_enabled(gate_ref(i)); 11367839a050SYann Gautier } 11377839a050SYann Gautier 11383f9c9784SYann Gautier unsigned long stm32mp_clk_get_rate(unsigned long id) 11397839a050SYann Gautier { 11400d21680cSYann Gautier int p = stm32mp1_clk_get_parent(id); 11417839a050SYann Gautier 11427839a050SYann Gautier if (p < 0) { 11437839a050SYann Gautier return 0; 11447839a050SYann Gautier } 11457839a050SYann Gautier 11460d21680cSYann Gautier return get_clock_rate(p); 11477839a050SYann Gautier } 11487839a050SYann Gautier 11490d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) 11507839a050SYann Gautier { 11510d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 11527839a050SYann Gautier 11530d21680cSYann Gautier if (enable) { 11547839a050SYann Gautier mmio_setbits_32(address, mask_on); 11557839a050SYann Gautier } else { 11567839a050SYann Gautier mmio_clrbits_32(address, mask_on); 11577839a050SYann Gautier } 11587839a050SYann Gautier } 11597839a050SYann Gautier 11600d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) 11617839a050SYann Gautier { 11620d21680cSYann Gautier uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; 11630d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 11640d21680cSYann Gautier 11650d21680cSYann Gautier mmio_write_32(address, mask_on); 11667839a050SYann Gautier } 11677839a050SYann Gautier 11680d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) 11697839a050SYann Gautier { 1170dfdb057aSYann Gautier uint64_t timeout; 11717839a050SYann Gautier uint32_t mask_test; 11720d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + offset; 11737839a050SYann Gautier 11740d21680cSYann Gautier if (enable) { 11757839a050SYann Gautier mask_test = mask_rdy; 11767839a050SYann Gautier } else { 11777839a050SYann Gautier mask_test = 0; 11787839a050SYann Gautier } 11797839a050SYann Gautier 1180dfdb057aSYann Gautier timeout = timeout_init_us(OSCRDY_TIMEOUT); 11817839a050SYann Gautier while ((mmio_read_32(address) & mask_rdy) != mask_test) { 1182dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 11830d21680cSYann Gautier ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", 11847839a050SYann Gautier mask_rdy, address, enable, mmio_read_32(address)); 11857839a050SYann Gautier return -ETIMEDOUT; 11867839a050SYann Gautier } 11877839a050SYann Gautier } 11887839a050SYann Gautier 11897839a050SYann Gautier return 0; 11907839a050SYann Gautier } 11917839a050SYann Gautier 11920d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) 11937839a050SYann Gautier { 11947839a050SYann Gautier uint32_t value; 11950d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 11967839a050SYann Gautier 11970d21680cSYann Gautier if (digbyp) { 11980d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); 11990d21680cSYann Gautier } 12000d21680cSYann Gautier 12010d21680cSYann Gautier if (bypass || digbyp) { 12020d21680cSYann Gautier mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); 12037839a050SYann Gautier } 12047839a050SYann Gautier 12057839a050SYann Gautier /* 12067839a050SYann Gautier * Warning: not recommended to switch directly from "high drive" 12077839a050SYann Gautier * to "medium low drive", and vice-versa. 12087839a050SYann Gautier */ 12090d21680cSYann Gautier value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> 12107839a050SYann Gautier RCC_BDCR_LSEDRV_SHIFT; 12117839a050SYann Gautier 12127839a050SYann Gautier while (value != lsedrv) { 12137839a050SYann Gautier if (value > lsedrv) { 12147839a050SYann Gautier value--; 12157839a050SYann Gautier } else { 12167839a050SYann Gautier value++; 12177839a050SYann Gautier } 12187839a050SYann Gautier 12190d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_BDCR, 12207839a050SYann Gautier RCC_BDCR_LSEDRV_MASK, 12217839a050SYann Gautier value << RCC_BDCR_LSEDRV_SHIFT); 12227839a050SYann Gautier } 12237839a050SYann Gautier 12240d21680cSYann Gautier stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); 12257839a050SYann Gautier } 12267839a050SYann Gautier 12270d21680cSYann Gautier static void stm32mp1_lse_wait(void) 12287839a050SYann Gautier { 12290d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { 12307839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12317839a050SYann Gautier } 12327839a050SYann Gautier } 12337839a050SYann Gautier 12340d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable) 12357839a050SYann Gautier { 12360d21680cSYann Gautier stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); 12370d21680cSYann Gautier 12380d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { 12397839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12407839a050SYann Gautier } 12417839a050SYann Gautier } 12427839a050SYann Gautier 12430d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) 12447839a050SYann Gautier { 12450d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 12460d21680cSYann Gautier 12470d21680cSYann Gautier if (digbyp) { 12480d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); 12497839a050SYann Gautier } 12507839a050SYann Gautier 12510d21680cSYann Gautier if (bypass || digbyp) { 12520d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); 12530d21680cSYann Gautier } 12540d21680cSYann Gautier 12550d21680cSYann Gautier stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); 12560d21680cSYann Gautier if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { 12577839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12587839a050SYann Gautier } 12597839a050SYann Gautier 12607839a050SYann Gautier if (css) { 12610d21680cSYann Gautier mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); 12627839a050SYann Gautier } 12637839a050SYann Gautier } 12647839a050SYann Gautier 12650d21680cSYann Gautier static void stm32mp1_csi_set(bool enable) 12667839a050SYann Gautier { 12670d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); 12680d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { 12697839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12707839a050SYann Gautier } 12717839a050SYann Gautier } 12727839a050SYann Gautier 12730d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable) 12747839a050SYann Gautier { 12750d21680cSYann Gautier stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); 12760d21680cSYann Gautier if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { 12777839a050SYann Gautier VERBOSE("%s: failed\n", __func__); 12787839a050SYann Gautier } 12797839a050SYann Gautier } 12807839a050SYann Gautier 12810d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv) 12827839a050SYann Gautier { 1283dfdb057aSYann Gautier uint64_t timeout; 12840d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 12850d21680cSYann Gautier uintptr_t address = rcc_base + RCC_OCRDYR; 12867839a050SYann Gautier 12870d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, 12887839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK, 12897839a050SYann Gautier RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); 12907839a050SYann Gautier 1291dfdb057aSYann Gautier timeout = timeout_init_us(HSIDIV_TIMEOUT); 12927839a050SYann Gautier while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { 1293dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 12940d21680cSYann Gautier ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", 12957839a050SYann Gautier address, mmio_read_32(address)); 12967839a050SYann Gautier return -ETIMEDOUT; 12977839a050SYann Gautier } 12987839a050SYann Gautier } 12997839a050SYann Gautier 13007839a050SYann Gautier return 0; 13017839a050SYann Gautier } 13027839a050SYann Gautier 13030d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq) 13047839a050SYann Gautier { 13057839a050SYann Gautier uint8_t hsidiv; 13067839a050SYann Gautier uint32_t hsidivfreq = MAX_HSI_HZ; 13077839a050SYann Gautier 13087839a050SYann Gautier for (hsidiv = 0; hsidiv < 4U; hsidiv++) { 13097839a050SYann Gautier if (hsidivfreq == hsifreq) { 13107839a050SYann Gautier break; 13117839a050SYann Gautier } 13127839a050SYann Gautier 13137839a050SYann Gautier hsidivfreq /= 2U; 13147839a050SYann Gautier } 13157839a050SYann Gautier 13167839a050SYann Gautier if (hsidiv == 4U) { 13177839a050SYann Gautier ERROR("Invalid clk-hsi frequency\n"); 13187839a050SYann Gautier return -1; 13197839a050SYann Gautier } 13207839a050SYann Gautier 13217839a050SYann Gautier if (hsidiv != 0U) { 13220d21680cSYann Gautier return stm32mp1_set_hsidiv(hsidiv); 13237839a050SYann Gautier } 13247839a050SYann Gautier 13257839a050SYann Gautier return 0; 13267839a050SYann Gautier } 13277839a050SYann Gautier 13280d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, 13290d21680cSYann Gautier unsigned int clksrc, 13300d21680cSYann Gautier uint32_t *pllcfg, int plloff) 13317839a050SYann Gautier { 13320d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 13330d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 13340d21680cSYann Gautier uintptr_t pllxcr = rcc_base + pll->pllxcr; 13350d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 13360d21680cSYann Gautier uintptr_t clksrc_address = rcc_base + (clksrc >> 4); 13370d21680cSYann Gautier unsigned long refclk; 13380d21680cSYann Gautier uint32_t ifrge = 0U; 1339be858cffSAndre Przywara uint32_t src, value, fracv = 0; 1340be858cffSAndre Przywara void *fdt; 13417839a050SYann Gautier 13420d21680cSYann Gautier /* Check PLL output */ 13430d21680cSYann Gautier if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { 13440d21680cSYann Gautier return false; 13457839a050SYann Gautier } 13467839a050SYann Gautier 13470d21680cSYann Gautier /* Check current clksrc */ 13480d21680cSYann Gautier src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; 13490d21680cSYann Gautier if (src != (clksrc & RCC_SELR_SRC_MASK)) { 13500d21680cSYann Gautier return false; 13510d21680cSYann Gautier } 13520d21680cSYann Gautier 13530d21680cSYann Gautier /* Check Div */ 13540d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; 13550d21680cSYann Gautier 13560d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 13570d21680cSYann Gautier (pllcfg[PLLCFG_M] + 1U); 13580d21680cSYann Gautier 13590d21680cSYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 13600d21680cSYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 13610d21680cSYann Gautier return false; 13620d21680cSYann Gautier } 13630d21680cSYann Gautier 13640d21680cSYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 13650d21680cSYann Gautier ifrge = 1U; 13660d21680cSYann Gautier } 13670d21680cSYann Gautier 13680d21680cSYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 13690d21680cSYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 13700d21680cSYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 13710d21680cSYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 13720d21680cSYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 13730d21680cSYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 13740d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { 13750d21680cSYann Gautier return false; 13760d21680cSYann Gautier } 13770d21680cSYann Gautier 13780d21680cSYann Gautier /* Fractional configuration */ 1379be858cffSAndre Przywara if (fdt_get_address(&fdt) == 1) { 1380be858cffSAndre Przywara fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); 1381be858cffSAndre Przywara } 13820d21680cSYann Gautier 13830d21680cSYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 13840d21680cSYann Gautier value |= RCC_PLLNFRACR_FRACLE; 13850d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { 13860d21680cSYann Gautier return false; 13870d21680cSYann Gautier } 13880d21680cSYann Gautier 13890d21680cSYann Gautier /* Output config */ 13900d21680cSYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 13910d21680cSYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 13920d21680cSYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 13930d21680cSYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 13940d21680cSYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 13950d21680cSYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 13960d21680cSYann Gautier if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { 13970d21680cSYann Gautier return false; 13980d21680cSYann Gautier } 13990d21680cSYann Gautier 14000d21680cSYann Gautier return true; 14010d21680cSYann Gautier } 14020d21680cSYann Gautier 14030d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) 14047839a050SYann Gautier { 14050d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14060d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 14070d21680cSYann Gautier 1408dd98aec8SYann Gautier /* Preserve RCC_PLLNCR_SSCG_CTRL value */ 1409dd98aec8SYann Gautier mmio_clrsetbits_32(pllxcr, 1410dd98aec8SYann Gautier RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 1411dd98aec8SYann Gautier RCC_PLLNCR_DIVREN, 1412dd98aec8SYann Gautier RCC_PLLNCR_PLLON); 14130d21680cSYann Gautier } 14140d21680cSYann Gautier 14150d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) 14160d21680cSYann Gautier { 14170d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14180d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1419dfdb057aSYann Gautier uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); 14207839a050SYann Gautier 14217839a050SYann Gautier /* Wait PLL lock */ 14227839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { 1423dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 14240d21680cSYann Gautier ERROR("PLL%d start failed @ 0x%lx: 0x%x\n", 14257839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 14267839a050SYann Gautier return -ETIMEDOUT; 14277839a050SYann Gautier } 14287839a050SYann Gautier } 14297839a050SYann Gautier 14307839a050SYann Gautier /* Start the requested output */ 14317839a050SYann Gautier mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); 14327839a050SYann Gautier 14337839a050SYann Gautier return 0; 14347839a050SYann Gautier } 14357839a050SYann Gautier 14360d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) 14377839a050SYann Gautier { 14380d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14390d21680cSYann Gautier uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; 1440dfdb057aSYann Gautier uint64_t timeout; 14417839a050SYann Gautier 14427839a050SYann Gautier /* Stop all output */ 14437839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | 14447839a050SYann Gautier RCC_PLLNCR_DIVREN); 14457839a050SYann Gautier 14467839a050SYann Gautier /* Stop PLL */ 14477839a050SYann Gautier mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); 14487839a050SYann Gautier 1449dfdb057aSYann Gautier timeout = timeout_init_us(PLLRDY_TIMEOUT); 14507839a050SYann Gautier /* Wait PLL stopped */ 14517839a050SYann Gautier while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { 1452dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 14530d21680cSYann Gautier ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n", 14547839a050SYann Gautier pll_id, pllxcr, mmio_read_32(pllxcr)); 14557839a050SYann Gautier return -ETIMEDOUT; 14567839a050SYann Gautier } 14577839a050SYann Gautier } 14587839a050SYann Gautier 14597839a050SYann Gautier return 0; 14607839a050SYann Gautier } 14617839a050SYann Gautier 14620d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, 14637839a050SYann Gautier uint32_t *pllcfg) 14647839a050SYann Gautier { 14650d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14660d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 14677839a050SYann Gautier uint32_t value; 14687839a050SYann Gautier 14697839a050SYann Gautier value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & 14707839a050SYann Gautier RCC_PLLNCFGR2_DIVP_MASK; 14717839a050SYann Gautier value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & 14727839a050SYann Gautier RCC_PLLNCFGR2_DIVQ_MASK; 14737839a050SYann Gautier value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & 14747839a050SYann Gautier RCC_PLLNCFGR2_DIVR_MASK; 14750d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr2, value); 14767839a050SYann Gautier } 14777839a050SYann Gautier 14780d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, 14797839a050SYann Gautier uint32_t *pllcfg, uint32_t fracv) 14807839a050SYann Gautier { 14810d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 14820d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 14830d21680cSYann Gautier enum stm32mp1_plltype type = pll->plltype; 14847839a050SYann Gautier unsigned long refclk; 14857839a050SYann Gautier uint32_t ifrge = 0; 14867839a050SYann Gautier uint32_t src, value; 14877839a050SYann Gautier 14880d21680cSYann Gautier src = mmio_read_32(rcc_base + pll->rckxselr) & 14897839a050SYann Gautier RCC_SELR_REFCLK_SRC_MASK; 14907839a050SYann Gautier 14910d21680cSYann Gautier refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / 14927839a050SYann Gautier (pllcfg[PLLCFG_M] + 1U); 14937839a050SYann Gautier 14947839a050SYann Gautier if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || 14957839a050SYann Gautier (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { 14967839a050SYann Gautier return -EINVAL; 14977839a050SYann Gautier } 14987839a050SYann Gautier 14997839a050SYann Gautier if ((type == PLL_800) && (refclk >= 8000000U)) { 15007839a050SYann Gautier ifrge = 1U; 15017839a050SYann Gautier } 15027839a050SYann Gautier 15037839a050SYann Gautier value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & 15047839a050SYann Gautier RCC_PLLNCFGR1_DIVN_MASK; 15057839a050SYann Gautier value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & 15067839a050SYann Gautier RCC_PLLNCFGR1_DIVM_MASK; 15077839a050SYann Gautier value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & 15087839a050SYann Gautier RCC_PLLNCFGR1_IFRGE_MASK; 15090d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxcfgr1, value); 15107839a050SYann Gautier 15117839a050SYann Gautier /* Fractional configuration */ 15127839a050SYann Gautier value = 0; 15130d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 15147839a050SYann Gautier 15157839a050SYann Gautier value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; 15160d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 15177839a050SYann Gautier 15187839a050SYann Gautier value |= RCC_PLLNFRACR_FRACLE; 15190d21680cSYann Gautier mmio_write_32(rcc_base + pll->pllxfracr, value); 15207839a050SYann Gautier 15210d21680cSYann Gautier stm32mp1_pll_config_output(pll_id, pllcfg); 15227839a050SYann Gautier 15237839a050SYann Gautier return 0; 15247839a050SYann Gautier } 15257839a050SYann Gautier 15260d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) 15277839a050SYann Gautier { 15280d21680cSYann Gautier const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); 15297839a050SYann Gautier uint32_t pllxcsg = 0; 15307839a050SYann Gautier 15317839a050SYann Gautier pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & 15327839a050SYann Gautier RCC_PLLNCSGR_MOD_PER_MASK; 15337839a050SYann Gautier 15347839a050SYann Gautier pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & 15357839a050SYann Gautier RCC_PLLNCSGR_INC_STEP_MASK; 15367839a050SYann Gautier 15377839a050SYann Gautier pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & 15387839a050SYann Gautier RCC_PLLNCSGR_SSCG_MODE_MASK; 15397839a050SYann Gautier 15400d21680cSYann Gautier mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); 1541dd98aec8SYann Gautier 1542dd98aec8SYann Gautier mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, 1543dd98aec8SYann Gautier RCC_PLLNCR_SSCG_CTRL); 15447839a050SYann Gautier } 15457839a050SYann Gautier 15460d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc) 15477839a050SYann Gautier { 15480d21680cSYann Gautier uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 1549dfdb057aSYann Gautier uint64_t timeout; 15507839a050SYann Gautier 15510d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, 15527839a050SYann Gautier clksrc & RCC_SELR_SRC_MASK); 15537839a050SYann Gautier 1554dfdb057aSYann Gautier timeout = timeout_init_us(CLKSRC_TIMEOUT); 15550d21680cSYann Gautier while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { 1556dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 15570d21680cSYann Gautier ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, 15580d21680cSYann Gautier clksrc_address, mmio_read_32(clksrc_address)); 15597839a050SYann Gautier return -ETIMEDOUT; 15607839a050SYann Gautier } 15617839a050SYann Gautier } 15627839a050SYann Gautier 15637839a050SYann Gautier return 0; 15647839a050SYann Gautier } 15657839a050SYann Gautier 15660d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) 15677839a050SYann Gautier { 1568dfdb057aSYann Gautier uint64_t timeout; 15697839a050SYann Gautier 15707839a050SYann Gautier mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, 15717839a050SYann Gautier clkdiv & RCC_DIVR_DIV_MASK); 15727839a050SYann Gautier 1573dfdb057aSYann Gautier timeout = timeout_init_us(CLKDIV_TIMEOUT); 15747839a050SYann Gautier while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { 1575dfdb057aSYann Gautier if (timeout_elapsed(timeout)) { 15760d21680cSYann Gautier ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", 15777839a050SYann Gautier clkdiv, address, mmio_read_32(address)); 15787839a050SYann Gautier return -ETIMEDOUT; 15797839a050SYann Gautier } 15807839a050SYann Gautier } 15817839a050SYann Gautier 15827839a050SYann Gautier return 0; 15837839a050SYann Gautier } 15847839a050SYann Gautier 15850d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) 15867839a050SYann Gautier { 15870d21680cSYann Gautier uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); 15887839a050SYann Gautier 15897839a050SYann Gautier /* 15907839a050SYann Gautier * Binding clksrc : 15917839a050SYann Gautier * bit15-4 offset 15927839a050SYann Gautier * bit3: disable 15937839a050SYann Gautier * bit2-0: MCOSEL[2:0] 15947839a050SYann Gautier */ 15957839a050SYann Gautier if ((clksrc & 0x8U) != 0U) { 15960d21680cSYann Gautier mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); 15977839a050SYann Gautier } else { 15980d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, 15997839a050SYann Gautier RCC_MCOCFG_MCOSRC_MASK, 16007839a050SYann Gautier clksrc & RCC_MCOCFG_MCOSRC_MASK); 16010d21680cSYann Gautier mmio_clrsetbits_32(clksrc_address, 16027839a050SYann Gautier RCC_MCOCFG_MCODIV_MASK, 16037839a050SYann Gautier clkdiv << RCC_MCOCFG_MCODIV_SHIFT); 16040d21680cSYann Gautier mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); 16057839a050SYann Gautier } 16067839a050SYann Gautier } 16077839a050SYann Gautier 16080d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) 16097839a050SYann Gautier { 16100d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; 16117839a050SYann Gautier 16127839a050SYann Gautier if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || 16137839a050SYann Gautier (clksrc != (uint32_t)CLK_RTC_DISABLED)) { 16147839a050SYann Gautier mmio_clrsetbits_32(address, 16157839a050SYann Gautier RCC_BDCR_RTCSRC_MASK, 16167839a050SYann Gautier clksrc << RCC_BDCR_RTCSRC_SHIFT); 16177839a050SYann Gautier 16187839a050SYann Gautier mmio_setbits_32(address, RCC_BDCR_RTCCKEN); 16197839a050SYann Gautier } 16207839a050SYann Gautier 16217839a050SYann Gautier if (lse_css) { 16227839a050SYann Gautier mmio_setbits_32(address, RCC_BDCR_LSECSSON); 16237839a050SYann Gautier } 16247839a050SYann Gautier } 16257839a050SYann Gautier 16260d21680cSYann Gautier static void stm32mp1_stgen_config(void) 16277839a050SYann Gautier { 16287839a050SYann Gautier uintptr_t stgen; 16297839a050SYann Gautier uint32_t cntfid0; 16307839a050SYann Gautier unsigned long rate; 16317839a050SYann Gautier unsigned long long counter; 16327839a050SYann Gautier 16330d21680cSYann Gautier stgen = fdt_get_stgen_base(); 16340d21680cSYann Gautier cntfid0 = mmio_read_32(stgen + CNTFID_OFF); 16350d21680cSYann Gautier rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); 16360d21680cSYann Gautier 16370d21680cSYann Gautier if (cntfid0 == rate) { 16380d21680cSYann Gautier return; 16390d21680cSYann Gautier } 16400d21680cSYann Gautier 16417839a050SYann Gautier mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); 16420d21680cSYann Gautier counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF); 16430d21680cSYann Gautier counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32; 16447839a050SYann Gautier counter = (counter * rate / cntfid0); 16450d21680cSYann Gautier 16467839a050SYann Gautier mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter); 16477839a050SYann Gautier mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32)); 16487839a050SYann Gautier mmio_write_32(stgen + CNTFID_OFF, rate); 16497839a050SYann Gautier mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); 16507839a050SYann Gautier 16517839a050SYann Gautier write_cntfrq((u_register_t)rate); 16527839a050SYann Gautier 16537839a050SYann Gautier /* Need to update timer with new frequency */ 16547839a050SYann Gautier generic_delay_timer_init(); 16557839a050SYann Gautier } 16567839a050SYann Gautier 16577839a050SYann Gautier void stm32mp1_stgen_increment(unsigned long long offset_in_ms) 16587839a050SYann Gautier { 16597839a050SYann Gautier uintptr_t stgen; 16607839a050SYann Gautier unsigned long long cnt; 16617839a050SYann Gautier 16627839a050SYann Gautier stgen = fdt_get_stgen_base(); 16637839a050SYann Gautier 16647839a050SYann Gautier cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) | 16657839a050SYann Gautier mmio_read_32(stgen + CNTCVL_OFF); 16667839a050SYann Gautier 16677839a050SYann Gautier cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U; 16687839a050SYann Gautier 16697839a050SYann Gautier mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN); 16707839a050SYann Gautier mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt); 16717839a050SYann Gautier mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(cnt >> 32)); 16727839a050SYann Gautier mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN); 16737839a050SYann Gautier } 16747839a050SYann Gautier 16750d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs) 16767839a050SYann Gautier { 16770d21680cSYann Gautier uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); 16787839a050SYann Gautier uint32_t value = pkcs & 0xFU; 16797839a050SYann Gautier uint32_t mask = 0xFU; 16807839a050SYann Gautier 16817839a050SYann Gautier if ((pkcs & BIT(31)) != 0U) { 16827839a050SYann Gautier mask <<= 4; 16837839a050SYann Gautier value <<= 4; 16847839a050SYann Gautier } 16857839a050SYann Gautier 16867839a050SYann Gautier mmio_clrsetbits_32(address, mask, value); 16877839a050SYann Gautier } 16887839a050SYann Gautier 16897839a050SYann Gautier int stm32mp1_clk_init(void) 16907839a050SYann Gautier { 16910d21680cSYann Gautier uintptr_t rcc_base = stm32mp_rcc_base(); 16927839a050SYann Gautier unsigned int clksrc[CLKSRC_NB]; 16937839a050SYann Gautier unsigned int clkdiv[CLKDIV_NB]; 16947839a050SYann Gautier unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; 16957839a050SYann Gautier int plloff[_PLL_NB]; 16967839a050SYann Gautier int ret, len; 16977839a050SYann Gautier enum stm32mp1_pll_id i; 16987839a050SYann Gautier bool lse_css = false; 16990d21680cSYann Gautier bool pll3_preserve = false; 17000d21680cSYann Gautier bool pll4_preserve = false; 17010d21680cSYann Gautier bool pll4_bootrom = false; 17023e6fab43SYann Gautier const fdt32_t *pkcs_cell; 170352a616b4SAndre Przywara void *fdt; 170452a616b4SAndre Przywara 170552a616b4SAndre Przywara if (fdt_get_address(&fdt) == 0) { 170652a616b4SAndre Przywara return false; 170752a616b4SAndre Przywara } 17087839a050SYann Gautier 17097839a050SYann Gautier /* Check status field to disable security */ 17107839a050SYann Gautier if (!fdt_get_rcc_secure_status()) { 17110d21680cSYann Gautier mmio_write_32(rcc_base + RCC_TZCR, 0); 17127839a050SYann Gautier } 17137839a050SYann Gautier 171452a616b4SAndre Przywara ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, 171552a616b4SAndre Przywara clksrc); 17167839a050SYann Gautier if (ret < 0) { 17177839a050SYann Gautier return -FDT_ERR_NOTFOUND; 17187839a050SYann Gautier } 17197839a050SYann Gautier 172052a616b4SAndre Przywara ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, 172152a616b4SAndre Przywara clkdiv); 17227839a050SYann Gautier if (ret < 0) { 17237839a050SYann Gautier return -FDT_ERR_NOTFOUND; 17247839a050SYann Gautier } 17257839a050SYann Gautier 17267839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 17277839a050SYann Gautier char name[12]; 17287839a050SYann Gautier 172939b6cc66SAntonio Nino Diaz snprintf(name, sizeof(name), "st,pll@%d", i); 17307839a050SYann Gautier plloff[i] = fdt_rcc_subnode_offset(name); 17317839a050SYann Gautier 17327839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 17337839a050SYann Gautier continue; 17347839a050SYann Gautier } 17357839a050SYann Gautier 173652a616b4SAndre Przywara ret = fdt_read_uint32_array(fdt, plloff[i], "cfg", 173752a616b4SAndre Przywara (int)PLLCFG_NB, pllcfg[i]); 17387839a050SYann Gautier if (ret < 0) { 17397839a050SYann Gautier return -FDT_ERR_NOTFOUND; 17407839a050SYann Gautier } 17417839a050SYann Gautier } 17427839a050SYann Gautier 17430d21680cSYann Gautier stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); 17440d21680cSYann Gautier stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); 17457839a050SYann Gautier 17467839a050SYann Gautier /* 17477839a050SYann Gautier * Switch ON oscillator found in device-tree. 17487839a050SYann Gautier * Note: HSI already ON after BootROM stage. 17497839a050SYann Gautier */ 17500d21680cSYann Gautier if (stm32mp1_osc[_LSI] != 0U) { 17510d21680cSYann Gautier stm32mp1_lsi_set(true); 17527839a050SYann Gautier } 17530d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 17540d21680cSYann Gautier bool bypass, digbyp; 17557839a050SYann Gautier uint32_t lsedrv; 17567839a050SYann Gautier 17577839a050SYann Gautier bypass = fdt_osc_read_bool(_LSE, "st,bypass"); 17580d21680cSYann Gautier digbyp = fdt_osc_read_bool(_LSE, "st,digbypass"); 17597839a050SYann Gautier lse_css = fdt_osc_read_bool(_LSE, "st,css"); 17607839a050SYann Gautier lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive", 17617839a050SYann Gautier LSEDRV_MEDIUM_HIGH); 17620d21680cSYann Gautier stm32mp1_lse_enable(bypass, digbyp, lsedrv); 17637839a050SYann Gautier } 17640d21680cSYann Gautier if (stm32mp1_osc[_HSE] != 0U) { 17650d21680cSYann Gautier bool bypass, digbyp, css; 17667839a050SYann Gautier 17670d21680cSYann Gautier bypass = fdt_osc_read_bool(_HSE, "st,bypass"); 17680d21680cSYann Gautier digbyp = fdt_osc_read_bool(_HSE, "st,digbypass"); 17690d21680cSYann Gautier css = fdt_osc_read_bool(_HSE, "st,css"); 17700d21680cSYann Gautier stm32mp1_hse_enable(bypass, digbyp, css); 17717839a050SYann Gautier } 17727839a050SYann Gautier /* 17737839a050SYann Gautier * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) 17747839a050SYann Gautier * => switch on CSI even if node is not present in device tree 17757839a050SYann Gautier */ 17760d21680cSYann Gautier stm32mp1_csi_set(true); 17777839a050SYann Gautier 17787839a050SYann Gautier /* Come back to HSI */ 17790d21680cSYann Gautier ret = stm32mp1_set_clksrc(CLK_MPU_HSI); 17807839a050SYann Gautier if (ret != 0) { 17817839a050SYann Gautier return ret; 17827839a050SYann Gautier } 17830d21680cSYann Gautier ret = stm32mp1_set_clksrc(CLK_AXI_HSI); 17847839a050SYann Gautier if (ret != 0) { 17857839a050SYann Gautier return ret; 17867839a050SYann Gautier } 1787b053a22eSYann Gautier ret = stm32mp1_set_clksrc(CLK_MCU_HSI); 1788b053a22eSYann Gautier if (ret != 0) { 1789b053a22eSYann Gautier return ret; 1790b053a22eSYann Gautier } 17917839a050SYann Gautier 17920d21680cSYann Gautier if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & 17930d21680cSYann Gautier RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { 17940d21680cSYann Gautier pll3_preserve = stm32mp1_check_pll_conf(_PLL3, 17950d21680cSYann Gautier clksrc[CLKSRC_PLL3], 17960d21680cSYann Gautier pllcfg[_PLL3], 17970d21680cSYann Gautier plloff[_PLL3]); 17980d21680cSYann Gautier pll4_preserve = stm32mp1_check_pll_conf(_PLL4, 17990d21680cSYann Gautier clksrc[CLKSRC_PLL4], 18000d21680cSYann Gautier pllcfg[_PLL4], 18010d21680cSYann Gautier plloff[_PLL4]); 18020d21680cSYann Gautier } 18030d21680cSYann Gautier 18047839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 18050d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 18060d21680cSYann Gautier ((i == _PLL4) && pll4_preserve)) { 18077839a050SYann Gautier continue; 18080d21680cSYann Gautier } 18090d21680cSYann Gautier 18100d21680cSYann Gautier ret = stm32mp1_pll_stop(i); 18117839a050SYann Gautier if (ret != 0) { 18127839a050SYann Gautier return ret; 18137839a050SYann Gautier } 18147839a050SYann Gautier } 18157839a050SYann Gautier 18167839a050SYann Gautier /* Configure HSIDIV */ 18170d21680cSYann Gautier if (stm32mp1_osc[_HSI] != 0U) { 18180d21680cSYann Gautier ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); 18197839a050SYann Gautier if (ret != 0) { 18207839a050SYann Gautier return ret; 18217839a050SYann Gautier } 18220d21680cSYann Gautier stm32mp1_stgen_config(); 18237839a050SYann Gautier } 18247839a050SYann Gautier 18257839a050SYann Gautier /* Select DIV */ 18267839a050SYann Gautier /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ 18270d21680cSYann Gautier mmio_write_32(rcc_base + RCC_MPCKDIVR, 18287839a050SYann Gautier clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); 18290d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); 18307839a050SYann Gautier if (ret != 0) { 18317839a050SYann Gautier return ret; 18327839a050SYann Gautier } 18330d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); 18347839a050SYann Gautier if (ret != 0) { 18357839a050SYann Gautier return ret; 18367839a050SYann Gautier } 18370d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); 18387839a050SYann Gautier if (ret != 0) { 18397839a050SYann Gautier return ret; 18407839a050SYann Gautier } 1841b053a22eSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); 1842b053a22eSYann Gautier if (ret != 0) { 1843b053a22eSYann Gautier return ret; 1844b053a22eSYann Gautier } 18450d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); 18467839a050SYann Gautier if (ret != 0) { 18477839a050SYann Gautier return ret; 18487839a050SYann Gautier } 18490d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); 18507839a050SYann Gautier if (ret != 0) { 18517839a050SYann Gautier return ret; 18527839a050SYann Gautier } 18530d21680cSYann Gautier ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); 18547839a050SYann Gautier if (ret != 0) { 18557839a050SYann Gautier return ret; 18567839a050SYann Gautier } 18577839a050SYann Gautier 18587839a050SYann Gautier /* No ready bit for RTC */ 18590d21680cSYann Gautier mmio_write_32(rcc_base + RCC_RTCDIVR, 18607839a050SYann Gautier clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); 18617839a050SYann Gautier 18627839a050SYann Gautier /* Configure PLLs source */ 18630d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); 18647839a050SYann Gautier if (ret != 0) { 18657839a050SYann Gautier return ret; 18667839a050SYann Gautier } 18677839a050SYann Gautier 18680d21680cSYann Gautier if (!pll3_preserve) { 18690d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); 18707839a050SYann Gautier if (ret != 0) { 18717839a050SYann Gautier return ret; 18727839a050SYann Gautier } 18730d21680cSYann Gautier } 18740d21680cSYann Gautier 18750d21680cSYann Gautier if (!pll4_preserve) { 18760d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); 18770d21680cSYann Gautier if (ret != 0) { 18780d21680cSYann Gautier return ret; 18790d21680cSYann Gautier } 18800d21680cSYann Gautier } 18817839a050SYann Gautier 18827839a050SYann Gautier /* Configure and start PLLs */ 18837839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 18847839a050SYann Gautier uint32_t fracv; 18857839a050SYann Gautier uint32_t csg[PLLCSG_NB]; 18867839a050SYann Gautier 18870d21680cSYann Gautier if (((i == _PLL3) && pll3_preserve) || 18880d21680cSYann Gautier ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { 18890d21680cSYann Gautier continue; 18900d21680cSYann Gautier } 18910d21680cSYann Gautier 18927839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 18937839a050SYann Gautier continue; 18947839a050SYann Gautier } 18957839a050SYann Gautier 18960d21680cSYann Gautier if ((i == _PLL4) && pll4_bootrom) { 18970d21680cSYann Gautier /* Set output divider if not done by the Bootrom */ 18980d21680cSYann Gautier stm32mp1_pll_config_output(i, pllcfg[i]); 18990d21680cSYann Gautier continue; 19000d21680cSYann Gautier } 19010d21680cSYann Gautier 1902be858cffSAndre Przywara fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0); 19037839a050SYann Gautier 19040d21680cSYann Gautier ret = stm32mp1_pll_config(i, pllcfg[i], fracv); 19057839a050SYann Gautier if (ret != 0) { 19067839a050SYann Gautier return ret; 19077839a050SYann Gautier } 190852a616b4SAndre Przywara ret = fdt_read_uint32_array(fdt, plloff[i], "csg", 190952a616b4SAndre Przywara (uint32_t)PLLCSG_NB, csg); 19107839a050SYann Gautier if (ret == 0) { 19110d21680cSYann Gautier stm32mp1_pll_csg(i, csg); 19127839a050SYann Gautier } else if (ret != -FDT_ERR_NOTFOUND) { 19137839a050SYann Gautier return ret; 19147839a050SYann Gautier } 19157839a050SYann Gautier 19160d21680cSYann Gautier stm32mp1_pll_start(i); 19177839a050SYann Gautier } 19187839a050SYann Gautier /* Wait and start PLLs ouptut when ready */ 19197839a050SYann Gautier for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { 19207839a050SYann Gautier if (!fdt_check_node(plloff[i])) { 19217839a050SYann Gautier continue; 19227839a050SYann Gautier } 19237839a050SYann Gautier 19240d21680cSYann Gautier ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); 19257839a050SYann Gautier if (ret != 0) { 19267839a050SYann Gautier return ret; 19277839a050SYann Gautier } 19287839a050SYann Gautier } 19297839a050SYann Gautier /* Wait LSE ready before to use it */ 19300d21680cSYann Gautier if (stm32mp1_osc[_LSE] != 0U) { 19310d21680cSYann Gautier stm32mp1_lse_wait(); 19327839a050SYann Gautier } 19337839a050SYann Gautier 19347839a050SYann Gautier /* Configure with expected clock source */ 19350d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); 19367839a050SYann Gautier if (ret != 0) { 19377839a050SYann Gautier return ret; 19387839a050SYann Gautier } 19390d21680cSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); 19407839a050SYann Gautier if (ret != 0) { 19417839a050SYann Gautier return ret; 19427839a050SYann Gautier } 1943b053a22eSYann Gautier ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); 1944b053a22eSYann Gautier if (ret != 0) { 1945b053a22eSYann Gautier return ret; 1946b053a22eSYann Gautier } 19470d21680cSYann Gautier stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); 19487839a050SYann Gautier 19497839a050SYann Gautier /* Configure PKCK */ 19507839a050SYann Gautier pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); 19517839a050SYann Gautier if (pkcs_cell != NULL) { 19527839a050SYann Gautier bool ckper_disabled = false; 19537839a050SYann Gautier uint32_t j; 19547839a050SYann Gautier 19557839a050SYann Gautier for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { 19563e6fab43SYann Gautier uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); 19577839a050SYann Gautier 19587839a050SYann Gautier if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { 19597839a050SYann Gautier ckper_disabled = true; 19607839a050SYann Gautier continue; 19617839a050SYann Gautier } 19620d21680cSYann Gautier stm32mp1_pkcs_config(pkcs); 19637839a050SYann Gautier } 19647839a050SYann Gautier 19657839a050SYann Gautier /* 19667839a050SYann Gautier * CKPER is source for some peripheral clocks 19677839a050SYann Gautier * (FMC-NAND / QPSI-NOR) and switching source is allowed 19687839a050SYann Gautier * only if previous clock is still ON 19697839a050SYann Gautier * => deactivated CKPER only after switching clock 19707839a050SYann Gautier */ 19717839a050SYann Gautier if (ckper_disabled) { 19720d21680cSYann Gautier stm32mp1_pkcs_config(CLK_CKPER_DISABLED); 19737839a050SYann Gautier } 19747839a050SYann Gautier } 19757839a050SYann Gautier 19767839a050SYann Gautier /* Switch OFF HSI if not found in device-tree */ 19770d21680cSYann Gautier if (stm32mp1_osc[_HSI] == 0U) { 19780d21680cSYann Gautier stm32mp1_hsi_set(false); 19797839a050SYann Gautier } 19800d21680cSYann Gautier stm32mp1_stgen_config(); 19817839a050SYann Gautier 19827839a050SYann Gautier /* Software Self-Refresh mode (SSR) during DDR initilialization */ 19830d21680cSYann Gautier mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, 19847839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_MASK, 19857839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SSR << 19867839a050SYann Gautier RCC_DDRITFCR_DDRCKMOD_SHIFT); 19877839a050SYann Gautier 19887839a050SYann Gautier return 0; 19897839a050SYann Gautier } 19907839a050SYann Gautier 19917839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name, 19927839a050SYann Gautier enum stm32mp_osc_id index) 19937839a050SYann Gautier { 19947839a050SYann Gautier uint32_t frequency; 19957839a050SYann Gautier 19960d21680cSYann Gautier if (fdt_osc_read_freq(name, &frequency) == 0) { 19970d21680cSYann Gautier stm32mp1_osc[index] = frequency; 19987839a050SYann Gautier } 19997839a050SYann Gautier } 20007839a050SYann Gautier 20017839a050SYann Gautier static void stm32mp1_osc_init(void) 20027839a050SYann Gautier { 20037839a050SYann Gautier enum stm32mp_osc_id i; 20047839a050SYann Gautier 20057839a050SYann Gautier for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { 20060d21680cSYann Gautier stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); 20077839a050SYann Gautier } 20087839a050SYann Gautier } 20097839a050SYann Gautier 20106cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void) 20116cb45f89SYann Gautier { 2012033b6c3aSEtienne Carriere unsigned int idx; 2013033b6c3aSEtienne Carriere const unsigned long secure_enable[] = { 2014033b6c3aSEtienne Carriere AXIDCG, 2015033b6c3aSEtienne Carriere BSEC, 2016033b6c3aSEtienne Carriere DDRC1, DDRC1LP, 2017033b6c3aSEtienne Carriere DDRC2, DDRC2LP, 2018033b6c3aSEtienne Carriere DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, 2019033b6c3aSEtienne Carriere DDRPHYC, DDRPHYCLP, 2020033b6c3aSEtienne Carriere TZC1, TZC2, 2021033b6c3aSEtienne Carriere TZPC, 2022033b6c3aSEtienne Carriere STGEN_K, 2023033b6c3aSEtienne Carriere }; 2024033b6c3aSEtienne Carriere 2025033b6c3aSEtienne Carriere for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { 2026033b6c3aSEtienne Carriere stm32mp_clk_enable(secure_enable[idx]); 2027033b6c3aSEtienne Carriere } 2028033b6c3aSEtienne Carriere 20296cb45f89SYann Gautier if (!stm32mp_is_single_core()) { 20306cb45f89SYann Gautier stm32mp1_clk_enable_secure(RTCAPB); 20316cb45f89SYann Gautier } 20326cb45f89SYann Gautier } 20336cb45f89SYann Gautier 20347839a050SYann Gautier int stm32mp1_clk_probe(void) 20357839a050SYann Gautier { 20367839a050SYann Gautier stm32mp1_osc_init(); 20377839a050SYann Gautier 20386cb45f89SYann Gautier sync_earlyboot_clocks_state(); 20396cb45f89SYann Gautier 20407839a050SYann Gautier return 0; 20417839a050SYann Gautier } 2042