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