xref: /rk3399_ARM-atf/drivers/st/clk/stm32mp1_clk.c (revision b208e3da0487b29bf3d67f3649cc2b1b6159b978)
17839a050SYann Gautier /*
2964e5ff1SNicolas Le Bayon  * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved
37839a050SYann Gautier  *
47839a050SYann Gautier  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
57839a050SYann Gautier  */
67839a050SYann Gautier 
77839a050SYann Gautier #include <assert.h>
87839a050SYann Gautier #include <errno.h>
97839a050SYann Gautier #include <stdint.h>
1039b6cc66SAntonio Nino Diaz #include <stdio.h>
1109d40e0eSAntonio Nino Diaz 
1209d40e0eSAntonio Nino Diaz #include <arch.h>
1309d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1409d40e0eSAntonio Nino Diaz #include <common/debug.h>
1552a616b4SAndre Przywara #include <common/fdt_wrappers.h>
1633667d29SYann Gautier #include <drivers/clk.h>
1709d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h>
1809d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h>
19447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h>
2009d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h>
2109d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h>
2209d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h>
2309d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
240d21680cSYann Gautier #include <lib/spinlock.h>
2509d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
26964e5ff1SNicolas Le Bayon #include <libfdt.h>
2709d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
2809d40e0eSAntonio Nino Diaz 
29964e5ff1SNicolas Le Bayon #include <platform_def.h>
30964e5ff1SNicolas Le Bayon 
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,
59cbd2e8a6SGabriel Fernandez 	_HSE_RTC,
607839a050SYann Gautier 	_CSI_KER,
617839a050SYann Gautier 	_PLL1_P,
627839a050SYann Gautier 	_PLL1_Q,
637839a050SYann Gautier 	_PLL1_R,
647839a050SYann Gautier 	_PLL2_P,
657839a050SYann Gautier 	_PLL2_Q,
667839a050SYann Gautier 	_PLL2_R,
677839a050SYann Gautier 	_PLL3_P,
687839a050SYann Gautier 	_PLL3_Q,
697839a050SYann Gautier 	_PLL3_R,
707839a050SYann Gautier 	_PLL4_P,
717839a050SYann Gautier 	_PLL4_Q,
727839a050SYann Gautier 	_PLL4_R,
737839a050SYann Gautier 	_ACLK,
747839a050SYann Gautier 	_PCLK1,
757839a050SYann Gautier 	_PCLK2,
767839a050SYann Gautier 	_PCLK3,
777839a050SYann Gautier 	_PCLK4,
787839a050SYann Gautier 	_PCLK5,
797839a050SYann Gautier 	_HCLK6,
807839a050SYann Gautier 	_HCLK2,
817839a050SYann Gautier 	_CK_PER,
827839a050SYann Gautier 	_CK_MPU,
83b053a22eSYann Gautier 	_CK_MCU,
840d21680cSYann Gautier 	_USB_PHY_48,
857839a050SYann Gautier 	_PARENT_NB,
867839a050SYann Gautier 	_UNKNOWN_ID = 0xff,
877839a050SYann Gautier };
887839a050SYann Gautier 
890d21680cSYann Gautier /* Lists only the parent clock we are interested in */
907839a050SYann Gautier enum stm32mp1_parent_sel {
910d21680cSYann Gautier 	_I2C12_SEL,
920d21680cSYann Gautier 	_I2C35_SEL,
930d21680cSYann Gautier 	_STGEN_SEL,
947839a050SYann Gautier 	_I2C46_SEL,
950d21680cSYann Gautier 	_SPI6_SEL,
96d4151d2fSYann Gautier 	_UART1_SEL,
970d21680cSYann Gautier 	_RNG1_SEL,
987839a050SYann Gautier 	_UART6_SEL,
997839a050SYann Gautier 	_UART24_SEL,
1007839a050SYann Gautier 	_UART35_SEL,
1017839a050SYann Gautier 	_UART78_SEL,
1027839a050SYann Gautier 	_SDMMC12_SEL,
1037839a050SYann Gautier 	_SDMMC3_SEL,
1047839a050SYann Gautier 	_QSPI_SEL,
1057839a050SYann Gautier 	_FMC_SEL,
106d4151d2fSYann Gautier 	_AXIS_SEL,
107d4151d2fSYann Gautier 	_MCUS_SEL,
1087839a050SYann Gautier 	_USBPHY_SEL,
1097839a050SYann Gautier 	_USBO_SEL,
1108fbcd9e4SEtienne Carriere 	_MPU_SEL,
111288f5cf2SYann Gautier 	_CKPER_SEL,
112016af006SEtienne Carriere 	_RTC_SEL,
1137839a050SYann Gautier 	_PARENT_SEL_NB,
1147839a050SYann Gautier 	_UNKNOWN_SEL = 0xff,
1157839a050SYann Gautier };
1167839a050SYann Gautier 
1178fbcd9e4SEtienne Carriere /* State the parent clock ID straight related to a clock */
1188fbcd9e4SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = {
1198fbcd9e4SEtienne Carriere 	[_HSE] = CK_HSE,
1208fbcd9e4SEtienne Carriere 	[_HSI] = CK_HSI,
1218fbcd9e4SEtienne Carriere 	[_CSI] = CK_CSI,
1228fbcd9e4SEtienne Carriere 	[_LSE] = CK_LSE,
1238fbcd9e4SEtienne Carriere 	[_LSI] = CK_LSI,
1248fbcd9e4SEtienne Carriere 	[_I2S_CKIN] = _UNKNOWN_ID,
1258fbcd9e4SEtienne Carriere 	[_USB_PHY_48] = _UNKNOWN_ID,
1268fbcd9e4SEtienne Carriere 	[_HSI_KER] = CK_HSI,
1278fbcd9e4SEtienne Carriere 	[_HSE_KER] = CK_HSE,
1288fbcd9e4SEtienne Carriere 	[_HSE_KER_DIV2] = CK_HSE_DIV2,
129cbd2e8a6SGabriel Fernandez 	[_HSE_RTC] = _UNKNOWN_ID,
1308fbcd9e4SEtienne Carriere 	[_CSI_KER] = CK_CSI,
1318fbcd9e4SEtienne Carriere 	[_PLL1_P] = PLL1_P,
1328fbcd9e4SEtienne Carriere 	[_PLL1_Q] = PLL1_Q,
1338fbcd9e4SEtienne Carriere 	[_PLL1_R] = PLL1_R,
1348fbcd9e4SEtienne Carriere 	[_PLL2_P] = PLL2_P,
1358fbcd9e4SEtienne Carriere 	[_PLL2_Q] = PLL2_Q,
1368fbcd9e4SEtienne Carriere 	[_PLL2_R] = PLL2_R,
1378fbcd9e4SEtienne Carriere 	[_PLL3_P] = PLL3_P,
1388fbcd9e4SEtienne Carriere 	[_PLL3_Q] = PLL3_Q,
1398fbcd9e4SEtienne Carriere 	[_PLL3_R] = PLL3_R,
1408fbcd9e4SEtienne Carriere 	[_PLL4_P] = PLL4_P,
1418fbcd9e4SEtienne Carriere 	[_PLL4_Q] = PLL4_Q,
1428fbcd9e4SEtienne Carriere 	[_PLL4_R] = PLL4_R,
1438fbcd9e4SEtienne Carriere 	[_ACLK] = CK_AXI,
1448fbcd9e4SEtienne Carriere 	[_PCLK1] = CK_AXI,
1458fbcd9e4SEtienne Carriere 	[_PCLK2] = CK_AXI,
1468fbcd9e4SEtienne Carriere 	[_PCLK3] = CK_AXI,
1478fbcd9e4SEtienne Carriere 	[_PCLK4] = CK_AXI,
1488fbcd9e4SEtienne Carriere 	[_PCLK5] = CK_AXI,
1498fbcd9e4SEtienne Carriere 	[_CK_PER] = CK_PER,
1508fbcd9e4SEtienne Carriere 	[_CK_MPU] = CK_MPU,
1518fbcd9e4SEtienne Carriere 	[_CK_MCU] = CK_MCU,
1528fbcd9e4SEtienne Carriere };
1538fbcd9e4SEtienne Carriere 
1548fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id)
1558fbcd9e4SEtienne Carriere {
1568fbcd9e4SEtienne Carriere 	unsigned int n;
1578fbcd9e4SEtienne Carriere 
1588fbcd9e4SEtienne Carriere 	for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
1598fbcd9e4SEtienne Carriere 		if (parent_id_clock_id[n] == id) {
1608fbcd9e4SEtienne Carriere 			return n;
1618fbcd9e4SEtienne Carriere 		}
1628fbcd9e4SEtienne Carriere 	}
1638fbcd9e4SEtienne Carriere 
1648fbcd9e4SEtienne Carriere 	return _UNKNOWN_ID;
1658fbcd9e4SEtienne Carriere }
1668fbcd9e4SEtienne Carriere 
1677839a050SYann Gautier enum stm32mp1_pll_id {
1687839a050SYann Gautier 	_PLL1,
1697839a050SYann Gautier 	_PLL2,
1707839a050SYann Gautier 	_PLL3,
1717839a050SYann Gautier 	_PLL4,
1727839a050SYann Gautier 	_PLL_NB
1737839a050SYann Gautier };
1747839a050SYann Gautier 
1757839a050SYann Gautier enum stm32mp1_div_id {
1767839a050SYann Gautier 	_DIV_P,
1777839a050SYann Gautier 	_DIV_Q,
1787839a050SYann Gautier 	_DIV_R,
1797839a050SYann Gautier 	_DIV_NB,
1807839a050SYann Gautier };
1817839a050SYann Gautier 
1827839a050SYann Gautier enum stm32mp1_clksrc_id {
1837839a050SYann Gautier 	CLKSRC_MPU,
1847839a050SYann Gautier 	CLKSRC_AXI,
185b053a22eSYann Gautier 	CLKSRC_MCU,
1867839a050SYann Gautier 	CLKSRC_PLL12,
1877839a050SYann Gautier 	CLKSRC_PLL3,
1887839a050SYann Gautier 	CLKSRC_PLL4,
1897839a050SYann Gautier 	CLKSRC_RTC,
1907839a050SYann Gautier 	CLKSRC_MCO1,
1917839a050SYann Gautier 	CLKSRC_MCO2,
1927839a050SYann Gautier 	CLKSRC_NB
1937839a050SYann Gautier };
1947839a050SYann Gautier 
1957839a050SYann Gautier enum stm32mp1_clkdiv_id {
1967839a050SYann Gautier 	CLKDIV_MPU,
1977839a050SYann Gautier 	CLKDIV_AXI,
198b053a22eSYann Gautier 	CLKDIV_MCU,
1997839a050SYann Gautier 	CLKDIV_APB1,
2007839a050SYann Gautier 	CLKDIV_APB2,
2017839a050SYann Gautier 	CLKDIV_APB3,
2027839a050SYann Gautier 	CLKDIV_APB4,
2037839a050SYann Gautier 	CLKDIV_APB5,
2047839a050SYann Gautier 	CLKDIV_RTC,
2057839a050SYann Gautier 	CLKDIV_MCO1,
2067839a050SYann Gautier 	CLKDIV_MCO2,
2077839a050SYann Gautier 	CLKDIV_NB
2087839a050SYann Gautier };
2097839a050SYann Gautier 
2107839a050SYann Gautier enum stm32mp1_pllcfg {
2117839a050SYann Gautier 	PLLCFG_M,
2127839a050SYann Gautier 	PLLCFG_N,
2137839a050SYann Gautier 	PLLCFG_P,
2147839a050SYann Gautier 	PLLCFG_Q,
2157839a050SYann Gautier 	PLLCFG_R,
2167839a050SYann Gautier 	PLLCFG_O,
2177839a050SYann Gautier 	PLLCFG_NB
2187839a050SYann Gautier };
2197839a050SYann Gautier 
2207839a050SYann Gautier enum stm32mp1_pllcsg {
2217839a050SYann Gautier 	PLLCSG_MOD_PER,
2227839a050SYann Gautier 	PLLCSG_INC_STEP,
2237839a050SYann Gautier 	PLLCSG_SSCG_MODE,
2247839a050SYann Gautier 	PLLCSG_NB
2257839a050SYann Gautier };
2267839a050SYann Gautier 
2277839a050SYann Gautier enum stm32mp1_plltype {
2287839a050SYann Gautier 	PLL_800,
2297839a050SYann Gautier 	PLL_1600,
2307839a050SYann Gautier 	PLL_TYPE_NB
2317839a050SYann Gautier };
2327839a050SYann Gautier 
2337839a050SYann Gautier struct stm32mp1_pll {
2347839a050SYann Gautier 	uint8_t refclk_min;
2357839a050SYann Gautier 	uint8_t refclk_max;
2367839a050SYann Gautier 	uint8_t divn_max;
2377839a050SYann Gautier };
2387839a050SYann Gautier 
2397839a050SYann Gautier struct stm32mp1_clk_gate {
2407839a050SYann Gautier 	uint16_t offset;
2417839a050SYann Gautier 	uint8_t bit;
2427839a050SYann Gautier 	uint8_t index;
2437839a050SYann Gautier 	uint8_t set_clr;
2440d21680cSYann Gautier 	uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
2450d21680cSYann Gautier 	uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
2467839a050SYann Gautier };
2477839a050SYann Gautier 
2487839a050SYann Gautier struct stm32mp1_clk_sel {
2497839a050SYann Gautier 	uint16_t offset;
2507839a050SYann Gautier 	uint8_t src;
2517839a050SYann Gautier 	uint8_t msk;
2527839a050SYann Gautier 	uint8_t nb_parent;
2537839a050SYann Gautier 	const uint8_t *parent;
2547839a050SYann Gautier };
2557839a050SYann Gautier 
2567839a050SYann Gautier #define REFCLK_SIZE 4
2577839a050SYann Gautier struct stm32mp1_clk_pll {
2587839a050SYann Gautier 	enum stm32mp1_plltype plltype;
2597839a050SYann Gautier 	uint16_t rckxselr;
2607839a050SYann Gautier 	uint16_t pllxcfgr1;
2617839a050SYann Gautier 	uint16_t pllxcfgr2;
2627839a050SYann Gautier 	uint16_t pllxfracr;
2637839a050SYann Gautier 	uint16_t pllxcr;
2647839a050SYann Gautier 	uint16_t pllxcsgr;
2657839a050SYann Gautier 	enum stm32mp_osc_id refclk[REFCLK_SIZE];
2667839a050SYann Gautier };
2677839a050SYann Gautier 
2680d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */
2690d21680cSYann Gautier #define _CLK_SELEC(off, b, idx, s)			\
2707839a050SYann Gautier 	{						\
2717839a050SYann Gautier 		.offset = (off),			\
2727839a050SYann Gautier 		.bit = (b),				\
2737839a050SYann Gautier 		.index = (idx),				\
2747839a050SYann Gautier 		.set_clr = 0,				\
2757839a050SYann Gautier 		.sel = (s),				\
2767839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
2777839a050SYann Gautier 	}
2787839a050SYann Gautier 
2790d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */
2800d21680cSYann Gautier #define _CLK_FIXED(off, b, idx, f)			\
2817839a050SYann Gautier 	{						\
2827839a050SYann Gautier 		.offset = (off),			\
2837839a050SYann Gautier 		.bit = (b),				\
2847839a050SYann Gautier 		.index = (idx),				\
2857839a050SYann Gautier 		.set_clr = 0,				\
2867839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
2877839a050SYann Gautier 		.fixed = (f),				\
2887839a050SYann Gautier 	}
2897839a050SYann Gautier 
2900d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */
2910d21680cSYann Gautier #define _CLK_SC_SELEC(off, b, idx, s)			\
2927839a050SYann Gautier 	{						\
2937839a050SYann Gautier 		.offset = (off),			\
2947839a050SYann Gautier 		.bit = (b),				\
2957839a050SYann Gautier 		.index = (idx),				\
2967839a050SYann Gautier 		.set_clr = 1,				\
2977839a050SYann Gautier 		.sel = (s),				\
2987839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
2997839a050SYann Gautier 	}
3007839a050SYann Gautier 
3010d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */
3020d21680cSYann Gautier #define _CLK_SC_FIXED(off, b, idx, f)			\
3037839a050SYann Gautier 	{						\
3047839a050SYann Gautier 		.offset = (off),			\
3057839a050SYann Gautier 		.bit = (b),				\
3067839a050SYann Gautier 		.index = (idx),				\
3077839a050SYann Gautier 		.set_clr = 1,				\
3087839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
3097839a050SYann Gautier 		.fixed = (f),				\
3107839a050SYann Gautier 	}
3117839a050SYann Gautier 
312d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents)		\
313d4151d2fSYann Gautier 	[_ ## _label ## _SEL] = {				\
314d4151d2fSYann Gautier 		.offset = _rcc_selr,				\
315d4151d2fSYann Gautier 		.src = _rcc_selr ## _ ## _label ## SRC_SHIFT,	\
3168ae08dcdSEtienne Carriere 		.msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \
3178ae08dcdSEtienne Carriere 		       (_rcc_selr ## _ ## _label ## SRC_SHIFT), \
318d4151d2fSYann Gautier 		.parent = (_parents),				\
319d4151d2fSYann Gautier 		.nb_parent = ARRAY_SIZE(_parents)		\
3207839a050SYann Gautier 	}
3217839a050SYann Gautier 
3220d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3,		\
3237839a050SYann Gautier 		 off4, off5, off6,			\
3247839a050SYann Gautier 		 p1, p2, p3, p4)			\
3257839a050SYann Gautier 	[(idx)] = {					\
3267839a050SYann Gautier 		.plltype = (type),			\
3277839a050SYann Gautier 		.rckxselr = (off1),			\
3287839a050SYann Gautier 		.pllxcfgr1 = (off2),			\
3297839a050SYann Gautier 		.pllxcfgr2 = (off3),			\
3307839a050SYann Gautier 		.pllxfracr = (off4),			\
3317839a050SYann Gautier 		.pllxcr = (off5),			\
3327839a050SYann Gautier 		.pllxcsgr = (off6),			\
3337839a050SYann Gautier 		.refclk[0] = (p1),			\
3347839a050SYann Gautier 		.refclk[1] = (p2),			\
3357839a050SYann Gautier 		.refclk[2] = (p3),			\
3367839a050SYann Gautier 		.refclk[3] = (p4),			\
3377839a050SYann Gautier 	}
3387839a050SYann Gautier 
3390d21680cSYann Gautier #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
3400d21680cSYann Gautier 
3417839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
3420d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK),
3430d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
3440d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK),
3450d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
3460d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
3470d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
3480d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
3490d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
3500d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK),
3510d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
3520d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
3537839a050SYann Gautier 
3540d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
3550d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
3560d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
3570d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
3580d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
3590d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
3600d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
3610d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
3620d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
3630d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
3640d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
3657839a050SYann Gautier 
3660d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
3670d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
3687839a050SYann Gautier 
369f33b2433SYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
370f33b2433SYann Gautier 
3710d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
3720d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
3730d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
3747839a050SYann Gautier 
3750d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
3760d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
3770d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
378d4151d2fSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
3790d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
3800d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
3810d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
3820d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
3830d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
3840d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
3850d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
3867839a050SYann Gautier 
3870d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
3880d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
3897839a050SYann Gautier 
3900d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
3910d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
3920d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
3930d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
3940d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
3950d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
3960d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
3970d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
3980d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
3990d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
4000d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
4017839a050SYann Gautier 
4020d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
4030d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
4040d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
4050d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
4060d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
4077839a050SYann Gautier 
4080d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
4090d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
4100d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
4110d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
4120d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
4137839a050SYann Gautier 
414016af006SEtienne Carriere 	_CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL),
4150d21680cSYann Gautier 	_CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
4167839a050SYann Gautier };
4177839a050SYann Gautier 
4180d21680cSYann Gautier static const uint8_t i2c12_parents[] = {
4190d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4200d21680cSYann Gautier };
4210d21680cSYann Gautier 
4220d21680cSYann Gautier static const uint8_t i2c35_parents[] = {
4230d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4240d21680cSYann Gautier };
4250d21680cSYann Gautier 
4260d21680cSYann Gautier static const uint8_t stgen_parents[] = {
4270d21680cSYann Gautier 	_HSI_KER, _HSE_KER
4280d21680cSYann Gautier };
4290d21680cSYann Gautier 
4300d21680cSYann Gautier static const uint8_t i2c46_parents[] = {
4310d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
4320d21680cSYann Gautier };
4330d21680cSYann Gautier 
4340d21680cSYann Gautier static const uint8_t spi6_parents[] = {
4350d21680cSYann Gautier 	_PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
4360d21680cSYann Gautier };
4370d21680cSYann Gautier 
4380d21680cSYann Gautier static const uint8_t usart1_parents[] = {
4390d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
4400d21680cSYann Gautier };
4410d21680cSYann Gautier 
4420d21680cSYann Gautier static const uint8_t rng1_parents[] = {
4430d21680cSYann Gautier 	_CSI, _PLL4_R, _LSE, _LSI
4440d21680cSYann Gautier };
4450d21680cSYann Gautier 
4460d21680cSYann Gautier static const uint8_t uart6_parents[] = {
4470d21680cSYann Gautier 	_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4480d21680cSYann Gautier };
4490d21680cSYann Gautier 
4500d21680cSYann Gautier static const uint8_t uart234578_parents[] = {
4510d21680cSYann Gautier 	_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4520d21680cSYann Gautier };
4530d21680cSYann Gautier 
4540d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = {
4550d21680cSYann Gautier 	_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
4560d21680cSYann Gautier };
4570d21680cSYann Gautier 
4580d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = {
4590d21680cSYann Gautier 	_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
4600d21680cSYann Gautier };
4610d21680cSYann Gautier 
4620d21680cSYann Gautier static const uint8_t qspi_parents[] = {
4630d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4640d21680cSYann Gautier };
4650d21680cSYann Gautier 
4660d21680cSYann Gautier static const uint8_t fmc_parents[] = {
4670d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4680d21680cSYann Gautier };
4690d21680cSYann Gautier 
470b8fe48b6SEtienne Carriere static const uint8_t axiss_parents[] = {
471b8fe48b6SEtienne Carriere 	_HSI, _HSE, _PLL2_P
4720d21680cSYann Gautier };
4730d21680cSYann Gautier 
474b8fe48b6SEtienne Carriere static const uint8_t mcuss_parents[] = {
475b8fe48b6SEtienne Carriere 	_HSI, _HSE, _CSI, _PLL3_P
476b053a22eSYann Gautier };
477b053a22eSYann Gautier 
4780d21680cSYann Gautier static const uint8_t usbphy_parents[] = {
4790d21680cSYann Gautier 	_HSE_KER, _PLL4_R, _HSE_KER_DIV2
4800d21680cSYann Gautier };
4810d21680cSYann Gautier 
4820d21680cSYann Gautier static const uint8_t usbo_parents[] = {
4830d21680cSYann Gautier 	_PLL4_R, _USB_PHY_48
4840d21680cSYann Gautier };
4857839a050SYann Gautier 
4868fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = {
4878fbcd9e4SEtienne Carriere 	_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
4888fbcd9e4SEtienne Carriere };
4898fbcd9e4SEtienne Carriere 
4908fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = {
4918fbcd9e4SEtienne Carriere 	_HSI, _HSE, _CSI,
4928fbcd9e4SEtienne Carriere };
4938fbcd9e4SEtienne Carriere 
494016af006SEtienne Carriere static const uint8_t rtc_parents[] = {
495cbd2e8a6SGabriel Fernandez 	_UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
496016af006SEtienne Carriere };
497016af006SEtienne Carriere 
4987839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
499d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
500d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
501d4151d2fSYann Gautier 	_CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
502d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
503d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
504d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
505d4151d2fSYann Gautier 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
5068fbcd9e4SEtienne Carriere 	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
507288f5cf2SYann Gautier 	_CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents),
508016af006SEtienne Carriere 	_CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
509d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
510d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
511d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
512d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
513d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
514d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
515d4151d2fSYann Gautier 	_CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
516d4151d2fSYann Gautier 	_CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
517b8fe48b6SEtienne Carriere 	_CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents),
518b8fe48b6SEtienne Carriere 	_CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents),
519d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
520d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
5217839a050SYann Gautier };
5227839a050SYann Gautier 
5237839a050SYann Gautier /* Define characteristic of PLL according type */
5247839a050SYann Gautier #define DIVN_MIN	24
5257839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
5267839a050SYann Gautier 	[PLL_800] = {
5277839a050SYann Gautier 		.refclk_min = 4,
5287839a050SYann Gautier 		.refclk_max = 16,
5297839a050SYann Gautier 		.divn_max = 99,
5307839a050SYann Gautier 	},
5317839a050SYann Gautier 	[PLL_1600] = {
5327839a050SYann Gautier 		.refclk_min = 8,
5337839a050SYann Gautier 		.refclk_max = 16,
5347839a050SYann Gautier 		.divn_max = 199,
5357839a050SYann Gautier 	},
5367839a050SYann Gautier };
5377839a050SYann Gautier 
5387839a050SYann Gautier /* PLLNCFGR2 register divider by output */
5397839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = {
5407839a050SYann Gautier 	[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
5417839a050SYann Gautier 	[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
5420d21680cSYann Gautier 	[_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
5437839a050SYann Gautier };
5447839a050SYann Gautier 
5457839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
5460d21680cSYann Gautier 	_CLK_PLL(_PLL1, PLL_1600,
5477839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
5487839a050SYann Gautier 		 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
5497839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5500d21680cSYann Gautier 	_CLK_PLL(_PLL2, PLL_1600,
5517839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
5527839a050SYann Gautier 		 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
5537839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5540d21680cSYann Gautier 	_CLK_PLL(_PLL3, PLL_800,
5557839a050SYann Gautier 		 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
5567839a050SYann Gautier 		 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
5577839a050SYann Gautier 		 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
5580d21680cSYann Gautier 	_CLK_PLL(_PLL4, PLL_800,
5597839a050SYann Gautier 		 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
5607839a050SYann Gautier 		 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
5617839a050SYann Gautier 		 _HSI, _HSE, _CSI, _I2S_CKIN),
5627839a050SYann Gautier };
5637839a050SYann Gautier 
5647839a050SYann Gautier /* Prescaler table lookups for clock computation */
565b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
566b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = {
567b053a22eSYann Gautier 	0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
568b053a22eSYann Gautier };
5697839a050SYann Gautier 
5707839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
5717839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
5727839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
5737839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = {
5747839a050SYann Gautier 	0, 1, 2, 3, 4, 4, 4, 4
5757839a050SYann Gautier };
5767839a050SYann Gautier 
5777839a050SYann Gautier /* div = /1 /2 /3 /4 */
5787839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = {
5797839a050SYann Gautier 	1, 2, 3, 4, 4, 4, 4, 4
5807839a050SYann Gautier };
5817839a050SYann Gautier 
58237e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
58337e8295aSEtienne Carriere 	[_HSI] = "HSI",
58437e8295aSEtienne Carriere 	[_HSE] = "HSE",
58537e8295aSEtienne Carriere 	[_CSI] = "CSI",
58637e8295aSEtienne Carriere 	[_LSI] = "LSI",
58737e8295aSEtienne Carriere 	[_LSE] = "LSE",
58837e8295aSEtienne Carriere 	[_I2S_CKIN] = "I2S_CKIN",
58937e8295aSEtienne Carriere 	[_HSI_KER] = "HSI_KER",
59037e8295aSEtienne Carriere 	[_HSE_KER] = "HSE_KER",
59137e8295aSEtienne Carriere 	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
592cbd2e8a6SGabriel Fernandez 	[_HSE_RTC] = "HSE_RTC",
59337e8295aSEtienne Carriere 	[_CSI_KER] = "CSI_KER",
59437e8295aSEtienne Carriere 	[_PLL1_P] = "PLL1_P",
59537e8295aSEtienne Carriere 	[_PLL1_Q] = "PLL1_Q",
59637e8295aSEtienne Carriere 	[_PLL1_R] = "PLL1_R",
59737e8295aSEtienne Carriere 	[_PLL2_P] = "PLL2_P",
59837e8295aSEtienne Carriere 	[_PLL2_Q] = "PLL2_Q",
59937e8295aSEtienne Carriere 	[_PLL2_R] = "PLL2_R",
60037e8295aSEtienne Carriere 	[_PLL3_P] = "PLL3_P",
60137e8295aSEtienne Carriere 	[_PLL3_Q] = "PLL3_Q",
60237e8295aSEtienne Carriere 	[_PLL3_R] = "PLL3_R",
60337e8295aSEtienne Carriere 	[_PLL4_P] = "PLL4_P",
60437e8295aSEtienne Carriere 	[_PLL4_Q] = "PLL4_Q",
60537e8295aSEtienne Carriere 	[_PLL4_R] = "PLL4_R",
60637e8295aSEtienne Carriere 	[_ACLK] = "ACLK",
60737e8295aSEtienne Carriere 	[_PCLK1] = "PCLK1",
60837e8295aSEtienne Carriere 	[_PCLK2] = "PCLK2",
60937e8295aSEtienne Carriere 	[_PCLK3] = "PCLK3",
61037e8295aSEtienne Carriere 	[_PCLK4] = "PCLK4",
61137e8295aSEtienne Carriere 	[_PCLK5] = "PCLK5",
61237e8295aSEtienne Carriere 	[_HCLK6] = "KCLK6",
61337e8295aSEtienne Carriere 	[_HCLK2] = "HCLK2",
61437e8295aSEtienne Carriere 	[_CK_PER] = "CK_PER",
61537e8295aSEtienne Carriere 	[_CK_MPU] = "CK_MPU",
61637e8295aSEtienne Carriere 	[_CK_MCU] = "CK_MCU",
61737e8295aSEtienne Carriere 	[_USB_PHY_48] = "USB_PHY_48",
61837e8295aSEtienne Carriere };
61937e8295aSEtienne Carriere 
6200d21680cSYann Gautier /* RCC clock device driver private */
6210d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC];
6220d21680cSYann Gautier static struct spinlock reg_lock;
6230d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES];
6240d21680cSYann Gautier static struct spinlock refcount_lock;
6257839a050SYann Gautier 
6260d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
6270d21680cSYann Gautier {
6280d21680cSYann Gautier 	return &stm32mp1_clk_gate[idx];
6290d21680cSYann Gautier }
6307839a050SYann Gautier 
6310d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
6320d21680cSYann Gautier {
6330d21680cSYann Gautier 	return &stm32mp1_clk_sel[idx];
6340d21680cSYann Gautier }
6350d21680cSYann Gautier 
6360d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
6370d21680cSYann Gautier {
6380d21680cSYann Gautier 	return &stm32mp1_clk_pll[idx];
6390d21680cSYann Gautier }
6400d21680cSYann Gautier 
6410d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock)
6420d21680cSYann Gautier {
643e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6440d21680cSYann Gautier 		/* Assume interrupts are masked */
6450d21680cSYann Gautier 		spin_lock(lock);
6460d21680cSYann Gautier 	}
647e463d3f4SYann Gautier }
6480d21680cSYann Gautier 
6490d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock)
6500d21680cSYann Gautier {
651e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6520d21680cSYann Gautier 		spin_unlock(lock);
6530d21680cSYann Gautier 	}
654e463d3f4SYann Gautier }
6550d21680cSYann Gautier 
6560d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void)
6570d21680cSYann Gautier {
6580d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6591bb9072aSEtienne Carriere 	uint32_t mask = RCC_TZCR_TZEN;
6600d21680cSYann Gautier 
6611bb9072aSEtienne Carriere 	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
6620d21680cSYann Gautier }
6630d21680cSYann Gautier 
664b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void)
665b053a22eSYann Gautier {
666b053a22eSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6671bb9072aSEtienne Carriere 	uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT;
668b053a22eSYann Gautier 
6691bb9072aSEtienne Carriere 	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
670b053a22eSYann Gautier }
671b053a22eSYann Gautier 
6720d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void)
6730d21680cSYann Gautier {
6740d21680cSYann Gautier 	stm32mp1_clk_lock(&reg_lock);
6750d21680cSYann Gautier }
6760d21680cSYann Gautier 
6770d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void)
6780d21680cSYann Gautier {
6790d21680cSYann Gautier 	stm32mp1_clk_unlock(&reg_lock);
6800d21680cSYann Gautier }
6810d21680cSYann Gautier 
6820d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
6837839a050SYann Gautier {
6847839a050SYann Gautier 	if (idx >= NB_OSC) {
6857839a050SYann Gautier 		return 0;
6867839a050SYann Gautier 	}
6877839a050SYann Gautier 
6880d21680cSYann Gautier 	return stm32mp1_osc[idx];
6897839a050SYann Gautier }
6907839a050SYann Gautier 
6910d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id)
6927839a050SYann Gautier {
6930d21680cSYann Gautier 	unsigned int i;
6947839a050SYann Gautier 
6950d21680cSYann Gautier 	for (i = 0U; i < NB_GATES; i++) {
6960d21680cSYann Gautier 		if (gate_ref(i)->index == id) {
6977839a050SYann Gautier 			return i;
6987839a050SYann Gautier 		}
6997839a050SYann Gautier 	}
7007839a050SYann Gautier 
7017839a050SYann Gautier 	ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id);
7027839a050SYann Gautier 
7037839a050SYann Gautier 	return -EINVAL;
7047839a050SYann Gautier }
7057839a050SYann Gautier 
7060d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
7077839a050SYann Gautier {
7080d21680cSYann Gautier 	return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
7097839a050SYann Gautier }
7107839a050SYann Gautier 
7110d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
7127839a050SYann Gautier {
7130d21680cSYann Gautier 	return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
7147839a050SYann Gautier }
7157839a050SYann Gautier 
7160d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id)
7177839a050SYann Gautier {
7180d21680cSYann Gautier 	const struct stm32mp1_clk_sel *sel;
7198fbcd9e4SEtienne Carriere 	uint32_t p_sel;
7207839a050SYann Gautier 	int i;
7217839a050SYann Gautier 	enum stm32mp1_parent_id p;
7227839a050SYann Gautier 	enum stm32mp1_parent_sel s;
7230d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7247839a050SYann Gautier 
7258fbcd9e4SEtienne Carriere 	/* Few non gateable clock have a static parent ID, find them */
7268fbcd9e4SEtienne Carriere 	i = (int)clock_id2parent_id(id);
7278fbcd9e4SEtienne Carriere 	if (i != _UNKNOWN_ID) {
7288fbcd9e4SEtienne Carriere 		return i;
7297839a050SYann Gautier 	}
7307839a050SYann Gautier 
7310d21680cSYann Gautier 	i = stm32mp1_clk_get_gated_id(id);
7327839a050SYann Gautier 	if (i < 0) {
7330d21680cSYann Gautier 		panic();
7347839a050SYann Gautier 	}
7357839a050SYann Gautier 
7360d21680cSYann Gautier 	p = stm32mp1_clk_get_fixed_parent(i);
7377839a050SYann Gautier 	if (p < _PARENT_NB) {
7387839a050SYann Gautier 		return (int)p;
7397839a050SYann Gautier 	}
7407839a050SYann Gautier 
7410d21680cSYann Gautier 	s = stm32mp1_clk_get_sel(i);
7420d21680cSYann Gautier 	if (s == _UNKNOWN_SEL) {
7430d21680cSYann Gautier 		return -EINVAL;
7440d21680cSYann Gautier 	}
7457839a050SYann Gautier 	if (s >= _PARENT_SEL_NB) {
7460d21680cSYann Gautier 		panic();
7477839a050SYann Gautier 	}
7487839a050SYann Gautier 
7490d21680cSYann Gautier 	sel = clk_sel_ref(s);
7508ae08dcdSEtienne Carriere 	p_sel = (mmio_read_32(rcc_base + sel->offset) &
7518ae08dcdSEtienne Carriere 		 (sel->msk << sel->src)) >> sel->src;
7520d21680cSYann Gautier 	if (p_sel < sel->nb_parent) {
7530d21680cSYann Gautier 		return (int)sel->parent[p_sel];
7547839a050SYann Gautier 	}
7557839a050SYann Gautier 
7567839a050SYann Gautier 	return -EINVAL;
7577839a050SYann Gautier }
7587839a050SYann Gautier 
7590d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
7607839a050SYann Gautier {
7610d21680cSYann Gautier 	uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
7620d21680cSYann Gautier 	uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
7637839a050SYann Gautier 
7640d21680cSYann Gautier 	return stm32mp1_clk_get_fixed(pll->refclk[src]);
7657839a050SYann Gautier }
7667839a050SYann Gautier 
7677839a050SYann Gautier /*
7687839a050SYann Gautier  * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
7697839a050SYann Gautier  * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
7707839a050SYann Gautier  * - PLL3 & PLL4 => return VCO     with Fpll_y_ck = FVCO / (DIVy + 1)
7717839a050SYann Gautier  * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
7727839a050SYann Gautier  */
7730d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
7747839a050SYann Gautier {
7757839a050SYann Gautier 	unsigned long refclk, fvco;
7767839a050SYann Gautier 	uint32_t cfgr1, fracr, divm, divn;
7770d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7787839a050SYann Gautier 
7790d21680cSYann Gautier 	cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
7800d21680cSYann Gautier 	fracr = mmio_read_32(rcc_base + pll->pllxfracr);
7817839a050SYann Gautier 
7827839a050SYann Gautier 	divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
7837839a050SYann Gautier 	divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
7847839a050SYann Gautier 
7850d21680cSYann Gautier 	refclk = stm32mp1_pll_get_fref(pll);
7867839a050SYann Gautier 
7877839a050SYann Gautier 	/*
7887839a050SYann Gautier 	 * With FRACV :
7897839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
7907839a050SYann Gautier 	 * Without FRACV
7917839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
7927839a050SYann Gautier 	 */
7937839a050SYann Gautier 	if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
7940d21680cSYann Gautier 		uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
7950d21680cSYann Gautier 				 RCC_PLLNFRACR_FRACV_SHIFT;
7967839a050SYann Gautier 		unsigned long long numerator, denominator;
7977839a050SYann Gautier 
7980d21680cSYann Gautier 		numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
7990d21680cSYann Gautier 		numerator = refclk * numerator;
8007839a050SYann Gautier 		denominator = ((unsigned long long)divm + 1U) << 13;
8017839a050SYann Gautier 		fvco = (unsigned long)(numerator / denominator);
8027839a050SYann Gautier 	} else {
8037839a050SYann Gautier 		fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
8047839a050SYann Gautier 	}
8057839a050SYann Gautier 
8067839a050SYann Gautier 	return fvco;
8077839a050SYann Gautier }
8087839a050SYann Gautier 
8090d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
8107839a050SYann Gautier 					    enum stm32mp1_div_id div_id)
8117839a050SYann Gautier {
8120d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
8137839a050SYann Gautier 	unsigned long dfout;
8147839a050SYann Gautier 	uint32_t cfgr2, divy;
8157839a050SYann Gautier 
8167839a050SYann Gautier 	if (div_id >= _DIV_NB) {
8177839a050SYann Gautier 		return 0;
8187839a050SYann Gautier 	}
8197839a050SYann Gautier 
8200d21680cSYann Gautier 	cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
8217839a050SYann Gautier 	divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
8227839a050SYann Gautier 
8230d21680cSYann Gautier 	dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
8247839a050SYann Gautier 
8257839a050SYann Gautier 	return dfout;
8267839a050SYann Gautier }
8277839a050SYann Gautier 
8280d21680cSYann Gautier static unsigned long get_clock_rate(int p)
8297839a050SYann Gautier {
8307839a050SYann Gautier 	uint32_t reg, clkdiv;
8317839a050SYann Gautier 	unsigned long clock = 0;
8320d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
8337839a050SYann Gautier 
8347839a050SYann Gautier 	switch (p) {
8357839a050SYann Gautier 	case _CK_MPU:
8367839a050SYann Gautier 	/* MPU sub system */
8370d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
8387839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8397839a050SYann Gautier 		case RCC_MPCKSELR_HSI:
8400d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8417839a050SYann Gautier 			break;
8427839a050SYann Gautier 		case RCC_MPCKSELR_HSE:
8430d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8447839a050SYann Gautier 			break;
8457839a050SYann Gautier 		case RCC_MPCKSELR_PLL:
8460d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8477839a050SYann Gautier 			break;
8487839a050SYann Gautier 		case RCC_MPCKSELR_PLL_MPUDIV:
8490d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8507839a050SYann Gautier 
8510d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
8527839a050SYann Gautier 			clkdiv = reg & RCC_MPUDIV_MASK;
853602ae2f2SGabriel Fernandez 			clock >>= stm32mp1_mpu_div[clkdiv];
8547839a050SYann Gautier 			break;
8557839a050SYann Gautier 		default:
8567839a050SYann Gautier 			break;
8577839a050SYann Gautier 		}
8587839a050SYann Gautier 		break;
8597839a050SYann Gautier 	/* AXI sub system */
8607839a050SYann Gautier 	case _ACLK:
8617839a050SYann Gautier 	case _HCLK2:
8627839a050SYann Gautier 	case _HCLK6:
8637839a050SYann Gautier 	case _PCLK4:
8647839a050SYann Gautier 	case _PCLK5:
8650d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
8667839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8677839a050SYann Gautier 		case RCC_ASSCKSELR_HSI:
8680d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8697839a050SYann Gautier 			break;
8707839a050SYann Gautier 		case RCC_ASSCKSELR_HSE:
8710d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8727839a050SYann Gautier 			break;
8737839a050SYann Gautier 		case RCC_ASSCKSELR_PLL:
8740d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
8757839a050SYann Gautier 			break;
8767839a050SYann Gautier 		default:
8777839a050SYann Gautier 			break;
8787839a050SYann Gautier 		}
8797839a050SYann Gautier 
8807839a050SYann Gautier 		/* System clock divider */
8810d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
8827839a050SYann Gautier 		clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
8837839a050SYann Gautier 
8847839a050SYann Gautier 		switch (p) {
8857839a050SYann Gautier 		case _PCLK4:
8860d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
8877839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
8887839a050SYann Gautier 			break;
8897839a050SYann Gautier 		case _PCLK5:
8900d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
8917839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
8927839a050SYann Gautier 			break;
8937839a050SYann Gautier 		default:
8947839a050SYann Gautier 			break;
8957839a050SYann Gautier 		}
8967839a050SYann Gautier 		break;
897b053a22eSYann Gautier 	/* MCU sub system */
898b053a22eSYann Gautier 	case _CK_MCU:
899b053a22eSYann Gautier 	case _PCLK1:
900b053a22eSYann Gautier 	case _PCLK2:
901b053a22eSYann Gautier 	case _PCLK3:
902b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
903b053a22eSYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
904b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSI:
905b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
906b053a22eSYann Gautier 			break;
907b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSE:
908b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
909b053a22eSYann Gautier 			break;
910b053a22eSYann Gautier 		case RCC_MSSCKSELR_CSI:
911b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
912b053a22eSYann Gautier 			break;
913b053a22eSYann Gautier 		case RCC_MSSCKSELR_PLL:
914b053a22eSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
915b053a22eSYann Gautier 			break;
916b053a22eSYann Gautier 		default:
917b053a22eSYann Gautier 			break;
918b053a22eSYann Gautier 		}
919b053a22eSYann Gautier 
920b053a22eSYann Gautier 		/* MCU clock divider */
921b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
922b053a22eSYann Gautier 		clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
923b053a22eSYann Gautier 
924b053a22eSYann Gautier 		switch (p) {
925b053a22eSYann Gautier 		case _PCLK1:
926b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
927b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
928b053a22eSYann Gautier 			break;
929b053a22eSYann Gautier 		case _PCLK2:
930b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
931b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
932b053a22eSYann Gautier 			break;
933b053a22eSYann Gautier 		case _PCLK3:
934b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
935b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
936b053a22eSYann Gautier 			break;
937b053a22eSYann Gautier 		case _CK_MCU:
938b053a22eSYann Gautier 		default:
939b053a22eSYann Gautier 			break;
940b053a22eSYann Gautier 		}
941b053a22eSYann Gautier 		break;
9427839a050SYann Gautier 	case _CK_PER:
9430d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
9447839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
9457839a050SYann Gautier 		case RCC_CPERCKSELR_HSI:
9460d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
9477839a050SYann Gautier 			break;
9487839a050SYann Gautier 		case RCC_CPERCKSELR_HSE:
9490d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
9507839a050SYann Gautier 			break;
9517839a050SYann Gautier 		case RCC_CPERCKSELR_CSI:
9520d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
9537839a050SYann Gautier 			break;
9547839a050SYann Gautier 		default:
9557839a050SYann Gautier 			break;
9567839a050SYann Gautier 		}
9577839a050SYann Gautier 		break;
9587839a050SYann Gautier 	case _HSI:
9597839a050SYann Gautier 	case _HSI_KER:
9600d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSI);
9617839a050SYann Gautier 		break;
9627839a050SYann Gautier 	case _CSI:
9637839a050SYann Gautier 	case _CSI_KER:
9640d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_CSI);
9657839a050SYann Gautier 		break;
9667839a050SYann Gautier 	case _HSE:
9677839a050SYann Gautier 	case _HSE_KER:
9680d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE);
9697839a050SYann Gautier 		break;
9707839a050SYann Gautier 	case _HSE_KER_DIV2:
9710d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
9727839a050SYann Gautier 		break;
973cbd2e8a6SGabriel Fernandez 	case _HSE_RTC:
974cbd2e8a6SGabriel Fernandez 		clock = stm32mp1_clk_get_fixed(_HSE);
975cbd2e8a6SGabriel Fernandez 		clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
976cbd2e8a6SGabriel Fernandez 		break;
9777839a050SYann Gautier 	case _LSI:
9780d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSI);
9797839a050SYann Gautier 		break;
9807839a050SYann Gautier 	case _LSE:
9810d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSE);
9827839a050SYann Gautier 		break;
9837839a050SYann Gautier 	/* PLL */
9847839a050SYann Gautier 	case _PLL1_P:
9850d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
9867839a050SYann Gautier 		break;
9877839a050SYann Gautier 	case _PLL1_Q:
9880d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
9897839a050SYann Gautier 		break;
9907839a050SYann Gautier 	case _PLL1_R:
9910d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
9927839a050SYann Gautier 		break;
9937839a050SYann Gautier 	case _PLL2_P:
9940d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
9957839a050SYann Gautier 		break;
9967839a050SYann Gautier 	case _PLL2_Q:
9970d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
9987839a050SYann Gautier 		break;
9997839a050SYann Gautier 	case _PLL2_R:
10000d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
10017839a050SYann Gautier 		break;
10027839a050SYann Gautier 	case _PLL3_P:
10030d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
10047839a050SYann Gautier 		break;
10057839a050SYann Gautier 	case _PLL3_Q:
10060d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
10077839a050SYann Gautier 		break;
10087839a050SYann Gautier 	case _PLL3_R:
10090d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
10107839a050SYann Gautier 		break;
10117839a050SYann Gautier 	case _PLL4_P:
10120d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
10137839a050SYann Gautier 		break;
10147839a050SYann Gautier 	case _PLL4_Q:
10150d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
10167839a050SYann Gautier 		break;
10177839a050SYann Gautier 	case _PLL4_R:
10180d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
10197839a050SYann Gautier 		break;
10207839a050SYann Gautier 	/* Other */
10217839a050SYann Gautier 	case _USB_PHY_48:
10220d21680cSYann Gautier 		clock = USB_PHY_48_MHZ;
10237839a050SYann Gautier 		break;
10247839a050SYann Gautier 	default:
10257839a050SYann Gautier 		break;
10267839a050SYann Gautier 	}
10277839a050SYann Gautier 
10287839a050SYann Gautier 	return clock;
10297839a050SYann Gautier }
10307839a050SYann Gautier 
10310d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate)
10320d21680cSYann Gautier {
10330d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10340d21680cSYann Gautier 
103525be845eSEtienne Carriere 	VERBOSE("Enable clock %u\n", gate->index);
103625be845eSEtienne Carriere 
10370d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10380d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
10390d21680cSYann Gautier 	} else {
10400d21680cSYann Gautier 		mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
10410d21680cSYann Gautier 	}
10420d21680cSYann Gautier }
10430d21680cSYann Gautier 
10440d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate)
10450d21680cSYann Gautier {
10460d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10470d21680cSYann Gautier 
104825be845eSEtienne Carriere 	VERBOSE("Disable clock %u\n", gate->index);
104925be845eSEtienne Carriere 
10500d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10510d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
10520d21680cSYann Gautier 			      BIT(gate->bit));
10530d21680cSYann Gautier 	} else {
10540d21680cSYann Gautier 		mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
10550d21680cSYann Gautier 	}
10560d21680cSYann Gautier }
10570d21680cSYann Gautier 
10580d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
10590d21680cSYann Gautier {
10600d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10610d21680cSYann Gautier 
10620d21680cSYann Gautier 	return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
10630d21680cSYann Gautier }
10640d21680cSYann Gautier 
10650d21680cSYann Gautier unsigned int stm32mp1_clk_get_refcount(unsigned long id)
10660d21680cSYann Gautier {
10670d21680cSYann Gautier 	int i = stm32mp1_clk_get_gated_id(id);
10680d21680cSYann Gautier 
10690d21680cSYann Gautier 	if (i < 0) {
10700d21680cSYann Gautier 		panic();
10710d21680cSYann Gautier 	}
10720d21680cSYann Gautier 
10730d21680cSYann Gautier 	return gate_refcounts[i];
10740d21680cSYann Gautier }
10750d21680cSYann Gautier 
107635848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */
107735848200SEtienne Carriere static bool clock_is_always_on(unsigned long id)
107835848200SEtienne Carriere {
107935848200SEtienne Carriere 	switch (id) {
108035848200SEtienne Carriere 	case CK_HSE:
108135848200SEtienne Carriere 	case CK_CSI:
108235848200SEtienne Carriere 	case CK_LSI:
108335848200SEtienne Carriere 	case CK_LSE:
108435848200SEtienne Carriere 	case CK_HSI:
108535848200SEtienne Carriere 	case CK_HSE_DIV2:
108635848200SEtienne Carriere 	case PLL1_Q:
108735848200SEtienne Carriere 	case PLL1_R:
108835848200SEtienne Carriere 	case PLL2_P:
108935848200SEtienne Carriere 	case PLL2_Q:
109035848200SEtienne Carriere 	case PLL2_R:
109135848200SEtienne Carriere 	case PLL3_P:
109235848200SEtienne Carriere 	case PLL3_Q:
109335848200SEtienne Carriere 	case PLL3_R:
1094bf39318dSYann Gautier 	case CK_AXI:
1095bf39318dSYann Gautier 	case CK_MPU:
1096bf39318dSYann Gautier 	case CK_MCU:
10975b111c74SHE Shushan 	case RTC:
109835848200SEtienne Carriere 		return true;
109935848200SEtienne Carriere 	default:
110035848200SEtienne Carriere 		return false;
110135848200SEtienne Carriere 	}
110235848200SEtienne Carriere }
110335848200SEtienne Carriere 
11040d21680cSYann Gautier void __stm32mp1_clk_enable(unsigned long id, bool secure)
11050d21680cSYann Gautier {
11060d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
110735848200SEtienne Carriere 	int i;
11080d21680cSYann Gautier 	unsigned int *refcnt;
11090d21680cSYann Gautier 
111035848200SEtienne Carriere 	if (clock_is_always_on(id)) {
111135848200SEtienne Carriere 		return;
111235848200SEtienne Carriere 	}
111335848200SEtienne Carriere 
111435848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11150d21680cSYann Gautier 	if (i < 0) {
11160d21680cSYann Gautier 		ERROR("Clock %d can't be enabled\n", (uint32_t)id);
11170d21680cSYann Gautier 		panic();
11180d21680cSYann Gautier 	}
11190d21680cSYann Gautier 
11200d21680cSYann Gautier 	gate = gate_ref(i);
11210d21680cSYann Gautier 	refcnt = &gate_refcounts[i];
11220d21680cSYann Gautier 
11230d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11240d21680cSYann Gautier 
11250d21680cSYann Gautier 	if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) {
11260d21680cSYann Gautier 		__clk_enable(gate);
11270d21680cSYann Gautier 	}
11280d21680cSYann Gautier 
11290d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
11300d21680cSYann Gautier }
11310d21680cSYann Gautier 
11320d21680cSYann Gautier void __stm32mp1_clk_disable(unsigned long id, bool secure)
11330d21680cSYann Gautier {
11340d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
113535848200SEtienne Carriere 	int i;
11360d21680cSYann Gautier 	unsigned int *refcnt;
11370d21680cSYann Gautier 
113835848200SEtienne Carriere 	if (clock_is_always_on(id)) {
113935848200SEtienne Carriere 		return;
114035848200SEtienne Carriere 	}
114135848200SEtienne Carriere 
114235848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11430d21680cSYann Gautier 	if (i < 0) {
11440d21680cSYann Gautier 		ERROR("Clock %d can't be disabled\n", (uint32_t)id);
11450d21680cSYann Gautier 		panic();
11460d21680cSYann Gautier 	}
11470d21680cSYann Gautier 
11480d21680cSYann Gautier 	gate = gate_ref(i);
11490d21680cSYann Gautier 	refcnt = &gate_refcounts[i];
11500d21680cSYann Gautier 
11510d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11520d21680cSYann Gautier 
11530d21680cSYann Gautier 	if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) {
11540d21680cSYann Gautier 		__clk_disable(gate);
11550d21680cSYann Gautier 	}
11560d21680cSYann Gautier 
11570d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
11580d21680cSYann Gautier }
11590d21680cSYann Gautier 
116033667d29SYann Gautier static int stm32mp_clk_enable(unsigned long id)
11610d21680cSYann Gautier {
11620d21680cSYann Gautier 	__stm32mp1_clk_enable(id, true);
116333667d29SYann Gautier 
116433667d29SYann Gautier 	return 0;
11650d21680cSYann Gautier }
11660d21680cSYann Gautier 
116733667d29SYann Gautier static void stm32mp_clk_disable(unsigned long id)
11680d21680cSYann Gautier {
11690d21680cSYann Gautier 	__stm32mp1_clk_disable(id, true);
11700d21680cSYann Gautier }
11710d21680cSYann Gautier 
117233667d29SYann Gautier static bool stm32mp_clk_is_enabled(unsigned long id)
11737839a050SYann Gautier {
117435848200SEtienne Carriere 	int i;
11757839a050SYann Gautier 
117635848200SEtienne Carriere 	if (clock_is_always_on(id)) {
117735848200SEtienne Carriere 		return true;
117835848200SEtienne Carriere 	}
117935848200SEtienne Carriere 
118035848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11817839a050SYann Gautier 	if (i < 0) {
11820d21680cSYann Gautier 		panic();
11837839a050SYann Gautier 	}
11847839a050SYann Gautier 
11850d21680cSYann Gautier 	return __clk_is_enabled(gate_ref(i));
11867839a050SYann Gautier }
11877839a050SYann Gautier 
118833667d29SYann Gautier static unsigned long stm32mp_clk_get_rate(unsigned long id)
11897839a050SYann Gautier {
119033667d29SYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
11910d21680cSYann Gautier 	int p = stm32mp1_clk_get_parent(id);
119233667d29SYann Gautier 	uint32_t prescaler, timpre;
119333667d29SYann Gautier 	unsigned long parent_rate;
11947839a050SYann Gautier 
11957839a050SYann Gautier 	if (p < 0) {
11967839a050SYann Gautier 		return 0;
11977839a050SYann Gautier 	}
11987839a050SYann Gautier 
119933667d29SYann Gautier 	parent_rate = get_clock_rate(p);
120033667d29SYann Gautier 
120133667d29SYann Gautier 	switch (id) {
120233667d29SYann Gautier 	case TIM2_K:
120333667d29SYann Gautier 	case TIM3_K:
120433667d29SYann Gautier 	case TIM4_K:
120533667d29SYann Gautier 	case TIM5_K:
120633667d29SYann Gautier 	case TIM6_K:
120733667d29SYann Gautier 	case TIM7_K:
120833667d29SYann Gautier 	case TIM12_K:
120933667d29SYann Gautier 	case TIM13_K:
121033667d29SYann Gautier 	case TIM14_K:
121133667d29SYann Gautier 		prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) &
121233667d29SYann Gautier 			    RCC_APBXDIV_MASK;
121333667d29SYann Gautier 		timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) &
121433667d29SYann Gautier 			 RCC_TIMGXPRER_TIMGXPRE;
121533667d29SYann Gautier 		break;
121633667d29SYann Gautier 
121733667d29SYann Gautier 	case TIM1_K:
121833667d29SYann Gautier 	case TIM8_K:
121933667d29SYann Gautier 	case TIM15_K:
122033667d29SYann Gautier 	case TIM16_K:
122133667d29SYann Gautier 	case TIM17_K:
122233667d29SYann Gautier 		prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) &
122333667d29SYann Gautier 			    RCC_APBXDIV_MASK;
122433667d29SYann Gautier 		timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) &
122533667d29SYann Gautier 			 RCC_TIMGXPRER_TIMGXPRE;
122633667d29SYann Gautier 		break;
122733667d29SYann Gautier 
122833667d29SYann Gautier 	default:
122933667d29SYann Gautier 		return parent_rate;
123033667d29SYann Gautier 	}
123133667d29SYann Gautier 
123233667d29SYann Gautier 	if (prescaler == 0U) {
123333667d29SYann Gautier 		return parent_rate;
123433667d29SYann Gautier 	}
123533667d29SYann Gautier 
123633667d29SYann Gautier 	return parent_rate * (timpre + 1U) * 2U;
12377839a050SYann Gautier }
12387839a050SYann Gautier 
12390d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
12407839a050SYann Gautier {
12410d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12427839a050SYann Gautier 
12430d21680cSYann Gautier 	if (enable) {
12447839a050SYann Gautier 		mmio_setbits_32(address, mask_on);
12457839a050SYann Gautier 	} else {
12467839a050SYann Gautier 		mmio_clrbits_32(address, mask_on);
12477839a050SYann Gautier 	}
12487839a050SYann Gautier }
12497839a050SYann Gautier 
12500d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
12517839a050SYann Gautier {
12520d21680cSYann Gautier 	uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
12530d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12540d21680cSYann Gautier 
12550d21680cSYann Gautier 	mmio_write_32(address, mask_on);
12567839a050SYann Gautier }
12577839a050SYann Gautier 
12580d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
12597839a050SYann Gautier {
1260dfdb057aSYann Gautier 	uint64_t timeout;
12617839a050SYann Gautier 	uint32_t mask_test;
12620d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12637839a050SYann Gautier 
12640d21680cSYann Gautier 	if (enable) {
12657839a050SYann Gautier 		mask_test = mask_rdy;
12667839a050SYann Gautier 	} else {
12677839a050SYann Gautier 		mask_test = 0;
12687839a050SYann Gautier 	}
12697839a050SYann Gautier 
1270dfdb057aSYann Gautier 	timeout = timeout_init_us(OSCRDY_TIMEOUT);
12717839a050SYann Gautier 	while ((mmio_read_32(address) & mask_rdy) != mask_test) {
1272dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
12730d21680cSYann Gautier 			ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
12747839a050SYann Gautier 			      mask_rdy, address, enable, mmio_read_32(address));
12757839a050SYann Gautier 			return -ETIMEDOUT;
12767839a050SYann Gautier 		}
12777839a050SYann Gautier 	}
12787839a050SYann Gautier 
12797839a050SYann Gautier 	return 0;
12807839a050SYann Gautier }
12817839a050SYann Gautier 
12820d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
12837839a050SYann Gautier {
12847839a050SYann Gautier 	uint32_t value;
12850d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
12867839a050SYann Gautier 
12870d21680cSYann Gautier 	if (digbyp) {
12880d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
12890d21680cSYann Gautier 	}
12900d21680cSYann Gautier 
12910d21680cSYann Gautier 	if (bypass || digbyp) {
12920d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
12937839a050SYann Gautier 	}
12947839a050SYann Gautier 
12957839a050SYann Gautier 	/*
12967839a050SYann Gautier 	 * Warning: not recommended to switch directly from "high drive"
12977839a050SYann Gautier 	 * to "medium low drive", and vice-versa.
12987839a050SYann Gautier 	 */
12990d21680cSYann Gautier 	value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
13007839a050SYann Gautier 		RCC_BDCR_LSEDRV_SHIFT;
13017839a050SYann Gautier 
13027839a050SYann Gautier 	while (value != lsedrv) {
13037839a050SYann Gautier 		if (value > lsedrv) {
13047839a050SYann Gautier 			value--;
13057839a050SYann Gautier 		} else {
13067839a050SYann Gautier 			value++;
13077839a050SYann Gautier 		}
13087839a050SYann Gautier 
13090d21680cSYann Gautier 		mmio_clrsetbits_32(rcc_base + RCC_BDCR,
13107839a050SYann Gautier 				   RCC_BDCR_LSEDRV_MASK,
13117839a050SYann Gautier 				   value << RCC_BDCR_LSEDRV_SHIFT);
13127839a050SYann Gautier 	}
13137839a050SYann Gautier 
13140d21680cSYann Gautier 	stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
13157839a050SYann Gautier }
13167839a050SYann Gautier 
13170d21680cSYann Gautier static void stm32mp1_lse_wait(void)
13187839a050SYann Gautier {
13190d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
13207839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13217839a050SYann Gautier 	}
13227839a050SYann Gautier }
13237839a050SYann Gautier 
13240d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable)
13257839a050SYann Gautier {
13260d21680cSYann Gautier 	stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
13270d21680cSYann Gautier 
13280d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
13297839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13307839a050SYann Gautier 	}
13317839a050SYann Gautier }
13327839a050SYann Gautier 
13330d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
13347839a050SYann Gautier {
13350d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13360d21680cSYann Gautier 
13370d21680cSYann Gautier 	if (digbyp) {
13380d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
13397839a050SYann Gautier 	}
13407839a050SYann Gautier 
13410d21680cSYann Gautier 	if (bypass || digbyp) {
13420d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
13430d21680cSYann Gautier 	}
13440d21680cSYann Gautier 
13450d21680cSYann Gautier 	stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
13460d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
13477839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13487839a050SYann Gautier 	}
13497839a050SYann Gautier 
13507839a050SYann Gautier 	if (css) {
13510d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
13527839a050SYann Gautier 	}
135331e9750bSLionel Debieve 
135431e9750bSLionel Debieve #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
135531e9750bSLionel Debieve 	if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) &&
135631e9750bSLionel Debieve 	    (!(digbyp || bypass))) {
135731e9750bSLionel Debieve 		panic();
135831e9750bSLionel Debieve 	}
135931e9750bSLionel Debieve #endif
13607839a050SYann Gautier }
13617839a050SYann Gautier 
13620d21680cSYann Gautier static void stm32mp1_csi_set(bool enable)
13637839a050SYann Gautier {
13640d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
13650d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
13667839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13677839a050SYann Gautier 	}
13687839a050SYann Gautier }
13697839a050SYann Gautier 
13700d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable)
13717839a050SYann Gautier {
13720d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
13730d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
13747839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13757839a050SYann Gautier 	}
13767839a050SYann Gautier }
13777839a050SYann Gautier 
13780d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv)
13797839a050SYann Gautier {
1380dfdb057aSYann Gautier 	uint64_t timeout;
13810d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13820d21680cSYann Gautier 	uintptr_t address = rcc_base + RCC_OCRDYR;
13837839a050SYann Gautier 
13840d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
13857839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK,
13867839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
13877839a050SYann Gautier 
1388dfdb057aSYann Gautier 	timeout = timeout_init_us(HSIDIV_TIMEOUT);
13897839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
1390dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
13910d21680cSYann Gautier 			ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
13927839a050SYann Gautier 			      address, mmio_read_32(address));
13937839a050SYann Gautier 			return -ETIMEDOUT;
13947839a050SYann Gautier 		}
13957839a050SYann Gautier 	}
13967839a050SYann Gautier 
13977839a050SYann Gautier 	return 0;
13987839a050SYann Gautier }
13997839a050SYann Gautier 
14000d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq)
14017839a050SYann Gautier {
14027839a050SYann Gautier 	uint8_t hsidiv;
14037839a050SYann Gautier 	uint32_t hsidivfreq = MAX_HSI_HZ;
14047839a050SYann Gautier 
14057839a050SYann Gautier 	for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
14067839a050SYann Gautier 		if (hsidivfreq == hsifreq) {
14077839a050SYann Gautier 			break;
14087839a050SYann Gautier 		}
14097839a050SYann Gautier 
14107839a050SYann Gautier 		hsidivfreq /= 2U;
14117839a050SYann Gautier 	}
14127839a050SYann Gautier 
14137839a050SYann Gautier 	if (hsidiv == 4U) {
14147839a050SYann Gautier 		ERROR("Invalid clk-hsi frequency\n");
14157839a050SYann Gautier 		return -1;
14167839a050SYann Gautier 	}
14177839a050SYann Gautier 
14187839a050SYann Gautier 	if (hsidiv != 0U) {
14190d21680cSYann Gautier 		return stm32mp1_set_hsidiv(hsidiv);
14207839a050SYann Gautier 	}
14217839a050SYann Gautier 
14227839a050SYann Gautier 	return 0;
14237839a050SYann Gautier }
14247839a050SYann Gautier 
14250d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
14260d21680cSYann Gautier 				    unsigned int clksrc,
14270d21680cSYann Gautier 				    uint32_t *pllcfg, int plloff)
14287839a050SYann Gautier {
14290d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
14300d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
14310d21680cSYann Gautier 	uintptr_t pllxcr = rcc_base + pll->pllxcr;
14320d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
14330d21680cSYann Gautier 	uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
14340d21680cSYann Gautier 	unsigned long refclk;
14350d21680cSYann Gautier 	uint32_t ifrge = 0U;
1436be858cffSAndre Przywara 	uint32_t src, value, fracv = 0;
1437be858cffSAndre Przywara 	void *fdt;
14387839a050SYann Gautier 
14390d21680cSYann Gautier 	/* Check PLL output */
14400d21680cSYann Gautier 	if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
14410d21680cSYann Gautier 		return false;
14427839a050SYann Gautier 	}
14437839a050SYann Gautier 
14440d21680cSYann Gautier 	/* Check current clksrc */
14450d21680cSYann Gautier 	src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
14460d21680cSYann Gautier 	if (src != (clksrc & RCC_SELR_SRC_MASK)) {
14470d21680cSYann Gautier 		return false;
14480d21680cSYann Gautier 	}
14490d21680cSYann Gautier 
14500d21680cSYann Gautier 	/* Check Div */
14510d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
14520d21680cSYann Gautier 
14530d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
14540d21680cSYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
14550d21680cSYann Gautier 
14560d21680cSYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
14570d21680cSYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
14580d21680cSYann Gautier 		return false;
14590d21680cSYann Gautier 	}
14600d21680cSYann Gautier 
14610d21680cSYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
14620d21680cSYann Gautier 		ifrge = 1U;
14630d21680cSYann Gautier 	}
14640d21680cSYann Gautier 
14650d21680cSYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
14660d21680cSYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
14670d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
14680d21680cSYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
14690d21680cSYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
14700d21680cSYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
14710d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
14720d21680cSYann Gautier 		return false;
14730d21680cSYann Gautier 	}
14740d21680cSYann Gautier 
14750d21680cSYann Gautier 	/* Fractional configuration */
1476be858cffSAndre Przywara 	if (fdt_get_address(&fdt) == 1) {
1477be858cffSAndre Przywara 		fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1478be858cffSAndre Przywara 	}
14790d21680cSYann Gautier 
14800d21680cSYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
14810d21680cSYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
14820d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
14830d21680cSYann Gautier 		return false;
14840d21680cSYann Gautier 	}
14850d21680cSYann Gautier 
14860d21680cSYann Gautier 	/* Output config */
14870d21680cSYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
14880d21680cSYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
14890d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
14900d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
14910d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
14920d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
14930d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
14940d21680cSYann Gautier 		return false;
14950d21680cSYann Gautier 	}
14960d21680cSYann Gautier 
14970d21680cSYann Gautier 	return true;
14980d21680cSYann Gautier }
14990d21680cSYann Gautier 
15000d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
15017839a050SYann Gautier {
15020d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15030d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
15040d21680cSYann Gautier 
1505dd98aec8SYann Gautier 	/* Preserve RCC_PLLNCR_SSCG_CTRL value */
1506dd98aec8SYann Gautier 	mmio_clrsetbits_32(pllxcr,
1507dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1508dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVREN,
1509dd98aec8SYann Gautier 			   RCC_PLLNCR_PLLON);
15100d21680cSYann Gautier }
15110d21680cSYann Gautier 
15120d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
15130d21680cSYann Gautier {
15140d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15150d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1516dfdb057aSYann Gautier 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
15177839a050SYann Gautier 
15187839a050SYann Gautier 	/* Wait PLL lock */
15197839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
1520dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
15210d21680cSYann Gautier 			ERROR("PLL%d start failed @ 0x%lx: 0x%x\n",
15227839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
15237839a050SYann Gautier 			return -ETIMEDOUT;
15247839a050SYann Gautier 		}
15257839a050SYann Gautier 	}
15267839a050SYann Gautier 
15277839a050SYann Gautier 	/* Start the requested output */
15287839a050SYann Gautier 	mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
15297839a050SYann Gautier 
15307839a050SYann Gautier 	return 0;
15317839a050SYann Gautier }
15327839a050SYann Gautier 
15330d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
15347839a050SYann Gautier {
15350d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15360d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1537dfdb057aSYann Gautier 	uint64_t timeout;
15387839a050SYann Gautier 
15397839a050SYann Gautier 	/* Stop all output */
15407839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
15417839a050SYann Gautier 			RCC_PLLNCR_DIVREN);
15427839a050SYann Gautier 
15437839a050SYann Gautier 	/* Stop PLL */
15447839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
15457839a050SYann Gautier 
1546dfdb057aSYann Gautier 	timeout = timeout_init_us(PLLRDY_TIMEOUT);
15477839a050SYann Gautier 	/* Wait PLL stopped */
15487839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
1549dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
15500d21680cSYann Gautier 			ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
15517839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
15527839a050SYann Gautier 			return -ETIMEDOUT;
15537839a050SYann Gautier 		}
15547839a050SYann Gautier 	}
15557839a050SYann Gautier 
15567839a050SYann Gautier 	return 0;
15577839a050SYann Gautier }
15587839a050SYann Gautier 
15590d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
15607839a050SYann Gautier 				       uint32_t *pllcfg)
15617839a050SYann Gautier {
15620d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15630d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
15647839a050SYann Gautier 	uint32_t value;
15657839a050SYann Gautier 
15667839a050SYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
15677839a050SYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
15687839a050SYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
15697839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
15707839a050SYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
15717839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
15720d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr2, value);
15737839a050SYann Gautier }
15747839a050SYann Gautier 
15750d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
15767839a050SYann Gautier 			       uint32_t *pllcfg, uint32_t fracv)
15777839a050SYann Gautier {
15780d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15790d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
15800d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
15817839a050SYann Gautier 	unsigned long refclk;
15827839a050SYann Gautier 	uint32_t ifrge = 0;
15837839a050SYann Gautier 	uint32_t src, value;
15847839a050SYann Gautier 
15850d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) &
15867839a050SYann Gautier 		RCC_SELR_REFCLK_SRC_MASK;
15877839a050SYann Gautier 
15880d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
15897839a050SYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
15907839a050SYann Gautier 
15917839a050SYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
15927839a050SYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
15937839a050SYann Gautier 		return -EINVAL;
15947839a050SYann Gautier 	}
15957839a050SYann Gautier 
15967839a050SYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
15977839a050SYann Gautier 		ifrge = 1U;
15987839a050SYann Gautier 	}
15997839a050SYann Gautier 
16007839a050SYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
16017839a050SYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
16027839a050SYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
16037839a050SYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
16047839a050SYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
16057839a050SYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
16060d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr1, value);
16077839a050SYann Gautier 
16087839a050SYann Gautier 	/* Fractional configuration */
16097839a050SYann Gautier 	value = 0;
16100d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16117839a050SYann Gautier 
16127839a050SYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
16130d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16147839a050SYann Gautier 
16157839a050SYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
16160d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16177839a050SYann Gautier 
16180d21680cSYann Gautier 	stm32mp1_pll_config_output(pll_id, pllcfg);
16197839a050SYann Gautier 
16207839a050SYann Gautier 	return 0;
16217839a050SYann Gautier }
16227839a050SYann Gautier 
16230d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
16247839a050SYann Gautier {
16250d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16267839a050SYann Gautier 	uint32_t pllxcsg = 0;
16277839a050SYann Gautier 
16287839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
16297839a050SYann Gautier 		    RCC_PLLNCSGR_MOD_PER_MASK;
16307839a050SYann Gautier 
16317839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
16327839a050SYann Gautier 		    RCC_PLLNCSGR_INC_STEP_MASK;
16337839a050SYann Gautier 
16347839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
16357839a050SYann Gautier 		    RCC_PLLNCSGR_SSCG_MODE_MASK;
16367839a050SYann Gautier 
16370d21680cSYann Gautier 	mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
1638dd98aec8SYann Gautier 
1639dd98aec8SYann Gautier 	mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
1640dd98aec8SYann Gautier 			RCC_PLLNCR_SSCG_CTRL);
16417839a050SYann Gautier }
16427839a050SYann Gautier 
16430d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc)
16447839a050SYann Gautier {
16450d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
1646dfdb057aSYann Gautier 	uint64_t timeout;
16477839a050SYann Gautier 
16480d21680cSYann Gautier 	mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
16497839a050SYann Gautier 			   clksrc & RCC_SELR_SRC_MASK);
16507839a050SYann Gautier 
1651dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
16520d21680cSYann Gautier 	while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
1653dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
16540d21680cSYann Gautier 			ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
16550d21680cSYann Gautier 			      clksrc_address, mmio_read_32(clksrc_address));
16567839a050SYann Gautier 			return -ETIMEDOUT;
16577839a050SYann Gautier 		}
16587839a050SYann Gautier 	}
16597839a050SYann Gautier 
16607839a050SYann Gautier 	return 0;
16617839a050SYann Gautier }
16627839a050SYann Gautier 
16630d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
16647839a050SYann Gautier {
1665dfdb057aSYann Gautier 	uint64_t timeout;
16667839a050SYann Gautier 
16677839a050SYann Gautier 	mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
16687839a050SYann Gautier 			   clkdiv & RCC_DIVR_DIV_MASK);
16697839a050SYann Gautier 
1670dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
16717839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
1672dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
16730d21680cSYann Gautier 			ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
16747839a050SYann Gautier 			      clkdiv, address, mmio_read_32(address));
16757839a050SYann Gautier 			return -ETIMEDOUT;
16767839a050SYann Gautier 		}
16777839a050SYann Gautier 	}
16787839a050SYann Gautier 
16797839a050SYann Gautier 	return 0;
16807839a050SYann Gautier }
16817839a050SYann Gautier 
16820d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
16837839a050SYann Gautier {
16840d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
16857839a050SYann Gautier 
16867839a050SYann Gautier 	/*
16877839a050SYann Gautier 	 * Binding clksrc :
16887839a050SYann Gautier 	 *      bit15-4 offset
16897839a050SYann Gautier 	 *      bit3:   disable
16907839a050SYann Gautier 	 *      bit2-0: MCOSEL[2:0]
16917839a050SYann Gautier 	 */
16927839a050SYann Gautier 	if ((clksrc & 0x8U) != 0U) {
16930d21680cSYann Gautier 		mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
16947839a050SYann Gautier 	} else {
16950d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
16967839a050SYann Gautier 				   RCC_MCOCFG_MCOSRC_MASK,
16977839a050SYann Gautier 				   clksrc & RCC_MCOCFG_MCOSRC_MASK);
16980d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
16997839a050SYann Gautier 				   RCC_MCOCFG_MCODIV_MASK,
17007839a050SYann Gautier 				   clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
17010d21680cSYann Gautier 		mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
17027839a050SYann Gautier 	}
17037839a050SYann Gautier }
17047839a050SYann Gautier 
17050d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
17067839a050SYann Gautier {
17070d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
17087839a050SYann Gautier 
17097839a050SYann Gautier 	if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
17107839a050SYann Gautier 	    (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
17117839a050SYann Gautier 		mmio_clrsetbits_32(address,
17127839a050SYann Gautier 				   RCC_BDCR_RTCSRC_MASK,
171315509093SYann Gautier 				   (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
17147839a050SYann Gautier 
17157839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
17167839a050SYann Gautier 	}
17177839a050SYann Gautier 
17187839a050SYann Gautier 	if (lse_css) {
17197839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_LSECSSON);
17207839a050SYann Gautier 	}
17217839a050SYann Gautier }
17227839a050SYann Gautier 
17230d21680cSYann Gautier static void stm32mp1_stgen_config(void)
17247839a050SYann Gautier {
17257839a050SYann Gautier 	uint32_t cntfid0;
17267839a050SYann Gautier 	unsigned long rate;
17277839a050SYann Gautier 	unsigned long long counter;
17287839a050SYann Gautier 
1729ade9ce03SYann Gautier 	cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF);
17300d21680cSYann Gautier 	rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K));
17310d21680cSYann Gautier 
17320d21680cSYann Gautier 	if (cntfid0 == rate) {
17330d21680cSYann Gautier 		return;
17340d21680cSYann Gautier 	}
17350d21680cSYann Gautier 
1736ade9ce03SYann Gautier 	mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
1737ade9ce03SYann Gautier 	counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF);
1738ade9ce03SYann Gautier 	counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32;
17397839a050SYann Gautier 	counter = (counter * rate / cntfid0);
17400d21680cSYann Gautier 
1741ade9ce03SYann Gautier 	mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter);
1742ade9ce03SYann Gautier 	mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32));
1743ade9ce03SYann Gautier 	mmio_write_32(STGEN_BASE + CNTFID_OFF, rate);
1744ade9ce03SYann Gautier 	mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
17457839a050SYann Gautier 
17467839a050SYann Gautier 	write_cntfrq((u_register_t)rate);
17477839a050SYann Gautier 
17487839a050SYann Gautier 	/* Need to update timer with new frequency */
17497839a050SYann Gautier 	generic_delay_timer_init();
17507839a050SYann Gautier }
17517839a050SYann Gautier 
17527839a050SYann Gautier void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
17537839a050SYann Gautier {
17547839a050SYann Gautier 	unsigned long long cnt;
17557839a050SYann Gautier 
1756ade9ce03SYann Gautier 	cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) |
1757ade9ce03SYann Gautier 		mmio_read_32(STGEN_BASE + CNTCVL_OFF);
17587839a050SYann Gautier 
1759ade9ce03SYann Gautier 	cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U;
17607839a050SYann Gautier 
1761ade9ce03SYann Gautier 	mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
1762ade9ce03SYann Gautier 	mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt);
1763ade9ce03SYann Gautier 	mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32));
1764ade9ce03SYann Gautier 	mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN);
17657839a050SYann Gautier }
17667839a050SYann Gautier 
17670d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs)
17687839a050SYann Gautier {
17690d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
17707839a050SYann Gautier 	uint32_t value = pkcs & 0xFU;
17717839a050SYann Gautier 	uint32_t mask = 0xFU;
17727839a050SYann Gautier 
17737839a050SYann Gautier 	if ((pkcs & BIT(31)) != 0U) {
17747839a050SYann Gautier 		mask <<= 4;
17757839a050SYann Gautier 		value <<= 4;
17767839a050SYann Gautier 	}
17777839a050SYann Gautier 
17787839a050SYann Gautier 	mmio_clrsetbits_32(address, mask, value);
17797839a050SYann Gautier }
17807839a050SYann Gautier 
1781964e5ff1SNicolas Le Bayon static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg,
1782964e5ff1SNicolas Le Bayon 					uint32_t *fracv, uint32_t *csg,
1783964e5ff1SNicolas Le Bayon 					bool *csg_set)
1784964e5ff1SNicolas Le Bayon {
1785964e5ff1SNicolas Le Bayon 	void *fdt;
1786964e5ff1SNicolas Le Bayon 	int ret;
1787964e5ff1SNicolas Le Bayon 
1788964e5ff1SNicolas Le Bayon 	if (fdt_get_address(&fdt) == 0) {
1789964e5ff1SNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
1790964e5ff1SNicolas Le Bayon 	}
1791964e5ff1SNicolas Le Bayon 
1792964e5ff1SNicolas Le Bayon 	ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB,
1793964e5ff1SNicolas Le Bayon 				    pllcfg);
1794964e5ff1SNicolas Le Bayon 	if (ret < 0) {
1795964e5ff1SNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
1796964e5ff1SNicolas Le Bayon 	}
1797964e5ff1SNicolas Le Bayon 
1798964e5ff1SNicolas Le Bayon 	*fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1799964e5ff1SNicolas Le Bayon 
1800964e5ff1SNicolas Le Bayon 	ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB,
1801964e5ff1SNicolas Le Bayon 				    csg);
1802964e5ff1SNicolas Le Bayon 
1803964e5ff1SNicolas Le Bayon 	*csg_set = (ret == 0);
1804964e5ff1SNicolas Le Bayon 
1805964e5ff1SNicolas Le Bayon 	if (ret == -FDT_ERR_NOTFOUND) {
1806964e5ff1SNicolas Le Bayon 		ret = 0;
1807964e5ff1SNicolas Le Bayon 	}
1808964e5ff1SNicolas Le Bayon 
1809964e5ff1SNicolas Le Bayon 	return ret;
1810964e5ff1SNicolas Le Bayon }
1811964e5ff1SNicolas Le Bayon 
18127839a050SYann Gautier int stm32mp1_clk_init(void)
18137839a050SYann Gautier {
18140d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
1815964e5ff1SNicolas Le Bayon 	uint32_t pllfracv[_PLL_NB];
1816964e5ff1SNicolas Le Bayon 	uint32_t pllcsg[_PLL_NB][PLLCSG_NB];
18177839a050SYann Gautier 	unsigned int clksrc[CLKSRC_NB];
18187839a050SYann Gautier 	unsigned int clkdiv[CLKDIV_NB];
18197839a050SYann Gautier 	unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
18207839a050SYann Gautier 	int plloff[_PLL_NB];
18217839a050SYann Gautier 	int ret, len;
18227839a050SYann Gautier 	enum stm32mp1_pll_id i;
1823964e5ff1SNicolas Le Bayon 	bool pllcsg_set[_PLL_NB];
1824964e5ff1SNicolas Le Bayon 	bool pllcfg_valid[_PLL_NB];
18257839a050SYann Gautier 	bool lse_css = false;
18260d21680cSYann Gautier 	bool pll3_preserve = false;
18270d21680cSYann Gautier 	bool pll4_preserve = false;
18280d21680cSYann Gautier 	bool pll4_bootrom = false;
18293e6fab43SYann Gautier 	const fdt32_t *pkcs_cell;
183052a616b4SAndre Przywara 	void *fdt;
1831bf1af154SPatrick Delaunay 	int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
1832bf1af154SPatrick Delaunay 	int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
183352a616b4SAndre Przywara 
183452a616b4SAndre Przywara 	if (fdt_get_address(&fdt) == 0) {
18358f97c4faSYann Gautier 		return -FDT_ERR_NOTFOUND;
183652a616b4SAndre Przywara 	}
18377839a050SYann Gautier 
18387839a050SYann Gautier 	/* Check status field to disable security */
18397839a050SYann Gautier 	if (!fdt_get_rcc_secure_status()) {
18400d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_TZCR, 0);
18417839a050SYann Gautier 	}
18427839a050SYann Gautier 
184352a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
184452a616b4SAndre Przywara 					clksrc);
18457839a050SYann Gautier 	if (ret < 0) {
18467839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
18477839a050SYann Gautier 	}
18487839a050SYann Gautier 
184952a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
185052a616b4SAndre Przywara 					clkdiv);
18517839a050SYann Gautier 	if (ret < 0) {
18527839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
18537839a050SYann Gautier 	}
18547839a050SYann Gautier 
18557839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
18567839a050SYann Gautier 		char name[12];
18577839a050SYann Gautier 
185839b6cc66SAntonio Nino Diaz 		snprintf(name, sizeof(name), "st,pll@%d", i);
18597839a050SYann Gautier 		plloff[i] = fdt_rcc_subnode_offset(name);
18607839a050SYann Gautier 
1861964e5ff1SNicolas Le Bayon 		pllcfg_valid[i] = fdt_check_node(plloff[i]);
1862964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
18637839a050SYann Gautier 			continue;
18647839a050SYann Gautier 		}
18657839a050SYann Gautier 
1866964e5ff1SNicolas Le Bayon 		ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i],
1867964e5ff1SNicolas Le Bayon 						   &pllfracv[i], pllcsg[i],
1868964e5ff1SNicolas Le Bayon 						   &pllcsg_set[i]);
1869964e5ff1SNicolas Le Bayon 		if (ret != 0) {
1870964e5ff1SNicolas Le Bayon 			return ret;
18717839a050SYann Gautier 		}
18727839a050SYann Gautier 	}
18737839a050SYann Gautier 
18740d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
18750d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
18767839a050SYann Gautier 
18777839a050SYann Gautier 	/*
18787839a050SYann Gautier 	 * Switch ON oscillator found in device-tree.
18797839a050SYann Gautier 	 * Note: HSI already ON after BootROM stage.
18807839a050SYann Gautier 	 */
18810d21680cSYann Gautier 	if (stm32mp1_osc[_LSI] != 0U) {
18820d21680cSYann Gautier 		stm32mp1_lsi_set(true);
18837839a050SYann Gautier 	}
18840d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
1885*b208e3daSGabriel Fernandez 		const char *name = stm32mp_osc_node_label[_LSE];
18860d21680cSYann Gautier 		bool bypass, digbyp;
18877839a050SYann Gautier 		uint32_t lsedrv;
18887839a050SYann Gautier 
1889*b208e3daSGabriel Fernandez 		bypass = fdt_clk_read_bool(name, "st,bypass");
1890*b208e3daSGabriel Fernandez 		digbyp = fdt_clk_read_bool(name, "st,digbypass");
1891*b208e3daSGabriel Fernandez 		lse_css = fdt_clk_read_bool(name, "st,css");
1892*b208e3daSGabriel Fernandez 		lsedrv = fdt_clk_read_uint32_default(name, "st,drive",
18937839a050SYann Gautier 						     LSEDRV_MEDIUM_HIGH);
18940d21680cSYann Gautier 		stm32mp1_lse_enable(bypass, digbyp, lsedrv);
18957839a050SYann Gautier 	}
18960d21680cSYann Gautier 	if (stm32mp1_osc[_HSE] != 0U) {
1897*b208e3daSGabriel Fernandez 		const char *name = stm32mp_osc_node_label[_HSE];
18980d21680cSYann Gautier 		bool bypass, digbyp, css;
18997839a050SYann Gautier 
1900*b208e3daSGabriel Fernandez 		bypass = fdt_clk_read_bool(name, "st,bypass");
1901*b208e3daSGabriel Fernandez 		digbyp = fdt_clk_read_bool(name, "st,digbypass");
1902*b208e3daSGabriel Fernandez 		css = fdt_clk_read_bool(name, "st,css");
19030d21680cSYann Gautier 		stm32mp1_hse_enable(bypass, digbyp, css);
19047839a050SYann Gautier 	}
19057839a050SYann Gautier 	/*
19067839a050SYann Gautier 	 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
19077839a050SYann Gautier 	 * => switch on CSI even if node is not present in device tree
19087839a050SYann Gautier 	 */
19090d21680cSYann Gautier 	stm32mp1_csi_set(true);
19107839a050SYann Gautier 
19117839a050SYann Gautier 	/* Come back to HSI */
19120d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
19137839a050SYann Gautier 	if (ret != 0) {
19147839a050SYann Gautier 		return ret;
19157839a050SYann Gautier 	}
19160d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
19177839a050SYann Gautier 	if (ret != 0) {
19187839a050SYann Gautier 		return ret;
19197839a050SYann Gautier 	}
1920b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
1921b053a22eSYann Gautier 	if (ret != 0) {
1922b053a22eSYann Gautier 		return ret;
1923b053a22eSYann Gautier 	}
19247839a050SYann Gautier 
19250d21680cSYann Gautier 	if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
19260d21680cSYann Gautier 	     RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
19270d21680cSYann Gautier 		pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
19280d21680cSYann Gautier 							clksrc[CLKSRC_PLL3],
19290d21680cSYann Gautier 							pllcfg[_PLL3],
19300d21680cSYann Gautier 							plloff[_PLL3]);
19310d21680cSYann Gautier 		pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
19320d21680cSYann Gautier 							clksrc[CLKSRC_PLL4],
19330d21680cSYann Gautier 							pllcfg[_PLL4],
19340d21680cSYann Gautier 							plloff[_PLL4]);
19350d21680cSYann Gautier 	}
1936bf1af154SPatrick Delaunay 	/* Don't initialize PLL4, when used by BOOTROM */
1937bf1af154SPatrick Delaunay 	if ((stm32mp_get_boot_itf_selected() ==
1938bf1af154SPatrick Delaunay 	     BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) &&
1939bf1af154SPatrick Delaunay 	    ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
1940bf1af154SPatrick Delaunay 		pll4_bootrom = true;
1941bf1af154SPatrick Delaunay 		pll4_preserve = true;
1942bf1af154SPatrick Delaunay 	}
19430d21680cSYann Gautier 
19447839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
19450d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
19460d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve)) {
19477839a050SYann Gautier 			continue;
19480d21680cSYann Gautier 		}
19490d21680cSYann Gautier 
19500d21680cSYann Gautier 		ret = stm32mp1_pll_stop(i);
19517839a050SYann Gautier 		if (ret != 0) {
19527839a050SYann Gautier 			return ret;
19537839a050SYann Gautier 		}
19547839a050SYann Gautier 	}
19557839a050SYann Gautier 
19567839a050SYann Gautier 	/* Configure HSIDIV */
19570d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] != 0U) {
19580d21680cSYann Gautier 		ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
19597839a050SYann Gautier 		if (ret != 0) {
19607839a050SYann Gautier 			return ret;
19617839a050SYann Gautier 		}
19620d21680cSYann Gautier 		stm32mp1_stgen_config();
19637839a050SYann Gautier 	}
19647839a050SYann Gautier 
19657839a050SYann Gautier 	/* Select DIV */
19667839a050SYann Gautier 	/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
19670d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_MPCKDIVR,
19687839a050SYann Gautier 		      clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
19690d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
19707839a050SYann Gautier 	if (ret != 0) {
19717839a050SYann Gautier 		return ret;
19727839a050SYann Gautier 	}
19730d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
19747839a050SYann Gautier 	if (ret != 0) {
19757839a050SYann Gautier 		return ret;
19767839a050SYann Gautier 	}
19770d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
19787839a050SYann Gautier 	if (ret != 0) {
19797839a050SYann Gautier 		return ret;
19807839a050SYann Gautier 	}
1981b053a22eSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
1982b053a22eSYann Gautier 	if (ret != 0) {
1983b053a22eSYann Gautier 		return ret;
1984b053a22eSYann Gautier 	}
19850d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
19867839a050SYann Gautier 	if (ret != 0) {
19877839a050SYann Gautier 		return ret;
19887839a050SYann Gautier 	}
19890d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
19907839a050SYann Gautier 	if (ret != 0) {
19917839a050SYann Gautier 		return ret;
19927839a050SYann Gautier 	}
19930d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
19947839a050SYann Gautier 	if (ret != 0) {
19957839a050SYann Gautier 		return ret;
19967839a050SYann Gautier 	}
19977839a050SYann Gautier 
19987839a050SYann Gautier 	/* No ready bit for RTC */
19990d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_RTCDIVR,
20007839a050SYann Gautier 		      clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
20017839a050SYann Gautier 
20027839a050SYann Gautier 	/* Configure PLLs source */
20030d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
20047839a050SYann Gautier 	if (ret != 0) {
20057839a050SYann Gautier 		return ret;
20067839a050SYann Gautier 	}
20077839a050SYann Gautier 
20080d21680cSYann Gautier 	if (!pll3_preserve) {
20090d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
20107839a050SYann Gautier 		if (ret != 0) {
20117839a050SYann Gautier 			return ret;
20127839a050SYann Gautier 		}
20130d21680cSYann Gautier 	}
20140d21680cSYann Gautier 
20150d21680cSYann Gautier 	if (!pll4_preserve) {
20160d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
20170d21680cSYann Gautier 		if (ret != 0) {
20180d21680cSYann Gautier 			return ret;
20190d21680cSYann Gautier 		}
20200d21680cSYann Gautier 	}
20217839a050SYann Gautier 
20227839a050SYann Gautier 	/* Configure and start PLLs */
20237839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
20240d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
20250d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
20260d21680cSYann Gautier 			continue;
20270d21680cSYann Gautier 		}
20280d21680cSYann Gautier 
2029964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
20307839a050SYann Gautier 			continue;
20317839a050SYann Gautier 		}
20327839a050SYann Gautier 
20330d21680cSYann Gautier 		if ((i == _PLL4) && pll4_bootrom) {
20340d21680cSYann Gautier 			/* Set output divider if not done by the Bootrom */
20350d21680cSYann Gautier 			stm32mp1_pll_config_output(i, pllcfg[i]);
20360d21680cSYann Gautier 			continue;
20370d21680cSYann Gautier 		}
20380d21680cSYann Gautier 
2039964e5ff1SNicolas Le Bayon 		ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]);
20407839a050SYann Gautier 		if (ret != 0) {
20417839a050SYann Gautier 			return ret;
20427839a050SYann Gautier 		}
2043964e5ff1SNicolas Le Bayon 
2044964e5ff1SNicolas Le Bayon 		if (pllcsg_set[i]) {
2045964e5ff1SNicolas Le Bayon 			stm32mp1_pll_csg(i, pllcsg[i]);
20467839a050SYann Gautier 		}
20477839a050SYann Gautier 
20480d21680cSYann Gautier 		stm32mp1_pll_start(i);
20497839a050SYann Gautier 	}
20507839a050SYann Gautier 	/* Wait and start PLLs ouptut when ready */
20517839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
2052964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
20537839a050SYann Gautier 			continue;
20547839a050SYann Gautier 		}
20557839a050SYann Gautier 
20560d21680cSYann Gautier 		ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
20577839a050SYann Gautier 		if (ret != 0) {
20587839a050SYann Gautier 			return ret;
20597839a050SYann Gautier 		}
20607839a050SYann Gautier 	}
20617839a050SYann Gautier 	/* Wait LSE ready before to use it */
20620d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
20630d21680cSYann Gautier 		stm32mp1_lse_wait();
20647839a050SYann Gautier 	}
20657839a050SYann Gautier 
20667839a050SYann Gautier 	/* Configure with expected clock source */
20670d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
20687839a050SYann Gautier 	if (ret != 0) {
20697839a050SYann Gautier 		return ret;
20707839a050SYann Gautier 	}
20710d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
20727839a050SYann Gautier 	if (ret != 0) {
20737839a050SYann Gautier 		return ret;
20747839a050SYann Gautier 	}
2075b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
2076b053a22eSYann Gautier 	if (ret != 0) {
2077b053a22eSYann Gautier 		return ret;
2078b053a22eSYann Gautier 	}
20790d21680cSYann Gautier 	stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
20807839a050SYann Gautier 
20817839a050SYann Gautier 	/* Configure PKCK */
20827839a050SYann Gautier 	pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
20837839a050SYann Gautier 	if (pkcs_cell != NULL) {
20847839a050SYann Gautier 		bool ckper_disabled = false;
20857839a050SYann Gautier 		uint32_t j;
2086bf1af154SPatrick Delaunay 		uint32_t usbreg_bootrom = 0U;
2087bf1af154SPatrick Delaunay 
2088bf1af154SPatrick Delaunay 		if (pll4_bootrom) {
2089bf1af154SPatrick Delaunay 			usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
2090bf1af154SPatrick Delaunay 		}
20917839a050SYann Gautier 
20927839a050SYann Gautier 		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
20933e6fab43SYann Gautier 			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
20947839a050SYann Gautier 
20957839a050SYann Gautier 			if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
20967839a050SYann Gautier 				ckper_disabled = true;
20977839a050SYann Gautier 				continue;
20987839a050SYann Gautier 			}
20990d21680cSYann Gautier 			stm32mp1_pkcs_config(pkcs);
21007839a050SYann Gautier 		}
21017839a050SYann Gautier 
21027839a050SYann Gautier 		/*
21037839a050SYann Gautier 		 * CKPER is source for some peripheral clocks
21047839a050SYann Gautier 		 * (FMC-NAND / QPSI-NOR) and switching source is allowed
21057839a050SYann Gautier 		 * only if previous clock is still ON
21067839a050SYann Gautier 		 * => deactivated CKPER only after switching clock
21077839a050SYann Gautier 		 */
21087839a050SYann Gautier 		if (ckper_disabled) {
21090d21680cSYann Gautier 			stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
21107839a050SYann Gautier 		}
2111bf1af154SPatrick Delaunay 
2112bf1af154SPatrick Delaunay 		if (pll4_bootrom) {
2113bf1af154SPatrick Delaunay 			uint32_t usbreg_value, usbreg_mask;
2114bf1af154SPatrick Delaunay 			const struct stm32mp1_clk_sel *sel;
2115bf1af154SPatrick Delaunay 
2116bf1af154SPatrick Delaunay 			sel = clk_sel_ref(_USBPHY_SEL);
2117bf1af154SPatrick Delaunay 			usbreg_mask = (uint32_t)sel->msk << sel->src;
2118bf1af154SPatrick Delaunay 			sel = clk_sel_ref(_USBO_SEL);
2119bf1af154SPatrick Delaunay 			usbreg_mask |= (uint32_t)sel->msk << sel->src;
2120bf1af154SPatrick Delaunay 
2121bf1af154SPatrick Delaunay 			usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
2122bf1af154SPatrick Delaunay 				       usbreg_mask;
2123bf1af154SPatrick Delaunay 			usbreg_bootrom &= usbreg_mask;
2124bf1af154SPatrick Delaunay 			if (usbreg_bootrom != usbreg_value) {
2125bf1af154SPatrick Delaunay 				VERBOSE("forbidden new USB clk path\n");
2126bf1af154SPatrick Delaunay 				VERBOSE("vs bootrom on USB boot\n");
2127bf1af154SPatrick Delaunay 				return -FDT_ERR_BADVALUE;
2128bf1af154SPatrick Delaunay 			}
2129bf1af154SPatrick Delaunay 		}
21307839a050SYann Gautier 	}
21317839a050SYann Gautier 
21327839a050SYann Gautier 	/* Switch OFF HSI if not found in device-tree */
21330d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] == 0U) {
21340d21680cSYann Gautier 		stm32mp1_hsi_set(false);
21357839a050SYann Gautier 	}
21360d21680cSYann Gautier 	stm32mp1_stgen_config();
21377839a050SYann Gautier 
21387839a050SYann Gautier 	/* Software Self-Refresh mode (SSR) during DDR initilialization */
21390d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
21407839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_MASK,
21417839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SSR <<
21427839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SHIFT);
21437839a050SYann Gautier 
21447839a050SYann Gautier 	return 0;
21457839a050SYann Gautier }
21467839a050SYann Gautier 
21477839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name,
21487839a050SYann Gautier 				  enum stm32mp_osc_id index)
21497839a050SYann Gautier {
21507839a050SYann Gautier 	uint32_t frequency;
21517839a050SYann Gautier 
21520d21680cSYann Gautier 	if (fdt_osc_read_freq(name, &frequency) == 0) {
21530d21680cSYann Gautier 		stm32mp1_osc[index] = frequency;
21547839a050SYann Gautier 	}
21557839a050SYann Gautier }
21567839a050SYann Gautier 
21577839a050SYann Gautier static void stm32mp1_osc_init(void)
21587839a050SYann Gautier {
21597839a050SYann Gautier 	enum stm32mp_osc_id i;
21607839a050SYann Gautier 
21617839a050SYann Gautier 	for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
21620d21680cSYann Gautier 		stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
21637839a050SYann Gautier 	}
21647839a050SYann Gautier }
21657839a050SYann Gautier 
216637e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES
216737e8295aSEtienne Carriere /*
216837e8295aSEtienne Carriere  * Get the parent ID of the target parent clock, for tagging as secure
216937e8295aSEtienne Carriere  * shared clock dependencies.
217037e8295aSEtienne Carriere  */
217137e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id)
217237e8295aSEtienne Carriere {
217337e8295aSEtienne Carriere 	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
217437e8295aSEtienne Carriere 	enum stm32mp1_pll_id pll_id;
217537e8295aSEtienne Carriere 	uint32_t p_sel;
217637e8295aSEtienne Carriere 	uintptr_t rcc_base = stm32mp_rcc_base();
217737e8295aSEtienne Carriere 
217837e8295aSEtienne Carriere 	switch (parent_id) {
217937e8295aSEtienne Carriere 	case _ACLK:
218037e8295aSEtienne Carriere 	case _PCLK4:
218137e8295aSEtienne Carriere 	case _PCLK5:
218237e8295aSEtienne Carriere 		s = _AXIS_SEL;
218337e8295aSEtienne Carriere 		break;
218437e8295aSEtienne Carriere 	case _PLL1_P:
218537e8295aSEtienne Carriere 	case _PLL1_Q:
218637e8295aSEtienne Carriere 	case _PLL1_R:
218737e8295aSEtienne Carriere 		pll_id = _PLL1;
218837e8295aSEtienne Carriere 		break;
218937e8295aSEtienne Carriere 	case _PLL2_P:
219037e8295aSEtienne Carriere 	case _PLL2_Q:
219137e8295aSEtienne Carriere 	case _PLL2_R:
219237e8295aSEtienne Carriere 		pll_id = _PLL2;
219337e8295aSEtienne Carriere 		break;
219437e8295aSEtienne Carriere 	case _PLL3_P:
219537e8295aSEtienne Carriere 	case _PLL3_Q:
219637e8295aSEtienne Carriere 	case _PLL3_R:
219737e8295aSEtienne Carriere 		pll_id = _PLL3;
219837e8295aSEtienne Carriere 		break;
219937e8295aSEtienne Carriere 	case _PLL4_P:
220037e8295aSEtienne Carriere 	case _PLL4_Q:
220137e8295aSEtienne Carriere 	case _PLL4_R:
220237e8295aSEtienne Carriere 		pll_id = _PLL4;
220337e8295aSEtienne Carriere 		break;
220437e8295aSEtienne Carriere 	case _PCLK1:
220537e8295aSEtienne Carriere 	case _PCLK2:
220637e8295aSEtienne Carriere 	case _HCLK2:
220737e8295aSEtienne Carriere 	case _HCLK6:
220837e8295aSEtienne Carriere 	case _CK_PER:
220937e8295aSEtienne Carriere 	case _CK_MPU:
221037e8295aSEtienne Carriere 	case _CK_MCU:
221137e8295aSEtienne Carriere 	case _USB_PHY_48:
221237e8295aSEtienne Carriere 		/* We do not expect to access these */
221337e8295aSEtienne Carriere 		panic();
221437e8295aSEtienne Carriere 		break;
221537e8295aSEtienne Carriere 	default:
221637e8295aSEtienne Carriere 		/* Other parents have no parent */
221737e8295aSEtienne Carriere 		return -1;
221837e8295aSEtienne Carriere 	}
221937e8295aSEtienne Carriere 
222037e8295aSEtienne Carriere 	if (s != _UNKNOWN_SEL) {
222137e8295aSEtienne Carriere 		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
222237e8295aSEtienne Carriere 
222337e8295aSEtienne Carriere 		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
222437e8295aSEtienne Carriere 			sel->msk;
222537e8295aSEtienne Carriere 
222637e8295aSEtienne Carriere 		if (p_sel < sel->nb_parent) {
222737e8295aSEtienne Carriere 			return (int)sel->parent[p_sel];
222837e8295aSEtienne Carriere 		}
222937e8295aSEtienne Carriere 	} else {
223037e8295aSEtienne Carriere 		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
223137e8295aSEtienne Carriere 
223237e8295aSEtienne Carriere 		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
223337e8295aSEtienne Carriere 			RCC_SELR_REFCLK_SRC_MASK;
223437e8295aSEtienne Carriere 
223537e8295aSEtienne Carriere 		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
223637e8295aSEtienne Carriere 			return (int)pll->refclk[p_sel];
223737e8295aSEtienne Carriere 		}
223837e8295aSEtienne Carriere 	}
223937e8295aSEtienne Carriere 
224037e8295aSEtienne Carriere 	VERBOSE("No parent selected for %s\n",
224137e8295aSEtienne Carriere 		stm32mp1_clk_parent_name[parent_id]);
224237e8295aSEtienne Carriere 
224337e8295aSEtienne Carriere 	return -1;
224437e8295aSEtienne Carriere }
224537e8295aSEtienne Carriere 
224637e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id)
224737e8295aSEtienne Carriere {
224837e8295aSEtienne Carriere 	int grandparent_id;
224937e8295aSEtienne Carriere 
225037e8295aSEtienne Carriere 	switch (parent_id) {
225137e8295aSEtienne Carriere 	case _PLL3_P:
225237e8295aSEtienne Carriere 	case _PLL3_Q:
225337e8295aSEtienne Carriere 	case _PLL3_R:
225437e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
225537e8295aSEtienne Carriere 		break;
225637e8295aSEtienne Carriere 
225737e8295aSEtienne Carriere 	/* These clocks are always secure when RCC is secure */
225837e8295aSEtienne Carriere 	case _ACLK:
225937e8295aSEtienne Carriere 	case _HCLK2:
226037e8295aSEtienne Carriere 	case _HCLK6:
226137e8295aSEtienne Carriere 	case _PCLK4:
226237e8295aSEtienne Carriere 	case _PCLK5:
226337e8295aSEtienne Carriere 	case _PLL1_P:
226437e8295aSEtienne Carriere 	case _PLL1_Q:
226537e8295aSEtienne Carriere 	case _PLL1_R:
226637e8295aSEtienne Carriere 	case _PLL2_P:
226737e8295aSEtienne Carriere 	case _PLL2_Q:
226837e8295aSEtienne Carriere 	case _PLL2_R:
226937e8295aSEtienne Carriere 	case _HSI:
227037e8295aSEtienne Carriere 	case _HSI_KER:
227137e8295aSEtienne Carriere 	case _LSI:
227237e8295aSEtienne Carriere 	case _CSI:
227337e8295aSEtienne Carriere 	case _CSI_KER:
227437e8295aSEtienne Carriere 	case _HSE:
227537e8295aSEtienne Carriere 	case _HSE_KER:
227637e8295aSEtienne Carriere 	case _HSE_KER_DIV2:
2277cbd2e8a6SGabriel Fernandez 	case _HSE_RTC:
227837e8295aSEtienne Carriere 	case _LSE:
227937e8295aSEtienne Carriere 		break;
228037e8295aSEtienne Carriere 
228137e8295aSEtienne Carriere 	default:
228237e8295aSEtienne Carriere 		VERBOSE("Cannot secure parent clock %s\n",
228337e8295aSEtienne Carriere 			stm32mp1_clk_parent_name[parent_id]);
228437e8295aSEtienne Carriere 		panic();
228537e8295aSEtienne Carriere 	}
228637e8295aSEtienne Carriere 
228737e8295aSEtienne Carriere 	grandparent_id = get_parent_id_parent(parent_id);
228837e8295aSEtienne Carriere 	if (grandparent_id >= 0) {
228937e8295aSEtienne Carriere 		secure_parent_clocks(grandparent_id);
229037e8295aSEtienne Carriere 	}
229137e8295aSEtienne Carriere }
229237e8295aSEtienne Carriere 
229337e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
229437e8295aSEtienne Carriere {
229537e8295aSEtienne Carriere 	int parent_id;
229637e8295aSEtienne Carriere 
229737e8295aSEtienne Carriere 	if (!stm32mp1_rcc_is_secure()) {
229837e8295aSEtienne Carriere 		return;
229937e8295aSEtienne Carriere 	}
230037e8295aSEtienne Carriere 
230137e8295aSEtienne Carriere 	switch (clock_id) {
230237e8295aSEtienne Carriere 	case PLL1:
230337e8295aSEtienne Carriere 	case PLL2:
230437e8295aSEtienne Carriere 		/* PLL1/PLL2 are always secure: nothing to do */
230537e8295aSEtienne Carriere 		break;
230637e8295aSEtienne Carriere 	case PLL3:
230737e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
230837e8295aSEtienne Carriere 		break;
230937e8295aSEtienne Carriere 	case PLL4:
231037e8295aSEtienne Carriere 		ERROR("PLL4 cannot be secured\n");
231137e8295aSEtienne Carriere 		panic();
231237e8295aSEtienne Carriere 		break;
231337e8295aSEtienne Carriere 	default:
231437e8295aSEtienne Carriere 		/* Others are expected gateable clock */
231537e8295aSEtienne Carriere 		parent_id = stm32mp1_clk_get_parent(clock_id);
231637e8295aSEtienne Carriere 		if (parent_id < 0) {
231737e8295aSEtienne Carriere 			INFO("No parent found for clock %lu\n", clock_id);
231837e8295aSEtienne Carriere 		} else {
231937e8295aSEtienne Carriere 			secure_parent_clocks(parent_id);
232037e8295aSEtienne Carriere 		}
232137e8295aSEtienne Carriere 		break;
232237e8295aSEtienne Carriere 	}
232337e8295aSEtienne Carriere }
232437e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */
232537e8295aSEtienne Carriere 
23266cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void)
23276cb45f89SYann Gautier {
2328033b6c3aSEtienne Carriere 	unsigned int idx;
2329033b6c3aSEtienne Carriere 	const unsigned long secure_enable[] = {
2330033b6c3aSEtienne Carriere 		AXIDCG,
2331033b6c3aSEtienne Carriere 		BSEC,
2332033b6c3aSEtienne Carriere 		DDRC1, DDRC1LP,
2333033b6c3aSEtienne Carriere 		DDRC2, DDRC2LP,
2334033b6c3aSEtienne Carriere 		DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
2335033b6c3aSEtienne Carriere 		DDRPHYC, DDRPHYCLP,
2336373f06beSLionel Debieve 		RTCAPB,
2337033b6c3aSEtienne Carriere 		TZC1, TZC2,
2338033b6c3aSEtienne Carriere 		TZPC,
2339033b6c3aSEtienne Carriere 		STGEN_K,
2340033b6c3aSEtienne Carriere 	};
2341033b6c3aSEtienne Carriere 
2342033b6c3aSEtienne Carriere 	for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
2343033b6c3aSEtienne Carriere 		stm32mp_clk_enable(secure_enable[idx]);
2344033b6c3aSEtienne Carriere 	}
23456cb45f89SYann Gautier }
23466cb45f89SYann Gautier 
234733667d29SYann Gautier static const struct clk_ops stm32mp_clk_ops = {
234833667d29SYann Gautier 	.enable		= stm32mp_clk_enable,
234933667d29SYann Gautier 	.disable	= stm32mp_clk_disable,
235033667d29SYann Gautier 	.is_enabled	= stm32mp_clk_is_enabled,
235133667d29SYann Gautier 	.get_rate	= stm32mp_clk_get_rate,
235233667d29SYann Gautier 	.get_parent	= stm32mp1_clk_get_parent,
235333667d29SYann Gautier };
235433667d29SYann Gautier 
23557839a050SYann Gautier int stm32mp1_clk_probe(void)
23567839a050SYann Gautier {
23577839a050SYann Gautier 	stm32mp1_osc_init();
23587839a050SYann Gautier 
23596cb45f89SYann Gautier 	sync_earlyboot_clocks_state();
23606cb45f89SYann Gautier 
236133667d29SYann Gautier 	clk_register(&stm32mp_clk_ops);
236233667d29SYann Gautier 
23637839a050SYann Gautier 	return 0;
23647839a050SYann Gautier }
2365