xref: /rk3399_ARM-atf/drivers/st/clk/stm32mp1_clk.c (revision 37e8295abdc96831dc1ee983c41bad94770628f5)
17839a050SYann Gautier /*
23f9c9784SYann Gautier  * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
37839a050SYann Gautier  *
47839a050SYann Gautier  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
57839a050SYann Gautier  */
67839a050SYann Gautier 
77839a050SYann Gautier #include <assert.h>
87839a050SYann Gautier #include <errno.h>
97839a050SYann Gautier #include <stdint.h>
1039b6cc66SAntonio Nino Diaz #include <stdio.h>
1109d40e0eSAntonio Nino Diaz 
1209d40e0eSAntonio Nino Diaz #include <libfdt.h>
1309d40e0eSAntonio Nino Diaz 
146e6ab282SYann Gautier #include <platform_def.h>
156e6ab282SYann Gautier 
1609d40e0eSAntonio Nino Diaz #include <arch.h>
1709d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1809d40e0eSAntonio Nino Diaz #include <common/debug.h>
1952a616b4SAndre Przywara #include <common/fdt_wrappers.h>
2009d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h>
2109d40e0eSAntonio Nino Diaz #include <drivers/generic_delay_timer.h>
22447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h>
2309d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h>
2409d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h>
2509d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h>
2609d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
270d21680cSYann Gautier #include <lib/spinlock.h>
2809d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
2909d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
3009d40e0eSAntonio Nino Diaz 
317839a050SYann Gautier #define MAX_HSI_HZ		64000000
320d21680cSYann Gautier #define USB_PHY_48_MHZ		48000000
337839a050SYann Gautier 
34dfdb057aSYann Gautier #define TIMEOUT_US_200MS	U(200000)
35dfdb057aSYann Gautier #define TIMEOUT_US_1S		U(1000000)
367839a050SYann Gautier 
37dfdb057aSYann Gautier #define PLLRDY_TIMEOUT		TIMEOUT_US_200MS
38dfdb057aSYann Gautier #define CLKSRC_TIMEOUT		TIMEOUT_US_200MS
39dfdb057aSYann Gautier #define CLKDIV_TIMEOUT		TIMEOUT_US_200MS
40dfdb057aSYann Gautier #define HSIDIV_TIMEOUT		TIMEOUT_US_200MS
41dfdb057aSYann Gautier #define OSCRDY_TIMEOUT		TIMEOUT_US_1S
427839a050SYann Gautier 
43f66358afSYann Gautier const char *stm32mp_osc_node_label[NB_OSC] = {
44f66358afSYann Gautier 	[_LSI] = "clk-lsi",
45f66358afSYann Gautier 	[_LSE] = "clk-lse",
46f66358afSYann Gautier 	[_HSI] = "clk-hsi",
47f66358afSYann Gautier 	[_HSE] = "clk-hse",
48f66358afSYann Gautier 	[_CSI] = "clk-csi",
49f66358afSYann Gautier 	[_I2S_CKIN] = "i2s_ckin",
50f66358afSYann Gautier };
51f66358afSYann Gautier 
527839a050SYann Gautier enum stm32mp1_parent_id {
537839a050SYann Gautier /* Oscillators are defined in enum stm32mp_osc_id */
547839a050SYann Gautier 
557839a050SYann Gautier /* Other parent source */
567839a050SYann Gautier 	_HSI_KER = NB_OSC,
577839a050SYann Gautier 	_HSE_KER,
587839a050SYann Gautier 	_HSE_KER_DIV2,
597839a050SYann Gautier 	_CSI_KER,
607839a050SYann Gautier 	_PLL1_P,
617839a050SYann Gautier 	_PLL1_Q,
627839a050SYann Gautier 	_PLL1_R,
637839a050SYann Gautier 	_PLL2_P,
647839a050SYann Gautier 	_PLL2_Q,
657839a050SYann Gautier 	_PLL2_R,
667839a050SYann Gautier 	_PLL3_P,
677839a050SYann Gautier 	_PLL3_Q,
687839a050SYann Gautier 	_PLL3_R,
697839a050SYann Gautier 	_PLL4_P,
707839a050SYann Gautier 	_PLL4_Q,
717839a050SYann Gautier 	_PLL4_R,
727839a050SYann Gautier 	_ACLK,
737839a050SYann Gautier 	_PCLK1,
747839a050SYann Gautier 	_PCLK2,
757839a050SYann Gautier 	_PCLK3,
767839a050SYann Gautier 	_PCLK4,
777839a050SYann Gautier 	_PCLK5,
787839a050SYann Gautier 	_HCLK6,
797839a050SYann Gautier 	_HCLK2,
807839a050SYann Gautier 	_CK_PER,
817839a050SYann Gautier 	_CK_MPU,
82b053a22eSYann Gautier 	_CK_MCU,
830d21680cSYann Gautier 	_USB_PHY_48,
847839a050SYann Gautier 	_PARENT_NB,
857839a050SYann Gautier 	_UNKNOWN_ID = 0xff,
867839a050SYann Gautier };
877839a050SYann Gautier 
880d21680cSYann Gautier /* Lists only the parent clock we are interested in */
897839a050SYann Gautier enum stm32mp1_parent_sel {
900d21680cSYann Gautier 	_I2C12_SEL,
910d21680cSYann Gautier 	_I2C35_SEL,
920d21680cSYann Gautier 	_STGEN_SEL,
937839a050SYann Gautier 	_I2C46_SEL,
940d21680cSYann Gautier 	_SPI6_SEL,
95d4151d2fSYann Gautier 	_UART1_SEL,
960d21680cSYann Gautier 	_RNG1_SEL,
977839a050SYann Gautier 	_UART6_SEL,
987839a050SYann Gautier 	_UART24_SEL,
997839a050SYann Gautier 	_UART35_SEL,
1007839a050SYann Gautier 	_UART78_SEL,
1017839a050SYann Gautier 	_SDMMC12_SEL,
1027839a050SYann Gautier 	_SDMMC3_SEL,
1037839a050SYann Gautier 	_QSPI_SEL,
1047839a050SYann Gautier 	_FMC_SEL,
105d4151d2fSYann Gautier 	_AXIS_SEL,
106d4151d2fSYann Gautier 	_MCUS_SEL,
1077839a050SYann Gautier 	_USBPHY_SEL,
1087839a050SYann Gautier 	_USBO_SEL,
1098fbcd9e4SEtienne Carriere 	_MPU_SEL,
1108fbcd9e4SEtienne Carriere 	_PER_SEL,
111016af006SEtienne Carriere 	_RTC_SEL,
1127839a050SYann Gautier 	_PARENT_SEL_NB,
1137839a050SYann Gautier 	_UNKNOWN_SEL = 0xff,
1147839a050SYann Gautier };
1157839a050SYann Gautier 
1168fbcd9e4SEtienne Carriere /* State the parent clock ID straight related to a clock */
1178fbcd9e4SEtienne Carriere static const uint8_t parent_id_clock_id[_PARENT_NB] = {
1188fbcd9e4SEtienne Carriere 	[_HSE] = CK_HSE,
1198fbcd9e4SEtienne Carriere 	[_HSI] = CK_HSI,
1208fbcd9e4SEtienne Carriere 	[_CSI] = CK_CSI,
1218fbcd9e4SEtienne Carriere 	[_LSE] = CK_LSE,
1228fbcd9e4SEtienne Carriere 	[_LSI] = CK_LSI,
1238fbcd9e4SEtienne Carriere 	[_I2S_CKIN] = _UNKNOWN_ID,
1248fbcd9e4SEtienne Carriere 	[_USB_PHY_48] = _UNKNOWN_ID,
1258fbcd9e4SEtienne Carriere 	[_HSI_KER] = CK_HSI,
1268fbcd9e4SEtienne Carriere 	[_HSE_KER] = CK_HSE,
1278fbcd9e4SEtienne Carriere 	[_HSE_KER_DIV2] = CK_HSE_DIV2,
1288fbcd9e4SEtienne Carriere 	[_CSI_KER] = CK_CSI,
1298fbcd9e4SEtienne Carriere 	[_PLL1_P] = PLL1_P,
1308fbcd9e4SEtienne Carriere 	[_PLL1_Q] = PLL1_Q,
1318fbcd9e4SEtienne Carriere 	[_PLL1_R] = PLL1_R,
1328fbcd9e4SEtienne Carriere 	[_PLL2_P] = PLL2_P,
1338fbcd9e4SEtienne Carriere 	[_PLL2_Q] = PLL2_Q,
1348fbcd9e4SEtienne Carriere 	[_PLL2_R] = PLL2_R,
1358fbcd9e4SEtienne Carriere 	[_PLL3_P] = PLL3_P,
1368fbcd9e4SEtienne Carriere 	[_PLL3_Q] = PLL3_Q,
1378fbcd9e4SEtienne Carriere 	[_PLL3_R] = PLL3_R,
1388fbcd9e4SEtienne Carriere 	[_PLL4_P] = PLL4_P,
1398fbcd9e4SEtienne Carriere 	[_PLL4_Q] = PLL4_Q,
1408fbcd9e4SEtienne Carriere 	[_PLL4_R] = PLL4_R,
1418fbcd9e4SEtienne Carriere 	[_ACLK] = CK_AXI,
1428fbcd9e4SEtienne Carriere 	[_PCLK1] = CK_AXI,
1438fbcd9e4SEtienne Carriere 	[_PCLK2] = CK_AXI,
1448fbcd9e4SEtienne Carriere 	[_PCLK3] = CK_AXI,
1458fbcd9e4SEtienne Carriere 	[_PCLK4] = CK_AXI,
1468fbcd9e4SEtienne Carriere 	[_PCLK5] = CK_AXI,
1478fbcd9e4SEtienne Carriere 	[_CK_PER] = CK_PER,
1488fbcd9e4SEtienne Carriere 	[_CK_MPU] = CK_MPU,
1498fbcd9e4SEtienne Carriere 	[_CK_MCU] = CK_MCU,
1508fbcd9e4SEtienne Carriere };
1518fbcd9e4SEtienne Carriere 
1528fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id)
1538fbcd9e4SEtienne Carriere {
1548fbcd9e4SEtienne Carriere 	unsigned int n;
1558fbcd9e4SEtienne Carriere 
1568fbcd9e4SEtienne Carriere 	for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
1578fbcd9e4SEtienne Carriere 		if (parent_id_clock_id[n] == id) {
1588fbcd9e4SEtienne Carriere 			return n;
1598fbcd9e4SEtienne Carriere 		}
1608fbcd9e4SEtienne Carriere 	}
1618fbcd9e4SEtienne Carriere 
1628fbcd9e4SEtienne Carriere 	return _UNKNOWN_ID;
1638fbcd9e4SEtienne Carriere }
1648fbcd9e4SEtienne Carriere 
1657839a050SYann Gautier enum stm32mp1_pll_id {
1667839a050SYann Gautier 	_PLL1,
1677839a050SYann Gautier 	_PLL2,
1687839a050SYann Gautier 	_PLL3,
1697839a050SYann Gautier 	_PLL4,
1707839a050SYann Gautier 	_PLL_NB
1717839a050SYann Gautier };
1727839a050SYann Gautier 
1737839a050SYann Gautier enum stm32mp1_div_id {
1747839a050SYann Gautier 	_DIV_P,
1757839a050SYann Gautier 	_DIV_Q,
1767839a050SYann Gautier 	_DIV_R,
1777839a050SYann Gautier 	_DIV_NB,
1787839a050SYann Gautier };
1797839a050SYann Gautier 
1807839a050SYann Gautier enum stm32mp1_clksrc_id {
1817839a050SYann Gautier 	CLKSRC_MPU,
1827839a050SYann Gautier 	CLKSRC_AXI,
183b053a22eSYann Gautier 	CLKSRC_MCU,
1847839a050SYann Gautier 	CLKSRC_PLL12,
1857839a050SYann Gautier 	CLKSRC_PLL3,
1867839a050SYann Gautier 	CLKSRC_PLL4,
1877839a050SYann Gautier 	CLKSRC_RTC,
1887839a050SYann Gautier 	CLKSRC_MCO1,
1897839a050SYann Gautier 	CLKSRC_MCO2,
1907839a050SYann Gautier 	CLKSRC_NB
1917839a050SYann Gautier };
1927839a050SYann Gautier 
1937839a050SYann Gautier enum stm32mp1_clkdiv_id {
1947839a050SYann Gautier 	CLKDIV_MPU,
1957839a050SYann Gautier 	CLKDIV_AXI,
196b053a22eSYann Gautier 	CLKDIV_MCU,
1977839a050SYann Gautier 	CLKDIV_APB1,
1987839a050SYann Gautier 	CLKDIV_APB2,
1997839a050SYann Gautier 	CLKDIV_APB3,
2007839a050SYann Gautier 	CLKDIV_APB4,
2017839a050SYann Gautier 	CLKDIV_APB5,
2027839a050SYann Gautier 	CLKDIV_RTC,
2037839a050SYann Gautier 	CLKDIV_MCO1,
2047839a050SYann Gautier 	CLKDIV_MCO2,
2057839a050SYann Gautier 	CLKDIV_NB
2067839a050SYann Gautier };
2077839a050SYann Gautier 
2087839a050SYann Gautier enum stm32mp1_pllcfg {
2097839a050SYann Gautier 	PLLCFG_M,
2107839a050SYann Gautier 	PLLCFG_N,
2117839a050SYann Gautier 	PLLCFG_P,
2127839a050SYann Gautier 	PLLCFG_Q,
2137839a050SYann Gautier 	PLLCFG_R,
2147839a050SYann Gautier 	PLLCFG_O,
2157839a050SYann Gautier 	PLLCFG_NB
2167839a050SYann Gautier };
2177839a050SYann Gautier 
2187839a050SYann Gautier enum stm32mp1_pllcsg {
2197839a050SYann Gautier 	PLLCSG_MOD_PER,
2207839a050SYann Gautier 	PLLCSG_INC_STEP,
2217839a050SYann Gautier 	PLLCSG_SSCG_MODE,
2227839a050SYann Gautier 	PLLCSG_NB
2237839a050SYann Gautier };
2247839a050SYann Gautier 
2257839a050SYann Gautier enum stm32mp1_plltype {
2267839a050SYann Gautier 	PLL_800,
2277839a050SYann Gautier 	PLL_1600,
2287839a050SYann Gautier 	PLL_TYPE_NB
2297839a050SYann Gautier };
2307839a050SYann Gautier 
2317839a050SYann Gautier struct stm32mp1_pll {
2327839a050SYann Gautier 	uint8_t refclk_min;
2337839a050SYann Gautier 	uint8_t refclk_max;
2347839a050SYann Gautier 	uint8_t divn_max;
2357839a050SYann Gautier };
2367839a050SYann Gautier 
2377839a050SYann Gautier struct stm32mp1_clk_gate {
2387839a050SYann Gautier 	uint16_t offset;
2397839a050SYann Gautier 	uint8_t bit;
2407839a050SYann Gautier 	uint8_t index;
2417839a050SYann Gautier 	uint8_t set_clr;
2420d21680cSYann Gautier 	uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
2430d21680cSYann Gautier 	uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
2447839a050SYann Gautier };
2457839a050SYann Gautier 
2467839a050SYann Gautier struct stm32mp1_clk_sel {
2477839a050SYann Gautier 	uint16_t offset;
2487839a050SYann Gautier 	uint8_t src;
2497839a050SYann Gautier 	uint8_t msk;
2507839a050SYann Gautier 	uint8_t nb_parent;
2517839a050SYann Gautier 	const uint8_t *parent;
2527839a050SYann Gautier };
2537839a050SYann Gautier 
2547839a050SYann Gautier #define REFCLK_SIZE 4
2557839a050SYann Gautier struct stm32mp1_clk_pll {
2567839a050SYann Gautier 	enum stm32mp1_plltype plltype;
2577839a050SYann Gautier 	uint16_t rckxselr;
2587839a050SYann Gautier 	uint16_t pllxcfgr1;
2597839a050SYann Gautier 	uint16_t pllxcfgr2;
2607839a050SYann Gautier 	uint16_t pllxfracr;
2617839a050SYann Gautier 	uint16_t pllxcr;
2627839a050SYann Gautier 	uint16_t pllxcsgr;
2637839a050SYann Gautier 	enum stm32mp_osc_id refclk[REFCLK_SIZE];
2647839a050SYann Gautier };
2657839a050SYann Gautier 
2660d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */
2670d21680cSYann Gautier #define _CLK_SELEC(off, b, idx, s)			\
2687839a050SYann Gautier 	{						\
2697839a050SYann Gautier 		.offset = (off),			\
2707839a050SYann Gautier 		.bit = (b),				\
2717839a050SYann Gautier 		.index = (idx),				\
2727839a050SYann Gautier 		.set_clr = 0,				\
2737839a050SYann Gautier 		.sel = (s),				\
2747839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
2757839a050SYann Gautier 	}
2767839a050SYann Gautier 
2770d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */
2780d21680cSYann Gautier #define _CLK_FIXED(off, b, idx, f)			\
2797839a050SYann Gautier 	{						\
2807839a050SYann Gautier 		.offset = (off),			\
2817839a050SYann Gautier 		.bit = (b),				\
2827839a050SYann Gautier 		.index = (idx),				\
2837839a050SYann Gautier 		.set_clr = 0,				\
2847839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
2857839a050SYann Gautier 		.fixed = (f),				\
2867839a050SYann Gautier 	}
2877839a050SYann Gautier 
2880d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */
2890d21680cSYann Gautier #define _CLK_SC_SELEC(off, b, idx, s)			\
2907839a050SYann Gautier 	{						\
2917839a050SYann Gautier 		.offset = (off),			\
2927839a050SYann Gautier 		.bit = (b),				\
2937839a050SYann Gautier 		.index = (idx),				\
2947839a050SYann Gautier 		.set_clr = 1,				\
2957839a050SYann Gautier 		.sel = (s),				\
2967839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
2977839a050SYann Gautier 	}
2987839a050SYann Gautier 
2990d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */
3000d21680cSYann Gautier #define _CLK_SC_FIXED(off, b, idx, f)			\
3017839a050SYann Gautier 	{						\
3027839a050SYann Gautier 		.offset = (off),			\
3037839a050SYann Gautier 		.bit = (b),				\
3047839a050SYann Gautier 		.index = (idx),				\
3057839a050SYann Gautier 		.set_clr = 1,				\
3067839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
3077839a050SYann Gautier 		.fixed = (f),				\
3087839a050SYann Gautier 	}
3097839a050SYann Gautier 
310d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents)		\
311d4151d2fSYann Gautier 	[_ ## _label ## _SEL] = {				\
312d4151d2fSYann Gautier 		.offset = _rcc_selr,				\
313d4151d2fSYann Gautier 		.src = _rcc_selr ## _ ## _label ## SRC_SHIFT,	\
3148ae08dcdSEtienne Carriere 		.msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \
3158ae08dcdSEtienne Carriere 		       (_rcc_selr ## _ ## _label ## SRC_SHIFT), \
316d4151d2fSYann Gautier 		.parent = (_parents),				\
317d4151d2fSYann Gautier 		.nb_parent = ARRAY_SIZE(_parents)		\
3187839a050SYann Gautier 	}
3197839a050SYann Gautier 
3200d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3,		\
3217839a050SYann Gautier 		 off4, off5, off6,			\
3227839a050SYann Gautier 		 p1, p2, p3, p4)			\
3237839a050SYann Gautier 	[(idx)] = {					\
3247839a050SYann Gautier 		.plltype = (type),			\
3257839a050SYann Gautier 		.rckxselr = (off1),			\
3267839a050SYann Gautier 		.pllxcfgr1 = (off2),			\
3277839a050SYann Gautier 		.pllxcfgr2 = (off3),			\
3287839a050SYann Gautier 		.pllxfracr = (off4),			\
3297839a050SYann Gautier 		.pllxcr = (off5),			\
3307839a050SYann Gautier 		.pllxcsgr = (off6),			\
3317839a050SYann Gautier 		.refclk[0] = (p1),			\
3327839a050SYann Gautier 		.refclk[1] = (p2),			\
3337839a050SYann Gautier 		.refclk[2] = (p3),			\
3347839a050SYann Gautier 		.refclk[3] = (p4),			\
3357839a050SYann Gautier 	}
3367839a050SYann Gautier 
3370d21680cSYann Gautier #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
3380d21680cSYann Gautier 
3397839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
3400d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK),
3410d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
3420d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK),
3430d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
3440d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
3450d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
3460d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
3470d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
3480d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK),
3490d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
3500d21680cSYann Gautier 	_CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
3517839a050SYann Gautier 
3520d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
3530d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
3540d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
3550d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
3560d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
3570d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
3580d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
3590d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
3600d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
3610d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
3620d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
3637839a050SYann Gautier 
3640d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
3650d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
3667839a050SYann Gautier 
367f33b2433SYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
368f33b2433SYann Gautier 
3690d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
3700d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
3710d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
3727839a050SYann Gautier 
3730d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
3740d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
3750d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
376d4151d2fSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
3770d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
3780d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
3790d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
3800d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
3810d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
3820d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
3830d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
3847839a050SYann Gautier 
3850d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
3860d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
3877839a050SYann Gautier 
3880d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
3890d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
3900d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
3910d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
3920d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
3930d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
3940d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
3950d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
3960d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
3970d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
3980d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
3997839a050SYann Gautier 
4000d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
4010d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
4020d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
4030d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
4040d21680cSYann Gautier 	_CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
4057839a050SYann Gautier 
4060d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
4070d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
4080d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
4090d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
4100d21680cSYann Gautier 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
4117839a050SYann Gautier 
412016af006SEtienne Carriere 	_CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL),
4130d21680cSYann Gautier 	_CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
4147839a050SYann Gautier };
4157839a050SYann Gautier 
4160d21680cSYann Gautier static const uint8_t i2c12_parents[] = {
4170d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4180d21680cSYann Gautier };
4190d21680cSYann Gautier 
4200d21680cSYann Gautier static const uint8_t i2c35_parents[] = {
4210d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4220d21680cSYann Gautier };
4230d21680cSYann Gautier 
4240d21680cSYann Gautier static const uint8_t stgen_parents[] = {
4250d21680cSYann Gautier 	_HSI_KER, _HSE_KER
4260d21680cSYann Gautier };
4270d21680cSYann Gautier 
4280d21680cSYann Gautier static const uint8_t i2c46_parents[] = {
4290d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
4300d21680cSYann Gautier };
4310d21680cSYann Gautier 
4320d21680cSYann Gautier static const uint8_t spi6_parents[] = {
4330d21680cSYann Gautier 	_PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
4340d21680cSYann Gautier };
4350d21680cSYann Gautier 
4360d21680cSYann Gautier static const uint8_t usart1_parents[] = {
4370d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
4380d21680cSYann Gautier };
4390d21680cSYann Gautier 
4400d21680cSYann Gautier static const uint8_t rng1_parents[] = {
4410d21680cSYann Gautier 	_CSI, _PLL4_R, _LSE, _LSI
4420d21680cSYann Gautier };
4430d21680cSYann Gautier 
4440d21680cSYann Gautier static const uint8_t uart6_parents[] = {
4450d21680cSYann Gautier 	_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4460d21680cSYann Gautier };
4470d21680cSYann Gautier 
4480d21680cSYann Gautier static const uint8_t uart234578_parents[] = {
4490d21680cSYann Gautier 	_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4500d21680cSYann Gautier };
4510d21680cSYann Gautier 
4520d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = {
4530d21680cSYann Gautier 	_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
4540d21680cSYann Gautier };
4550d21680cSYann Gautier 
4560d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = {
4570d21680cSYann Gautier 	_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
4580d21680cSYann Gautier };
4590d21680cSYann Gautier 
4600d21680cSYann Gautier static const uint8_t qspi_parents[] = {
4610d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4620d21680cSYann Gautier };
4630d21680cSYann Gautier 
4640d21680cSYann Gautier static const uint8_t fmc_parents[] = {
4650d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4660d21680cSYann Gautier };
4670d21680cSYann Gautier 
4680d21680cSYann Gautier static const uint8_t ass_parents[] = {
4690d21680cSYann Gautier 	_HSI, _HSE, _PLL2
4700d21680cSYann Gautier };
4710d21680cSYann Gautier 
472b053a22eSYann Gautier static const uint8_t mss_parents[] = {
473b053a22eSYann Gautier 	_HSI, _HSE, _CSI, _PLL3
474b053a22eSYann Gautier };
475b053a22eSYann Gautier 
4760d21680cSYann Gautier static const uint8_t usbphy_parents[] = {
4770d21680cSYann Gautier 	_HSE_KER, _PLL4_R, _HSE_KER_DIV2
4780d21680cSYann Gautier };
4790d21680cSYann Gautier 
4800d21680cSYann Gautier static const uint8_t usbo_parents[] = {
4810d21680cSYann Gautier 	_PLL4_R, _USB_PHY_48
4820d21680cSYann Gautier };
4837839a050SYann Gautier 
4848fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = {
4858fbcd9e4SEtienne Carriere 	_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
4868fbcd9e4SEtienne Carriere };
4878fbcd9e4SEtienne Carriere 
4888fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = {
4898fbcd9e4SEtienne Carriere 	_HSI, _HSE, _CSI,
4908fbcd9e4SEtienne Carriere };
4918fbcd9e4SEtienne Carriere 
492016af006SEtienne Carriere static const uint8_t rtc_parents[] = {
493016af006SEtienne Carriere 	_UNKNOWN_ID, _LSE, _LSI, _HSE
494016af006SEtienne Carriere };
495016af006SEtienne Carriere 
4967839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
497d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
498d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
499d4151d2fSYann Gautier 	_CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
500d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
501d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
502d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
503d4151d2fSYann Gautier 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
5048fbcd9e4SEtienne Carriere 	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
5058fbcd9e4SEtienne Carriere 	_CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents),
506016af006SEtienne Carriere 	_CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
507d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
508d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
509d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
510d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
511d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
512d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
513d4151d2fSYann Gautier 	_CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
514d4151d2fSYann Gautier 	_CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
515d4151d2fSYann Gautier 	_CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, ass_parents),
516d4151d2fSYann Gautier 	_CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mss_parents),
517d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
518d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
5197839a050SYann Gautier };
5207839a050SYann Gautier 
5217839a050SYann Gautier /* Define characteristic of PLL according type */
5227839a050SYann Gautier #define DIVN_MIN	24
5237839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
5247839a050SYann Gautier 	[PLL_800] = {
5257839a050SYann Gautier 		.refclk_min = 4,
5267839a050SYann Gautier 		.refclk_max = 16,
5277839a050SYann Gautier 		.divn_max = 99,
5287839a050SYann Gautier 	},
5297839a050SYann Gautier 	[PLL_1600] = {
5307839a050SYann Gautier 		.refclk_min = 8,
5317839a050SYann Gautier 		.refclk_max = 16,
5327839a050SYann Gautier 		.divn_max = 199,
5337839a050SYann Gautier 	},
5347839a050SYann Gautier };
5357839a050SYann Gautier 
5367839a050SYann Gautier /* PLLNCFGR2 register divider by output */
5377839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = {
5387839a050SYann Gautier 	[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
5397839a050SYann Gautier 	[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
5400d21680cSYann Gautier 	[_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
5417839a050SYann Gautier };
5427839a050SYann Gautier 
5437839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
5440d21680cSYann Gautier 	_CLK_PLL(_PLL1, PLL_1600,
5457839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
5467839a050SYann Gautier 		 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
5477839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5480d21680cSYann Gautier 	_CLK_PLL(_PLL2, PLL_1600,
5497839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
5507839a050SYann Gautier 		 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
5517839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5520d21680cSYann Gautier 	_CLK_PLL(_PLL3, PLL_800,
5537839a050SYann Gautier 		 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
5547839a050SYann Gautier 		 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
5557839a050SYann Gautier 		 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
5560d21680cSYann Gautier 	_CLK_PLL(_PLL4, PLL_800,
5577839a050SYann Gautier 		 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
5587839a050SYann Gautier 		 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
5597839a050SYann Gautier 		 _HSI, _HSE, _CSI, _I2S_CKIN),
5607839a050SYann Gautier };
5617839a050SYann Gautier 
5627839a050SYann Gautier /* Prescaler table lookups for clock computation */
563b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
564b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = {
565b053a22eSYann Gautier 	0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
566b053a22eSYann Gautier };
5677839a050SYann Gautier 
5687839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
5697839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
5707839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
5717839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = {
5727839a050SYann Gautier 	0, 1, 2, 3, 4, 4, 4, 4
5737839a050SYann Gautier };
5747839a050SYann Gautier 
5757839a050SYann Gautier /* div = /1 /2 /3 /4 */
5767839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = {
5777839a050SYann Gautier 	1, 2, 3, 4, 4, 4, 4, 4
5787839a050SYann Gautier };
5797839a050SYann Gautier 
580*37e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
581*37e8295aSEtienne Carriere 	[_HSI] = "HSI",
582*37e8295aSEtienne Carriere 	[_HSE] = "HSE",
583*37e8295aSEtienne Carriere 	[_CSI] = "CSI",
584*37e8295aSEtienne Carriere 	[_LSI] = "LSI",
585*37e8295aSEtienne Carriere 	[_LSE] = "LSE",
586*37e8295aSEtienne Carriere 	[_I2S_CKIN] = "I2S_CKIN",
587*37e8295aSEtienne Carriere 	[_HSI_KER] = "HSI_KER",
588*37e8295aSEtienne Carriere 	[_HSE_KER] = "HSE_KER",
589*37e8295aSEtienne Carriere 	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
590*37e8295aSEtienne Carriere 	[_CSI_KER] = "CSI_KER",
591*37e8295aSEtienne Carriere 	[_PLL1_P] = "PLL1_P",
592*37e8295aSEtienne Carriere 	[_PLL1_Q] = "PLL1_Q",
593*37e8295aSEtienne Carriere 	[_PLL1_R] = "PLL1_R",
594*37e8295aSEtienne Carriere 	[_PLL2_P] = "PLL2_P",
595*37e8295aSEtienne Carriere 	[_PLL2_Q] = "PLL2_Q",
596*37e8295aSEtienne Carriere 	[_PLL2_R] = "PLL2_R",
597*37e8295aSEtienne Carriere 	[_PLL3_P] = "PLL3_P",
598*37e8295aSEtienne Carriere 	[_PLL3_Q] = "PLL3_Q",
599*37e8295aSEtienne Carriere 	[_PLL3_R] = "PLL3_R",
600*37e8295aSEtienne Carriere 	[_PLL4_P] = "PLL4_P",
601*37e8295aSEtienne Carriere 	[_PLL4_Q] = "PLL4_Q",
602*37e8295aSEtienne Carriere 	[_PLL4_R] = "PLL4_R",
603*37e8295aSEtienne Carriere 	[_ACLK] = "ACLK",
604*37e8295aSEtienne Carriere 	[_PCLK1] = "PCLK1",
605*37e8295aSEtienne Carriere 	[_PCLK2] = "PCLK2",
606*37e8295aSEtienne Carriere 	[_PCLK3] = "PCLK3",
607*37e8295aSEtienne Carriere 	[_PCLK4] = "PCLK4",
608*37e8295aSEtienne Carriere 	[_PCLK5] = "PCLK5",
609*37e8295aSEtienne Carriere 	[_HCLK6] = "KCLK6",
610*37e8295aSEtienne Carriere 	[_HCLK2] = "HCLK2",
611*37e8295aSEtienne Carriere 	[_CK_PER] = "CK_PER",
612*37e8295aSEtienne Carriere 	[_CK_MPU] = "CK_MPU",
613*37e8295aSEtienne Carriere 	[_CK_MCU] = "CK_MCU",
614*37e8295aSEtienne Carriere 	[_USB_PHY_48] = "USB_PHY_48",
615*37e8295aSEtienne Carriere };
616*37e8295aSEtienne Carriere 
6170d21680cSYann Gautier /* RCC clock device driver private */
6180d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC];
6190d21680cSYann Gautier static struct spinlock reg_lock;
6200d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES];
6210d21680cSYann Gautier static struct spinlock refcount_lock;
6227839a050SYann Gautier 
6230d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
6240d21680cSYann Gautier {
6250d21680cSYann Gautier 	return &stm32mp1_clk_gate[idx];
6260d21680cSYann Gautier }
6277839a050SYann Gautier 
6280d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
6290d21680cSYann Gautier {
6300d21680cSYann Gautier 	return &stm32mp1_clk_sel[idx];
6310d21680cSYann Gautier }
6320d21680cSYann Gautier 
6330d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
6340d21680cSYann Gautier {
6350d21680cSYann Gautier 	return &stm32mp1_clk_pll[idx];
6360d21680cSYann Gautier }
6370d21680cSYann Gautier 
6380d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock)
6390d21680cSYann Gautier {
640e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6410d21680cSYann Gautier 		/* Assume interrupts are masked */
6420d21680cSYann Gautier 		spin_lock(lock);
6430d21680cSYann Gautier 	}
644e463d3f4SYann Gautier }
6450d21680cSYann Gautier 
6460d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock)
6470d21680cSYann Gautier {
648e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6490d21680cSYann Gautier 		spin_unlock(lock);
6500d21680cSYann Gautier 	}
651e463d3f4SYann Gautier }
6520d21680cSYann Gautier 
6530d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void)
6540d21680cSYann Gautier {
6550d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6560d21680cSYann Gautier 
6570d21680cSYann Gautier 	return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_TZEN) != 0;
6580d21680cSYann Gautier }
6590d21680cSYann Gautier 
660b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void)
661b053a22eSYann Gautier {
662b053a22eSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
663b053a22eSYann Gautier 
664b053a22eSYann Gautier 	return (mmio_read_32(rcc_base + RCC_TZCR) & RCC_TZCR_MCKPROT) != 0;
665b053a22eSYann Gautier }
666b053a22eSYann Gautier 
6670d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void)
6680d21680cSYann Gautier {
6690d21680cSYann Gautier 	stm32mp1_clk_lock(&reg_lock);
6700d21680cSYann Gautier }
6710d21680cSYann Gautier 
6720d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void)
6730d21680cSYann Gautier {
6740d21680cSYann Gautier 	stm32mp1_clk_unlock(&reg_lock);
6750d21680cSYann Gautier }
6760d21680cSYann Gautier 
6770d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
6787839a050SYann Gautier {
6797839a050SYann Gautier 	if (idx >= NB_OSC) {
6807839a050SYann Gautier 		return 0;
6817839a050SYann Gautier 	}
6827839a050SYann Gautier 
6830d21680cSYann Gautier 	return stm32mp1_osc[idx];
6847839a050SYann Gautier }
6857839a050SYann Gautier 
6860d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id)
6877839a050SYann Gautier {
6880d21680cSYann Gautier 	unsigned int i;
6897839a050SYann Gautier 
6900d21680cSYann Gautier 	for (i = 0U; i < NB_GATES; i++) {
6910d21680cSYann Gautier 		if (gate_ref(i)->index == id) {
6927839a050SYann Gautier 			return i;
6937839a050SYann Gautier 		}
6947839a050SYann Gautier 	}
6957839a050SYann Gautier 
6967839a050SYann Gautier 	ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id);
6977839a050SYann Gautier 
6987839a050SYann Gautier 	return -EINVAL;
6997839a050SYann Gautier }
7007839a050SYann Gautier 
7010d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
7027839a050SYann Gautier {
7030d21680cSYann Gautier 	return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
7047839a050SYann Gautier }
7057839a050SYann Gautier 
7060d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
7077839a050SYann Gautier {
7080d21680cSYann Gautier 	return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
7097839a050SYann Gautier }
7107839a050SYann Gautier 
7110d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id)
7127839a050SYann Gautier {
7130d21680cSYann Gautier 	const struct stm32mp1_clk_sel *sel;
7148fbcd9e4SEtienne Carriere 	uint32_t p_sel;
7157839a050SYann Gautier 	int i;
7167839a050SYann Gautier 	enum stm32mp1_parent_id p;
7177839a050SYann Gautier 	enum stm32mp1_parent_sel s;
7180d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7197839a050SYann Gautier 
7208fbcd9e4SEtienne Carriere 	/* Few non gateable clock have a static parent ID, find them */
7218fbcd9e4SEtienne Carriere 	i = (int)clock_id2parent_id(id);
7228fbcd9e4SEtienne Carriere 	if (i != _UNKNOWN_ID) {
7238fbcd9e4SEtienne Carriere 		return i;
7247839a050SYann Gautier 	}
7257839a050SYann Gautier 
7260d21680cSYann Gautier 	i = stm32mp1_clk_get_gated_id(id);
7277839a050SYann Gautier 	if (i < 0) {
7280d21680cSYann Gautier 		panic();
7297839a050SYann Gautier 	}
7307839a050SYann Gautier 
7310d21680cSYann Gautier 	p = stm32mp1_clk_get_fixed_parent(i);
7327839a050SYann Gautier 	if (p < _PARENT_NB) {
7337839a050SYann Gautier 		return (int)p;
7347839a050SYann Gautier 	}
7357839a050SYann Gautier 
7360d21680cSYann Gautier 	s = stm32mp1_clk_get_sel(i);
7370d21680cSYann Gautier 	if (s == _UNKNOWN_SEL) {
7380d21680cSYann Gautier 		return -EINVAL;
7390d21680cSYann Gautier 	}
7407839a050SYann Gautier 	if (s >= _PARENT_SEL_NB) {
7410d21680cSYann Gautier 		panic();
7427839a050SYann Gautier 	}
7437839a050SYann Gautier 
7440d21680cSYann Gautier 	sel = clk_sel_ref(s);
7458ae08dcdSEtienne Carriere 	p_sel = (mmio_read_32(rcc_base + sel->offset) &
7468ae08dcdSEtienne Carriere 		 (sel->msk << sel->src)) >> sel->src;
7470d21680cSYann Gautier 	if (p_sel < sel->nb_parent) {
7480d21680cSYann Gautier 		return (int)sel->parent[p_sel];
7497839a050SYann Gautier 	}
7507839a050SYann Gautier 
7517839a050SYann Gautier 	return -EINVAL;
7527839a050SYann Gautier }
7537839a050SYann Gautier 
7540d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
7557839a050SYann Gautier {
7560d21680cSYann Gautier 	uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
7570d21680cSYann Gautier 	uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
7587839a050SYann Gautier 
7590d21680cSYann Gautier 	return stm32mp1_clk_get_fixed(pll->refclk[src]);
7607839a050SYann Gautier }
7617839a050SYann Gautier 
7627839a050SYann Gautier /*
7637839a050SYann Gautier  * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
7647839a050SYann Gautier  * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
7657839a050SYann Gautier  * - PLL3 & PLL4 => return VCO     with Fpll_y_ck = FVCO / (DIVy + 1)
7667839a050SYann Gautier  * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
7677839a050SYann Gautier  */
7680d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
7697839a050SYann Gautier {
7707839a050SYann Gautier 	unsigned long refclk, fvco;
7717839a050SYann Gautier 	uint32_t cfgr1, fracr, divm, divn;
7720d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7737839a050SYann Gautier 
7740d21680cSYann Gautier 	cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
7750d21680cSYann Gautier 	fracr = mmio_read_32(rcc_base + pll->pllxfracr);
7767839a050SYann Gautier 
7777839a050SYann Gautier 	divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
7787839a050SYann Gautier 	divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
7797839a050SYann Gautier 
7800d21680cSYann Gautier 	refclk = stm32mp1_pll_get_fref(pll);
7817839a050SYann Gautier 
7827839a050SYann Gautier 	/*
7837839a050SYann Gautier 	 * With FRACV :
7847839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
7857839a050SYann Gautier 	 * Without FRACV
7867839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
7877839a050SYann Gautier 	 */
7887839a050SYann Gautier 	if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
7890d21680cSYann Gautier 		uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
7900d21680cSYann Gautier 				 RCC_PLLNFRACR_FRACV_SHIFT;
7917839a050SYann Gautier 		unsigned long long numerator, denominator;
7927839a050SYann Gautier 
7930d21680cSYann Gautier 		numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
7940d21680cSYann Gautier 		numerator = refclk * numerator;
7957839a050SYann Gautier 		denominator = ((unsigned long long)divm + 1U) << 13;
7967839a050SYann Gautier 		fvco = (unsigned long)(numerator / denominator);
7977839a050SYann Gautier 	} else {
7987839a050SYann Gautier 		fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
7997839a050SYann Gautier 	}
8007839a050SYann Gautier 
8017839a050SYann Gautier 	return fvco;
8027839a050SYann Gautier }
8037839a050SYann Gautier 
8040d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
8057839a050SYann Gautier 					    enum stm32mp1_div_id div_id)
8067839a050SYann Gautier {
8070d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
8087839a050SYann Gautier 	unsigned long dfout;
8097839a050SYann Gautier 	uint32_t cfgr2, divy;
8107839a050SYann Gautier 
8117839a050SYann Gautier 	if (div_id >= _DIV_NB) {
8127839a050SYann Gautier 		return 0;
8137839a050SYann Gautier 	}
8147839a050SYann Gautier 
8150d21680cSYann Gautier 	cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
8167839a050SYann Gautier 	divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
8177839a050SYann Gautier 
8180d21680cSYann Gautier 	dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
8197839a050SYann Gautier 
8207839a050SYann Gautier 	return dfout;
8217839a050SYann Gautier }
8227839a050SYann Gautier 
8230d21680cSYann Gautier static unsigned long get_clock_rate(int p)
8247839a050SYann Gautier {
8257839a050SYann Gautier 	uint32_t reg, clkdiv;
8267839a050SYann Gautier 	unsigned long clock = 0;
8270d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
8287839a050SYann Gautier 
8297839a050SYann Gautier 	switch (p) {
8307839a050SYann Gautier 	case _CK_MPU:
8317839a050SYann Gautier 	/* MPU sub system */
8320d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
8337839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8347839a050SYann Gautier 		case RCC_MPCKSELR_HSI:
8350d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8367839a050SYann Gautier 			break;
8377839a050SYann Gautier 		case RCC_MPCKSELR_HSE:
8380d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8397839a050SYann Gautier 			break;
8407839a050SYann Gautier 		case RCC_MPCKSELR_PLL:
8410d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8427839a050SYann Gautier 			break;
8437839a050SYann Gautier 		case RCC_MPCKSELR_PLL_MPUDIV:
8440d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8457839a050SYann Gautier 
8460d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
8477839a050SYann Gautier 			clkdiv = reg & RCC_MPUDIV_MASK;
8487839a050SYann Gautier 			if (clkdiv != 0U) {
8497839a050SYann Gautier 				clock /= stm32mp1_mpu_div[clkdiv];
8507839a050SYann Gautier 			}
8517839a050SYann Gautier 			break;
8527839a050SYann Gautier 		default:
8537839a050SYann Gautier 			break;
8547839a050SYann Gautier 		}
8557839a050SYann Gautier 		break;
8567839a050SYann Gautier 	/* AXI sub system */
8577839a050SYann Gautier 	case _ACLK:
8587839a050SYann Gautier 	case _HCLK2:
8597839a050SYann Gautier 	case _HCLK6:
8607839a050SYann Gautier 	case _PCLK4:
8617839a050SYann Gautier 	case _PCLK5:
8620d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
8637839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8647839a050SYann Gautier 		case RCC_ASSCKSELR_HSI:
8650d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8667839a050SYann Gautier 			break;
8677839a050SYann Gautier 		case RCC_ASSCKSELR_HSE:
8680d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8697839a050SYann Gautier 			break;
8707839a050SYann Gautier 		case RCC_ASSCKSELR_PLL:
8710d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
8727839a050SYann Gautier 			break;
8737839a050SYann Gautier 		default:
8747839a050SYann Gautier 			break;
8757839a050SYann Gautier 		}
8767839a050SYann Gautier 
8777839a050SYann Gautier 		/* System clock divider */
8780d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
8797839a050SYann Gautier 		clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
8807839a050SYann Gautier 
8817839a050SYann Gautier 		switch (p) {
8827839a050SYann Gautier 		case _PCLK4:
8830d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
8847839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
8857839a050SYann Gautier 			break;
8867839a050SYann Gautier 		case _PCLK5:
8870d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
8887839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
8897839a050SYann Gautier 			break;
8907839a050SYann Gautier 		default:
8917839a050SYann Gautier 			break;
8927839a050SYann Gautier 		}
8937839a050SYann Gautier 		break;
894b053a22eSYann Gautier 	/* MCU sub system */
895b053a22eSYann Gautier 	case _CK_MCU:
896b053a22eSYann Gautier 	case _PCLK1:
897b053a22eSYann Gautier 	case _PCLK2:
898b053a22eSYann Gautier 	case _PCLK3:
899b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
900b053a22eSYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
901b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSI:
902b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
903b053a22eSYann Gautier 			break;
904b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSE:
905b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
906b053a22eSYann Gautier 			break;
907b053a22eSYann Gautier 		case RCC_MSSCKSELR_CSI:
908b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
909b053a22eSYann Gautier 			break;
910b053a22eSYann Gautier 		case RCC_MSSCKSELR_PLL:
911b053a22eSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
912b053a22eSYann Gautier 			break;
913b053a22eSYann Gautier 		default:
914b053a22eSYann Gautier 			break;
915b053a22eSYann Gautier 		}
916b053a22eSYann Gautier 
917b053a22eSYann Gautier 		/* MCU clock divider */
918b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
919b053a22eSYann Gautier 		clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
920b053a22eSYann Gautier 
921b053a22eSYann Gautier 		switch (p) {
922b053a22eSYann Gautier 		case _PCLK1:
923b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
924b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
925b053a22eSYann Gautier 			break;
926b053a22eSYann Gautier 		case _PCLK2:
927b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
928b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
929b053a22eSYann Gautier 			break;
930b053a22eSYann Gautier 		case _PCLK3:
931b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
932b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
933b053a22eSYann Gautier 			break;
934b053a22eSYann Gautier 		case _CK_MCU:
935b053a22eSYann Gautier 		default:
936b053a22eSYann Gautier 			break;
937b053a22eSYann Gautier 		}
938b053a22eSYann Gautier 		break;
9397839a050SYann Gautier 	case _CK_PER:
9400d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
9417839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
9427839a050SYann Gautier 		case RCC_CPERCKSELR_HSI:
9430d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
9447839a050SYann Gautier 			break;
9457839a050SYann Gautier 		case RCC_CPERCKSELR_HSE:
9460d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
9477839a050SYann Gautier 			break;
9487839a050SYann Gautier 		case RCC_CPERCKSELR_CSI:
9490d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
9507839a050SYann Gautier 			break;
9517839a050SYann Gautier 		default:
9527839a050SYann Gautier 			break;
9537839a050SYann Gautier 		}
9547839a050SYann Gautier 		break;
9557839a050SYann Gautier 	case _HSI:
9567839a050SYann Gautier 	case _HSI_KER:
9570d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSI);
9587839a050SYann Gautier 		break;
9597839a050SYann Gautier 	case _CSI:
9607839a050SYann Gautier 	case _CSI_KER:
9610d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_CSI);
9627839a050SYann Gautier 		break;
9637839a050SYann Gautier 	case _HSE:
9647839a050SYann Gautier 	case _HSE_KER:
9650d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE);
9667839a050SYann Gautier 		break;
9677839a050SYann Gautier 	case _HSE_KER_DIV2:
9680d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
9697839a050SYann Gautier 		break;
9707839a050SYann Gautier 	case _LSI:
9710d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSI);
9727839a050SYann Gautier 		break;
9737839a050SYann Gautier 	case _LSE:
9740d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSE);
9757839a050SYann Gautier 		break;
9767839a050SYann Gautier 	/* PLL */
9777839a050SYann Gautier 	case _PLL1_P:
9780d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
9797839a050SYann Gautier 		break;
9807839a050SYann Gautier 	case _PLL1_Q:
9810d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
9827839a050SYann Gautier 		break;
9837839a050SYann Gautier 	case _PLL1_R:
9840d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
9857839a050SYann Gautier 		break;
9867839a050SYann Gautier 	case _PLL2_P:
9870d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
9887839a050SYann Gautier 		break;
9897839a050SYann Gautier 	case _PLL2_Q:
9900d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
9917839a050SYann Gautier 		break;
9927839a050SYann Gautier 	case _PLL2_R:
9930d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
9947839a050SYann Gautier 		break;
9957839a050SYann Gautier 	case _PLL3_P:
9960d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
9977839a050SYann Gautier 		break;
9987839a050SYann Gautier 	case _PLL3_Q:
9990d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
10007839a050SYann Gautier 		break;
10017839a050SYann Gautier 	case _PLL3_R:
10020d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
10037839a050SYann Gautier 		break;
10047839a050SYann Gautier 	case _PLL4_P:
10050d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
10067839a050SYann Gautier 		break;
10077839a050SYann Gautier 	case _PLL4_Q:
10080d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
10097839a050SYann Gautier 		break;
10107839a050SYann Gautier 	case _PLL4_R:
10110d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
10127839a050SYann Gautier 		break;
10137839a050SYann Gautier 	/* Other */
10147839a050SYann Gautier 	case _USB_PHY_48:
10150d21680cSYann Gautier 		clock = USB_PHY_48_MHZ;
10167839a050SYann Gautier 		break;
10177839a050SYann Gautier 	default:
10187839a050SYann Gautier 		break;
10197839a050SYann Gautier 	}
10207839a050SYann Gautier 
10217839a050SYann Gautier 	return clock;
10227839a050SYann Gautier }
10237839a050SYann Gautier 
10240d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate)
10250d21680cSYann Gautier {
10260d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10270d21680cSYann Gautier 
102825be845eSEtienne Carriere 	VERBOSE("Enable clock %u\n", gate->index);
102925be845eSEtienne Carriere 
10300d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10310d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
10320d21680cSYann Gautier 	} else {
10330d21680cSYann Gautier 		mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
10340d21680cSYann Gautier 	}
10350d21680cSYann Gautier }
10360d21680cSYann Gautier 
10370d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate)
10380d21680cSYann Gautier {
10390d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10400d21680cSYann Gautier 
104125be845eSEtienne Carriere 	VERBOSE("Disable clock %u\n", gate->index);
104225be845eSEtienne Carriere 
10430d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10440d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
10450d21680cSYann Gautier 			      BIT(gate->bit));
10460d21680cSYann Gautier 	} else {
10470d21680cSYann Gautier 		mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
10480d21680cSYann Gautier 	}
10490d21680cSYann Gautier }
10500d21680cSYann Gautier 
10510d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
10520d21680cSYann Gautier {
10530d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10540d21680cSYann Gautier 
10550d21680cSYann Gautier 	return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
10560d21680cSYann Gautier }
10570d21680cSYann Gautier 
10580d21680cSYann Gautier unsigned int stm32mp1_clk_get_refcount(unsigned long id)
10590d21680cSYann Gautier {
10600d21680cSYann Gautier 	int i = stm32mp1_clk_get_gated_id(id);
10610d21680cSYann Gautier 
10620d21680cSYann Gautier 	if (i < 0) {
10630d21680cSYann Gautier 		panic();
10640d21680cSYann Gautier 	}
10650d21680cSYann Gautier 
10660d21680cSYann Gautier 	return gate_refcounts[i];
10670d21680cSYann Gautier }
10680d21680cSYann Gautier 
106935848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */
107035848200SEtienne Carriere static bool clock_is_always_on(unsigned long id)
107135848200SEtienne Carriere {
107235848200SEtienne Carriere 	switch (id) {
107335848200SEtienne Carriere 	case CK_HSE:
107435848200SEtienne Carriere 	case CK_CSI:
107535848200SEtienne Carriere 	case CK_LSI:
107635848200SEtienne Carriere 	case CK_LSE:
107735848200SEtienne Carriere 	case CK_HSI:
107835848200SEtienne Carriere 	case CK_HSE_DIV2:
107935848200SEtienne Carriere 	case PLL1_Q:
108035848200SEtienne Carriere 	case PLL1_R:
108135848200SEtienne Carriere 	case PLL2_P:
108235848200SEtienne Carriere 	case PLL2_Q:
108335848200SEtienne Carriere 	case PLL2_R:
108435848200SEtienne Carriere 	case PLL3_P:
108535848200SEtienne Carriere 	case PLL3_Q:
108635848200SEtienne Carriere 	case PLL3_R:
108735848200SEtienne Carriere 		return true;
108835848200SEtienne Carriere 	default:
108935848200SEtienne Carriere 		return false;
109035848200SEtienne Carriere 	}
109135848200SEtienne Carriere }
109235848200SEtienne Carriere 
10930d21680cSYann Gautier void __stm32mp1_clk_enable(unsigned long id, bool secure)
10940d21680cSYann Gautier {
10950d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
109635848200SEtienne Carriere 	int i;
10970d21680cSYann Gautier 	unsigned int *refcnt;
10980d21680cSYann Gautier 
109935848200SEtienne Carriere 	if (clock_is_always_on(id)) {
110035848200SEtienne Carriere 		return;
110135848200SEtienne Carriere 	}
110235848200SEtienne Carriere 
110335848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11040d21680cSYann Gautier 	if (i < 0) {
11050d21680cSYann Gautier 		ERROR("Clock %d can't be enabled\n", (uint32_t)id);
11060d21680cSYann Gautier 		panic();
11070d21680cSYann Gautier 	}
11080d21680cSYann Gautier 
11090d21680cSYann Gautier 	gate = gate_ref(i);
11100d21680cSYann Gautier 	refcnt = &gate_refcounts[i];
11110d21680cSYann Gautier 
11120d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11130d21680cSYann Gautier 
11140d21680cSYann Gautier 	if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) {
11150d21680cSYann Gautier 		__clk_enable(gate);
11160d21680cSYann Gautier 	}
11170d21680cSYann Gautier 
11180d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
11190d21680cSYann Gautier }
11200d21680cSYann Gautier 
11210d21680cSYann Gautier void __stm32mp1_clk_disable(unsigned long id, bool secure)
11220d21680cSYann Gautier {
11230d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
112435848200SEtienne Carriere 	int i;
11250d21680cSYann Gautier 	unsigned int *refcnt;
11260d21680cSYann Gautier 
112735848200SEtienne Carriere 	if (clock_is_always_on(id)) {
112835848200SEtienne Carriere 		return;
112935848200SEtienne Carriere 	}
113035848200SEtienne Carriere 
113135848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11320d21680cSYann Gautier 	if (i < 0) {
11330d21680cSYann Gautier 		ERROR("Clock %d can't be disabled\n", (uint32_t)id);
11340d21680cSYann Gautier 		panic();
11350d21680cSYann Gautier 	}
11360d21680cSYann Gautier 
11370d21680cSYann Gautier 	gate = gate_ref(i);
11380d21680cSYann Gautier 	refcnt = &gate_refcounts[i];
11390d21680cSYann Gautier 
11400d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11410d21680cSYann Gautier 
11420d21680cSYann Gautier 	if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) {
11430d21680cSYann Gautier 		__clk_disable(gate);
11440d21680cSYann Gautier 	}
11450d21680cSYann Gautier 
11460d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
11470d21680cSYann Gautier }
11480d21680cSYann Gautier 
11490d21680cSYann Gautier void stm32mp_clk_enable(unsigned long id)
11500d21680cSYann Gautier {
11510d21680cSYann Gautier 	__stm32mp1_clk_enable(id, true);
11520d21680cSYann Gautier }
11530d21680cSYann Gautier 
11540d21680cSYann Gautier void stm32mp_clk_disable(unsigned long id)
11550d21680cSYann Gautier {
11560d21680cSYann Gautier 	__stm32mp1_clk_disable(id, true);
11570d21680cSYann Gautier }
11580d21680cSYann Gautier 
11593f9c9784SYann Gautier bool stm32mp_clk_is_enabled(unsigned long id)
11607839a050SYann Gautier {
116135848200SEtienne Carriere 	int i;
11627839a050SYann Gautier 
116335848200SEtienne Carriere 	if (clock_is_always_on(id)) {
116435848200SEtienne Carriere 		return true;
116535848200SEtienne Carriere 	}
116635848200SEtienne Carriere 
116735848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11687839a050SYann Gautier 	if (i < 0) {
11690d21680cSYann Gautier 		panic();
11707839a050SYann Gautier 	}
11717839a050SYann Gautier 
11720d21680cSYann Gautier 	return __clk_is_enabled(gate_ref(i));
11737839a050SYann Gautier }
11747839a050SYann Gautier 
11753f9c9784SYann Gautier unsigned long stm32mp_clk_get_rate(unsigned long id)
11767839a050SYann Gautier {
11770d21680cSYann Gautier 	int p = stm32mp1_clk_get_parent(id);
11787839a050SYann Gautier 
11797839a050SYann Gautier 	if (p < 0) {
11807839a050SYann Gautier 		return 0;
11817839a050SYann Gautier 	}
11827839a050SYann Gautier 
11830d21680cSYann Gautier 	return get_clock_rate(p);
11847839a050SYann Gautier }
11857839a050SYann Gautier 
11860d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
11877839a050SYann Gautier {
11880d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
11897839a050SYann Gautier 
11900d21680cSYann Gautier 	if (enable) {
11917839a050SYann Gautier 		mmio_setbits_32(address, mask_on);
11927839a050SYann Gautier 	} else {
11937839a050SYann Gautier 		mmio_clrbits_32(address, mask_on);
11947839a050SYann Gautier 	}
11957839a050SYann Gautier }
11967839a050SYann Gautier 
11970d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
11987839a050SYann Gautier {
11990d21680cSYann Gautier 	uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
12000d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12010d21680cSYann Gautier 
12020d21680cSYann Gautier 	mmio_write_32(address, mask_on);
12037839a050SYann Gautier }
12047839a050SYann Gautier 
12050d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
12067839a050SYann Gautier {
1207dfdb057aSYann Gautier 	uint64_t timeout;
12087839a050SYann Gautier 	uint32_t mask_test;
12090d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12107839a050SYann Gautier 
12110d21680cSYann Gautier 	if (enable) {
12127839a050SYann Gautier 		mask_test = mask_rdy;
12137839a050SYann Gautier 	} else {
12147839a050SYann Gautier 		mask_test = 0;
12157839a050SYann Gautier 	}
12167839a050SYann Gautier 
1217dfdb057aSYann Gautier 	timeout = timeout_init_us(OSCRDY_TIMEOUT);
12187839a050SYann Gautier 	while ((mmio_read_32(address) & mask_rdy) != mask_test) {
1219dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
12200d21680cSYann Gautier 			ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
12217839a050SYann Gautier 			      mask_rdy, address, enable, mmio_read_32(address));
12227839a050SYann Gautier 			return -ETIMEDOUT;
12237839a050SYann Gautier 		}
12247839a050SYann Gautier 	}
12257839a050SYann Gautier 
12267839a050SYann Gautier 	return 0;
12277839a050SYann Gautier }
12287839a050SYann Gautier 
12290d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
12307839a050SYann Gautier {
12317839a050SYann Gautier 	uint32_t value;
12320d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
12337839a050SYann Gautier 
12340d21680cSYann Gautier 	if (digbyp) {
12350d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
12360d21680cSYann Gautier 	}
12370d21680cSYann Gautier 
12380d21680cSYann Gautier 	if (bypass || digbyp) {
12390d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
12407839a050SYann Gautier 	}
12417839a050SYann Gautier 
12427839a050SYann Gautier 	/*
12437839a050SYann Gautier 	 * Warning: not recommended to switch directly from "high drive"
12447839a050SYann Gautier 	 * to "medium low drive", and vice-versa.
12457839a050SYann Gautier 	 */
12460d21680cSYann Gautier 	value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
12477839a050SYann Gautier 		RCC_BDCR_LSEDRV_SHIFT;
12487839a050SYann Gautier 
12497839a050SYann Gautier 	while (value != lsedrv) {
12507839a050SYann Gautier 		if (value > lsedrv) {
12517839a050SYann Gautier 			value--;
12527839a050SYann Gautier 		} else {
12537839a050SYann Gautier 			value++;
12547839a050SYann Gautier 		}
12557839a050SYann Gautier 
12560d21680cSYann Gautier 		mmio_clrsetbits_32(rcc_base + RCC_BDCR,
12577839a050SYann Gautier 				   RCC_BDCR_LSEDRV_MASK,
12587839a050SYann Gautier 				   value << RCC_BDCR_LSEDRV_SHIFT);
12597839a050SYann Gautier 	}
12607839a050SYann Gautier 
12610d21680cSYann Gautier 	stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
12627839a050SYann Gautier }
12637839a050SYann Gautier 
12640d21680cSYann Gautier static void stm32mp1_lse_wait(void)
12657839a050SYann Gautier {
12660d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
12677839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
12687839a050SYann Gautier 	}
12697839a050SYann Gautier }
12707839a050SYann Gautier 
12710d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable)
12727839a050SYann Gautier {
12730d21680cSYann Gautier 	stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
12740d21680cSYann Gautier 
12750d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
12767839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
12777839a050SYann Gautier 	}
12787839a050SYann Gautier }
12797839a050SYann Gautier 
12800d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
12817839a050SYann Gautier {
12820d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
12830d21680cSYann Gautier 
12840d21680cSYann Gautier 	if (digbyp) {
12850d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
12867839a050SYann Gautier 	}
12877839a050SYann Gautier 
12880d21680cSYann Gautier 	if (bypass || digbyp) {
12890d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
12900d21680cSYann Gautier 	}
12910d21680cSYann Gautier 
12920d21680cSYann Gautier 	stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
12930d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
12947839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
12957839a050SYann Gautier 	}
12967839a050SYann Gautier 
12977839a050SYann Gautier 	if (css) {
12980d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
12997839a050SYann Gautier 	}
13007839a050SYann Gautier }
13017839a050SYann Gautier 
13020d21680cSYann Gautier static void stm32mp1_csi_set(bool enable)
13037839a050SYann Gautier {
13040d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
13050d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
13067839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13077839a050SYann Gautier 	}
13087839a050SYann Gautier }
13097839a050SYann Gautier 
13100d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable)
13117839a050SYann Gautier {
13120d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
13130d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
13147839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13157839a050SYann Gautier 	}
13167839a050SYann Gautier }
13177839a050SYann Gautier 
13180d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv)
13197839a050SYann Gautier {
1320dfdb057aSYann Gautier 	uint64_t timeout;
13210d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13220d21680cSYann Gautier 	uintptr_t address = rcc_base + RCC_OCRDYR;
13237839a050SYann Gautier 
13240d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
13257839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK,
13267839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
13277839a050SYann Gautier 
1328dfdb057aSYann Gautier 	timeout = timeout_init_us(HSIDIV_TIMEOUT);
13297839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
1330dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
13310d21680cSYann Gautier 			ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
13327839a050SYann Gautier 			      address, mmio_read_32(address));
13337839a050SYann Gautier 			return -ETIMEDOUT;
13347839a050SYann Gautier 		}
13357839a050SYann Gautier 	}
13367839a050SYann Gautier 
13377839a050SYann Gautier 	return 0;
13387839a050SYann Gautier }
13397839a050SYann Gautier 
13400d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq)
13417839a050SYann Gautier {
13427839a050SYann Gautier 	uint8_t hsidiv;
13437839a050SYann Gautier 	uint32_t hsidivfreq = MAX_HSI_HZ;
13447839a050SYann Gautier 
13457839a050SYann Gautier 	for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
13467839a050SYann Gautier 		if (hsidivfreq == hsifreq) {
13477839a050SYann Gautier 			break;
13487839a050SYann Gautier 		}
13497839a050SYann Gautier 
13507839a050SYann Gautier 		hsidivfreq /= 2U;
13517839a050SYann Gautier 	}
13527839a050SYann Gautier 
13537839a050SYann Gautier 	if (hsidiv == 4U) {
13547839a050SYann Gautier 		ERROR("Invalid clk-hsi frequency\n");
13557839a050SYann Gautier 		return -1;
13567839a050SYann Gautier 	}
13577839a050SYann Gautier 
13587839a050SYann Gautier 	if (hsidiv != 0U) {
13590d21680cSYann Gautier 		return stm32mp1_set_hsidiv(hsidiv);
13607839a050SYann Gautier 	}
13617839a050SYann Gautier 
13627839a050SYann Gautier 	return 0;
13637839a050SYann Gautier }
13647839a050SYann Gautier 
13650d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
13660d21680cSYann Gautier 				    unsigned int clksrc,
13670d21680cSYann Gautier 				    uint32_t *pllcfg, int plloff)
13687839a050SYann Gautier {
13690d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
13700d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13710d21680cSYann Gautier 	uintptr_t pllxcr = rcc_base + pll->pllxcr;
13720d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
13730d21680cSYann Gautier 	uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
13740d21680cSYann Gautier 	unsigned long refclk;
13750d21680cSYann Gautier 	uint32_t ifrge = 0U;
1376be858cffSAndre Przywara 	uint32_t src, value, fracv = 0;
1377be858cffSAndre Przywara 	void *fdt;
13787839a050SYann Gautier 
13790d21680cSYann Gautier 	/* Check PLL output */
13800d21680cSYann Gautier 	if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
13810d21680cSYann Gautier 		return false;
13827839a050SYann Gautier 	}
13837839a050SYann Gautier 
13840d21680cSYann Gautier 	/* Check current clksrc */
13850d21680cSYann Gautier 	src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
13860d21680cSYann Gautier 	if (src != (clksrc & RCC_SELR_SRC_MASK)) {
13870d21680cSYann Gautier 		return false;
13880d21680cSYann Gautier 	}
13890d21680cSYann Gautier 
13900d21680cSYann Gautier 	/* Check Div */
13910d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
13920d21680cSYann Gautier 
13930d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
13940d21680cSYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
13950d21680cSYann Gautier 
13960d21680cSYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
13970d21680cSYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
13980d21680cSYann Gautier 		return false;
13990d21680cSYann Gautier 	}
14000d21680cSYann Gautier 
14010d21680cSYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
14020d21680cSYann Gautier 		ifrge = 1U;
14030d21680cSYann Gautier 	}
14040d21680cSYann Gautier 
14050d21680cSYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
14060d21680cSYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
14070d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
14080d21680cSYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
14090d21680cSYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
14100d21680cSYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
14110d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
14120d21680cSYann Gautier 		return false;
14130d21680cSYann Gautier 	}
14140d21680cSYann Gautier 
14150d21680cSYann Gautier 	/* Fractional configuration */
1416be858cffSAndre Przywara 	if (fdt_get_address(&fdt) == 1) {
1417be858cffSAndre Przywara 		fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1418be858cffSAndre Przywara 	}
14190d21680cSYann Gautier 
14200d21680cSYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
14210d21680cSYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
14220d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
14230d21680cSYann Gautier 		return false;
14240d21680cSYann Gautier 	}
14250d21680cSYann Gautier 
14260d21680cSYann Gautier 	/* Output config */
14270d21680cSYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
14280d21680cSYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
14290d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
14300d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
14310d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
14320d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
14330d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
14340d21680cSYann Gautier 		return false;
14350d21680cSYann Gautier 	}
14360d21680cSYann Gautier 
14370d21680cSYann Gautier 	return true;
14380d21680cSYann Gautier }
14390d21680cSYann Gautier 
14400d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
14417839a050SYann Gautier {
14420d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
14430d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
14440d21680cSYann Gautier 
1445dd98aec8SYann Gautier 	/* Preserve RCC_PLLNCR_SSCG_CTRL value */
1446dd98aec8SYann Gautier 	mmio_clrsetbits_32(pllxcr,
1447dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1448dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVREN,
1449dd98aec8SYann Gautier 			   RCC_PLLNCR_PLLON);
14500d21680cSYann Gautier }
14510d21680cSYann Gautier 
14520d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
14530d21680cSYann Gautier {
14540d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
14550d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1456dfdb057aSYann Gautier 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
14577839a050SYann Gautier 
14587839a050SYann Gautier 	/* Wait PLL lock */
14597839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
1460dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
14610d21680cSYann Gautier 			ERROR("PLL%d start failed @ 0x%lx: 0x%x\n",
14627839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
14637839a050SYann Gautier 			return -ETIMEDOUT;
14647839a050SYann Gautier 		}
14657839a050SYann Gautier 	}
14667839a050SYann Gautier 
14677839a050SYann Gautier 	/* Start the requested output */
14687839a050SYann Gautier 	mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
14697839a050SYann Gautier 
14707839a050SYann Gautier 	return 0;
14717839a050SYann Gautier }
14727839a050SYann Gautier 
14730d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
14747839a050SYann Gautier {
14750d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
14760d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1477dfdb057aSYann Gautier 	uint64_t timeout;
14787839a050SYann Gautier 
14797839a050SYann Gautier 	/* Stop all output */
14807839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
14817839a050SYann Gautier 			RCC_PLLNCR_DIVREN);
14827839a050SYann Gautier 
14837839a050SYann Gautier 	/* Stop PLL */
14847839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
14857839a050SYann Gautier 
1486dfdb057aSYann Gautier 	timeout = timeout_init_us(PLLRDY_TIMEOUT);
14877839a050SYann Gautier 	/* Wait PLL stopped */
14887839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
1489dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
14900d21680cSYann Gautier 			ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
14917839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
14927839a050SYann Gautier 			return -ETIMEDOUT;
14937839a050SYann Gautier 		}
14947839a050SYann Gautier 	}
14957839a050SYann Gautier 
14967839a050SYann Gautier 	return 0;
14977839a050SYann Gautier }
14987839a050SYann Gautier 
14990d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
15007839a050SYann Gautier 				       uint32_t *pllcfg)
15017839a050SYann Gautier {
15020d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15030d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
15047839a050SYann Gautier 	uint32_t value;
15057839a050SYann Gautier 
15067839a050SYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
15077839a050SYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
15087839a050SYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
15097839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
15107839a050SYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
15117839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
15120d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr2, value);
15137839a050SYann Gautier }
15147839a050SYann Gautier 
15150d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
15167839a050SYann Gautier 			       uint32_t *pllcfg, uint32_t fracv)
15177839a050SYann Gautier {
15180d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15190d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
15200d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
15217839a050SYann Gautier 	unsigned long refclk;
15227839a050SYann Gautier 	uint32_t ifrge = 0;
15237839a050SYann Gautier 	uint32_t src, value;
15247839a050SYann Gautier 
15250d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) &
15267839a050SYann Gautier 		RCC_SELR_REFCLK_SRC_MASK;
15277839a050SYann Gautier 
15280d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
15297839a050SYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
15307839a050SYann Gautier 
15317839a050SYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
15327839a050SYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
15337839a050SYann Gautier 		return -EINVAL;
15347839a050SYann Gautier 	}
15357839a050SYann Gautier 
15367839a050SYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
15377839a050SYann Gautier 		ifrge = 1U;
15387839a050SYann Gautier 	}
15397839a050SYann Gautier 
15407839a050SYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
15417839a050SYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
15427839a050SYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
15437839a050SYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
15447839a050SYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
15457839a050SYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
15460d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr1, value);
15477839a050SYann Gautier 
15487839a050SYann Gautier 	/* Fractional configuration */
15497839a050SYann Gautier 	value = 0;
15500d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
15517839a050SYann Gautier 
15527839a050SYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
15530d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
15547839a050SYann Gautier 
15557839a050SYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
15560d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
15577839a050SYann Gautier 
15580d21680cSYann Gautier 	stm32mp1_pll_config_output(pll_id, pllcfg);
15597839a050SYann Gautier 
15607839a050SYann Gautier 	return 0;
15617839a050SYann Gautier }
15627839a050SYann Gautier 
15630d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
15647839a050SYann Gautier {
15650d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15667839a050SYann Gautier 	uint32_t pllxcsg = 0;
15677839a050SYann Gautier 
15687839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
15697839a050SYann Gautier 		    RCC_PLLNCSGR_MOD_PER_MASK;
15707839a050SYann Gautier 
15717839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
15727839a050SYann Gautier 		    RCC_PLLNCSGR_INC_STEP_MASK;
15737839a050SYann Gautier 
15747839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
15757839a050SYann Gautier 		    RCC_PLLNCSGR_SSCG_MODE_MASK;
15767839a050SYann Gautier 
15770d21680cSYann Gautier 	mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
1578dd98aec8SYann Gautier 
1579dd98aec8SYann Gautier 	mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
1580dd98aec8SYann Gautier 			RCC_PLLNCR_SSCG_CTRL);
15817839a050SYann Gautier }
15827839a050SYann Gautier 
15830d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc)
15847839a050SYann Gautier {
15850d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
1586dfdb057aSYann Gautier 	uint64_t timeout;
15877839a050SYann Gautier 
15880d21680cSYann Gautier 	mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
15897839a050SYann Gautier 			   clksrc & RCC_SELR_SRC_MASK);
15907839a050SYann Gautier 
1591dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
15920d21680cSYann Gautier 	while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
1593dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
15940d21680cSYann Gautier 			ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
15950d21680cSYann Gautier 			      clksrc_address, mmio_read_32(clksrc_address));
15967839a050SYann Gautier 			return -ETIMEDOUT;
15977839a050SYann Gautier 		}
15987839a050SYann Gautier 	}
15997839a050SYann Gautier 
16007839a050SYann Gautier 	return 0;
16017839a050SYann Gautier }
16027839a050SYann Gautier 
16030d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
16047839a050SYann Gautier {
1605dfdb057aSYann Gautier 	uint64_t timeout;
16067839a050SYann Gautier 
16077839a050SYann Gautier 	mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
16087839a050SYann Gautier 			   clkdiv & RCC_DIVR_DIV_MASK);
16097839a050SYann Gautier 
1610dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
16117839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
1612dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
16130d21680cSYann Gautier 			ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
16147839a050SYann Gautier 			      clkdiv, address, mmio_read_32(address));
16157839a050SYann Gautier 			return -ETIMEDOUT;
16167839a050SYann Gautier 		}
16177839a050SYann Gautier 	}
16187839a050SYann Gautier 
16197839a050SYann Gautier 	return 0;
16207839a050SYann Gautier }
16217839a050SYann Gautier 
16220d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
16237839a050SYann Gautier {
16240d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
16257839a050SYann Gautier 
16267839a050SYann Gautier 	/*
16277839a050SYann Gautier 	 * Binding clksrc :
16287839a050SYann Gautier 	 *      bit15-4 offset
16297839a050SYann Gautier 	 *      bit3:   disable
16307839a050SYann Gautier 	 *      bit2-0: MCOSEL[2:0]
16317839a050SYann Gautier 	 */
16327839a050SYann Gautier 	if ((clksrc & 0x8U) != 0U) {
16330d21680cSYann Gautier 		mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
16347839a050SYann Gautier 	} else {
16350d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
16367839a050SYann Gautier 				   RCC_MCOCFG_MCOSRC_MASK,
16377839a050SYann Gautier 				   clksrc & RCC_MCOCFG_MCOSRC_MASK);
16380d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
16397839a050SYann Gautier 				   RCC_MCOCFG_MCODIV_MASK,
16407839a050SYann Gautier 				   clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
16410d21680cSYann Gautier 		mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
16427839a050SYann Gautier 	}
16437839a050SYann Gautier }
16447839a050SYann Gautier 
16450d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
16467839a050SYann Gautier {
16470d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
16487839a050SYann Gautier 
16497839a050SYann Gautier 	if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
16507839a050SYann Gautier 	    (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
16517839a050SYann Gautier 		mmio_clrsetbits_32(address,
16527839a050SYann Gautier 				   RCC_BDCR_RTCSRC_MASK,
16537839a050SYann Gautier 				   clksrc << RCC_BDCR_RTCSRC_SHIFT);
16547839a050SYann Gautier 
16557839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
16567839a050SYann Gautier 	}
16577839a050SYann Gautier 
16587839a050SYann Gautier 	if (lse_css) {
16597839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_LSECSSON);
16607839a050SYann Gautier 	}
16617839a050SYann Gautier }
16627839a050SYann Gautier 
16630d21680cSYann Gautier static void stm32mp1_stgen_config(void)
16647839a050SYann Gautier {
16657839a050SYann Gautier 	uintptr_t stgen;
16667839a050SYann Gautier 	uint32_t cntfid0;
16677839a050SYann Gautier 	unsigned long rate;
16687839a050SYann Gautier 	unsigned long long counter;
16697839a050SYann Gautier 
16700d21680cSYann Gautier 	stgen = fdt_get_stgen_base();
16710d21680cSYann Gautier 	cntfid0 = mmio_read_32(stgen + CNTFID_OFF);
16720d21680cSYann Gautier 	rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K));
16730d21680cSYann Gautier 
16740d21680cSYann Gautier 	if (cntfid0 == rate) {
16750d21680cSYann Gautier 		return;
16760d21680cSYann Gautier 	}
16770d21680cSYann Gautier 
16787839a050SYann Gautier 	mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
16790d21680cSYann Gautier 	counter = (unsigned long long)mmio_read_32(stgen + CNTCVL_OFF);
16800d21680cSYann Gautier 	counter |= ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF)) << 32;
16817839a050SYann Gautier 	counter = (counter * rate / cntfid0);
16820d21680cSYann Gautier 
16837839a050SYann Gautier 	mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter);
16847839a050SYann Gautier 	mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32));
16857839a050SYann Gautier 	mmio_write_32(stgen + CNTFID_OFF, rate);
16867839a050SYann Gautier 	mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
16877839a050SYann Gautier 
16887839a050SYann Gautier 	write_cntfrq((u_register_t)rate);
16897839a050SYann Gautier 
16907839a050SYann Gautier 	/* Need to update timer with new frequency */
16917839a050SYann Gautier 	generic_delay_timer_init();
16927839a050SYann Gautier }
16937839a050SYann Gautier 
16947839a050SYann Gautier void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
16957839a050SYann Gautier {
16967839a050SYann Gautier 	uintptr_t stgen;
16977839a050SYann Gautier 	unsigned long long cnt;
16987839a050SYann Gautier 
16997839a050SYann Gautier 	stgen = fdt_get_stgen_base();
17007839a050SYann Gautier 
17017839a050SYann Gautier 	cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
17027839a050SYann Gautier 		mmio_read_32(stgen + CNTCVL_OFF);
17037839a050SYann Gautier 
17047839a050SYann Gautier 	cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U;
17057839a050SYann Gautier 
17067839a050SYann Gautier 	mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
17077839a050SYann Gautier 	mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt);
17087839a050SYann Gautier 	mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(cnt >> 32));
17097839a050SYann Gautier 	mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
17107839a050SYann Gautier }
17117839a050SYann Gautier 
17120d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs)
17137839a050SYann Gautier {
17140d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
17157839a050SYann Gautier 	uint32_t value = pkcs & 0xFU;
17167839a050SYann Gautier 	uint32_t mask = 0xFU;
17177839a050SYann Gautier 
17187839a050SYann Gautier 	if ((pkcs & BIT(31)) != 0U) {
17197839a050SYann Gautier 		mask <<= 4;
17207839a050SYann Gautier 		value <<= 4;
17217839a050SYann Gautier 	}
17227839a050SYann Gautier 
17237839a050SYann Gautier 	mmio_clrsetbits_32(address, mask, value);
17247839a050SYann Gautier }
17257839a050SYann Gautier 
17267839a050SYann Gautier int stm32mp1_clk_init(void)
17277839a050SYann Gautier {
17280d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
17297839a050SYann Gautier 	unsigned int clksrc[CLKSRC_NB];
17307839a050SYann Gautier 	unsigned int clkdiv[CLKDIV_NB];
17317839a050SYann Gautier 	unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
17327839a050SYann Gautier 	int plloff[_PLL_NB];
17337839a050SYann Gautier 	int ret, len;
17347839a050SYann Gautier 	enum stm32mp1_pll_id i;
17357839a050SYann Gautier 	bool lse_css = false;
17360d21680cSYann Gautier 	bool pll3_preserve = false;
17370d21680cSYann Gautier 	bool pll4_preserve = false;
17380d21680cSYann Gautier 	bool pll4_bootrom = false;
17393e6fab43SYann Gautier 	const fdt32_t *pkcs_cell;
174052a616b4SAndre Przywara 	void *fdt;
174152a616b4SAndre Przywara 
174252a616b4SAndre Przywara 	if (fdt_get_address(&fdt) == 0) {
174352a616b4SAndre Przywara 		return false;
174452a616b4SAndre Przywara 	}
17457839a050SYann Gautier 
17467839a050SYann Gautier 	/* Check status field to disable security */
17477839a050SYann Gautier 	if (!fdt_get_rcc_secure_status()) {
17480d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_TZCR, 0);
17497839a050SYann Gautier 	}
17507839a050SYann Gautier 
175152a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
175252a616b4SAndre Przywara 					clksrc);
17537839a050SYann Gautier 	if (ret < 0) {
17547839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
17557839a050SYann Gautier 	}
17567839a050SYann Gautier 
175752a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
175852a616b4SAndre Przywara 					clkdiv);
17597839a050SYann Gautier 	if (ret < 0) {
17607839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
17617839a050SYann Gautier 	}
17627839a050SYann Gautier 
17637839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
17647839a050SYann Gautier 		char name[12];
17657839a050SYann Gautier 
176639b6cc66SAntonio Nino Diaz 		snprintf(name, sizeof(name), "st,pll@%d", i);
17677839a050SYann Gautier 		plloff[i] = fdt_rcc_subnode_offset(name);
17687839a050SYann Gautier 
17697839a050SYann Gautier 		if (!fdt_check_node(plloff[i])) {
17707839a050SYann Gautier 			continue;
17717839a050SYann Gautier 		}
17727839a050SYann Gautier 
177352a616b4SAndre Przywara 		ret = fdt_read_uint32_array(fdt, plloff[i], "cfg",
177452a616b4SAndre Przywara 					    (int)PLLCFG_NB, pllcfg[i]);
17757839a050SYann Gautier 		if (ret < 0) {
17767839a050SYann Gautier 			return -FDT_ERR_NOTFOUND;
17777839a050SYann Gautier 		}
17787839a050SYann Gautier 	}
17797839a050SYann Gautier 
17800d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
17810d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
17827839a050SYann Gautier 
17837839a050SYann Gautier 	/*
17847839a050SYann Gautier 	 * Switch ON oscillator found in device-tree.
17857839a050SYann Gautier 	 * Note: HSI already ON after BootROM stage.
17867839a050SYann Gautier 	 */
17870d21680cSYann Gautier 	if (stm32mp1_osc[_LSI] != 0U) {
17880d21680cSYann Gautier 		stm32mp1_lsi_set(true);
17897839a050SYann Gautier 	}
17900d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
17910d21680cSYann Gautier 		bool bypass, digbyp;
17927839a050SYann Gautier 		uint32_t lsedrv;
17937839a050SYann Gautier 
17947839a050SYann Gautier 		bypass = fdt_osc_read_bool(_LSE, "st,bypass");
17950d21680cSYann Gautier 		digbyp = fdt_osc_read_bool(_LSE, "st,digbypass");
17967839a050SYann Gautier 		lse_css = fdt_osc_read_bool(_LSE, "st,css");
17977839a050SYann Gautier 		lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive",
17987839a050SYann Gautier 						     LSEDRV_MEDIUM_HIGH);
17990d21680cSYann Gautier 		stm32mp1_lse_enable(bypass, digbyp, lsedrv);
18007839a050SYann Gautier 	}
18010d21680cSYann Gautier 	if (stm32mp1_osc[_HSE] != 0U) {
18020d21680cSYann Gautier 		bool bypass, digbyp, css;
18037839a050SYann Gautier 
18040d21680cSYann Gautier 		bypass = fdt_osc_read_bool(_HSE, "st,bypass");
18050d21680cSYann Gautier 		digbyp = fdt_osc_read_bool(_HSE, "st,digbypass");
18060d21680cSYann Gautier 		css = fdt_osc_read_bool(_HSE, "st,css");
18070d21680cSYann Gautier 		stm32mp1_hse_enable(bypass, digbyp, css);
18087839a050SYann Gautier 	}
18097839a050SYann Gautier 	/*
18107839a050SYann Gautier 	 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
18117839a050SYann Gautier 	 * => switch on CSI even if node is not present in device tree
18127839a050SYann Gautier 	 */
18130d21680cSYann Gautier 	stm32mp1_csi_set(true);
18147839a050SYann Gautier 
18157839a050SYann Gautier 	/* Come back to HSI */
18160d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
18177839a050SYann Gautier 	if (ret != 0) {
18187839a050SYann Gautier 		return ret;
18197839a050SYann Gautier 	}
18200d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
18217839a050SYann Gautier 	if (ret != 0) {
18227839a050SYann Gautier 		return ret;
18237839a050SYann Gautier 	}
1824b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
1825b053a22eSYann Gautier 	if (ret != 0) {
1826b053a22eSYann Gautier 		return ret;
1827b053a22eSYann Gautier 	}
18287839a050SYann Gautier 
18290d21680cSYann Gautier 	if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
18300d21680cSYann Gautier 	     RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
18310d21680cSYann Gautier 		pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
18320d21680cSYann Gautier 							clksrc[CLKSRC_PLL3],
18330d21680cSYann Gautier 							pllcfg[_PLL3],
18340d21680cSYann Gautier 							plloff[_PLL3]);
18350d21680cSYann Gautier 		pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
18360d21680cSYann Gautier 							clksrc[CLKSRC_PLL4],
18370d21680cSYann Gautier 							pllcfg[_PLL4],
18380d21680cSYann Gautier 							plloff[_PLL4]);
18390d21680cSYann Gautier 	}
18400d21680cSYann Gautier 
18417839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
18420d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
18430d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve)) {
18447839a050SYann Gautier 			continue;
18450d21680cSYann Gautier 		}
18460d21680cSYann Gautier 
18470d21680cSYann Gautier 		ret = stm32mp1_pll_stop(i);
18487839a050SYann Gautier 		if (ret != 0) {
18497839a050SYann Gautier 			return ret;
18507839a050SYann Gautier 		}
18517839a050SYann Gautier 	}
18527839a050SYann Gautier 
18537839a050SYann Gautier 	/* Configure HSIDIV */
18540d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] != 0U) {
18550d21680cSYann Gautier 		ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
18567839a050SYann Gautier 		if (ret != 0) {
18577839a050SYann Gautier 			return ret;
18587839a050SYann Gautier 		}
18590d21680cSYann Gautier 		stm32mp1_stgen_config();
18607839a050SYann Gautier 	}
18617839a050SYann Gautier 
18627839a050SYann Gautier 	/* Select DIV */
18637839a050SYann Gautier 	/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
18640d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_MPCKDIVR,
18657839a050SYann Gautier 		      clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
18660d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
18677839a050SYann Gautier 	if (ret != 0) {
18687839a050SYann Gautier 		return ret;
18697839a050SYann Gautier 	}
18700d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
18717839a050SYann Gautier 	if (ret != 0) {
18727839a050SYann Gautier 		return ret;
18737839a050SYann Gautier 	}
18740d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
18757839a050SYann Gautier 	if (ret != 0) {
18767839a050SYann Gautier 		return ret;
18777839a050SYann Gautier 	}
1878b053a22eSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
1879b053a22eSYann Gautier 	if (ret != 0) {
1880b053a22eSYann Gautier 		return ret;
1881b053a22eSYann Gautier 	}
18820d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
18837839a050SYann Gautier 	if (ret != 0) {
18847839a050SYann Gautier 		return ret;
18857839a050SYann Gautier 	}
18860d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
18877839a050SYann Gautier 	if (ret != 0) {
18887839a050SYann Gautier 		return ret;
18897839a050SYann Gautier 	}
18900d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
18917839a050SYann Gautier 	if (ret != 0) {
18927839a050SYann Gautier 		return ret;
18937839a050SYann Gautier 	}
18947839a050SYann Gautier 
18957839a050SYann Gautier 	/* No ready bit for RTC */
18960d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_RTCDIVR,
18977839a050SYann Gautier 		      clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
18987839a050SYann Gautier 
18997839a050SYann Gautier 	/* Configure PLLs source */
19000d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
19017839a050SYann Gautier 	if (ret != 0) {
19027839a050SYann Gautier 		return ret;
19037839a050SYann Gautier 	}
19047839a050SYann Gautier 
19050d21680cSYann Gautier 	if (!pll3_preserve) {
19060d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
19077839a050SYann Gautier 		if (ret != 0) {
19087839a050SYann Gautier 			return ret;
19097839a050SYann Gautier 		}
19100d21680cSYann Gautier 	}
19110d21680cSYann Gautier 
19120d21680cSYann Gautier 	if (!pll4_preserve) {
19130d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
19140d21680cSYann Gautier 		if (ret != 0) {
19150d21680cSYann Gautier 			return ret;
19160d21680cSYann Gautier 		}
19170d21680cSYann Gautier 	}
19187839a050SYann Gautier 
19197839a050SYann Gautier 	/* Configure and start PLLs */
19207839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
19217839a050SYann Gautier 		uint32_t fracv;
19227839a050SYann Gautier 		uint32_t csg[PLLCSG_NB];
19237839a050SYann Gautier 
19240d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
19250d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
19260d21680cSYann Gautier 			continue;
19270d21680cSYann Gautier 		}
19280d21680cSYann Gautier 
19297839a050SYann Gautier 		if (!fdt_check_node(plloff[i])) {
19307839a050SYann Gautier 			continue;
19317839a050SYann Gautier 		}
19327839a050SYann Gautier 
19330d21680cSYann Gautier 		if ((i == _PLL4) && pll4_bootrom) {
19340d21680cSYann Gautier 			/* Set output divider if not done by the Bootrom */
19350d21680cSYann Gautier 			stm32mp1_pll_config_output(i, pllcfg[i]);
19360d21680cSYann Gautier 			continue;
19370d21680cSYann Gautier 		}
19380d21680cSYann Gautier 
1939be858cffSAndre Przywara 		fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0);
19407839a050SYann Gautier 
19410d21680cSYann Gautier 		ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
19427839a050SYann Gautier 		if (ret != 0) {
19437839a050SYann Gautier 			return ret;
19447839a050SYann Gautier 		}
194552a616b4SAndre Przywara 		ret = fdt_read_uint32_array(fdt, plloff[i], "csg",
194652a616b4SAndre Przywara 					    (uint32_t)PLLCSG_NB, csg);
19477839a050SYann Gautier 		if (ret == 0) {
19480d21680cSYann Gautier 			stm32mp1_pll_csg(i, csg);
19497839a050SYann Gautier 		} else if (ret != -FDT_ERR_NOTFOUND) {
19507839a050SYann Gautier 			return ret;
19517839a050SYann Gautier 		}
19527839a050SYann Gautier 
19530d21680cSYann Gautier 		stm32mp1_pll_start(i);
19547839a050SYann Gautier 	}
19557839a050SYann Gautier 	/* Wait and start PLLs ouptut when ready */
19567839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
19577839a050SYann Gautier 		if (!fdt_check_node(plloff[i])) {
19587839a050SYann Gautier 			continue;
19597839a050SYann Gautier 		}
19607839a050SYann Gautier 
19610d21680cSYann Gautier 		ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
19627839a050SYann Gautier 		if (ret != 0) {
19637839a050SYann Gautier 			return ret;
19647839a050SYann Gautier 		}
19657839a050SYann Gautier 	}
19667839a050SYann Gautier 	/* Wait LSE ready before to use it */
19670d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
19680d21680cSYann Gautier 		stm32mp1_lse_wait();
19697839a050SYann Gautier 	}
19707839a050SYann Gautier 
19717839a050SYann Gautier 	/* Configure with expected clock source */
19720d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
19737839a050SYann Gautier 	if (ret != 0) {
19747839a050SYann Gautier 		return ret;
19757839a050SYann Gautier 	}
19760d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
19777839a050SYann Gautier 	if (ret != 0) {
19787839a050SYann Gautier 		return ret;
19797839a050SYann Gautier 	}
1980b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
1981b053a22eSYann Gautier 	if (ret != 0) {
1982b053a22eSYann Gautier 		return ret;
1983b053a22eSYann Gautier 	}
19840d21680cSYann Gautier 	stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
19857839a050SYann Gautier 
19867839a050SYann Gautier 	/* Configure PKCK */
19877839a050SYann Gautier 	pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
19887839a050SYann Gautier 	if (pkcs_cell != NULL) {
19897839a050SYann Gautier 		bool ckper_disabled = false;
19907839a050SYann Gautier 		uint32_t j;
19917839a050SYann Gautier 
19927839a050SYann Gautier 		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
19933e6fab43SYann Gautier 			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
19947839a050SYann Gautier 
19957839a050SYann Gautier 			if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
19967839a050SYann Gautier 				ckper_disabled = true;
19977839a050SYann Gautier 				continue;
19987839a050SYann Gautier 			}
19990d21680cSYann Gautier 			stm32mp1_pkcs_config(pkcs);
20007839a050SYann Gautier 		}
20017839a050SYann Gautier 
20027839a050SYann Gautier 		/*
20037839a050SYann Gautier 		 * CKPER is source for some peripheral clocks
20047839a050SYann Gautier 		 * (FMC-NAND / QPSI-NOR) and switching source is allowed
20057839a050SYann Gautier 		 * only if previous clock is still ON
20067839a050SYann Gautier 		 * => deactivated CKPER only after switching clock
20077839a050SYann Gautier 		 */
20087839a050SYann Gautier 		if (ckper_disabled) {
20090d21680cSYann Gautier 			stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
20107839a050SYann Gautier 		}
20117839a050SYann Gautier 	}
20127839a050SYann Gautier 
20137839a050SYann Gautier 	/* Switch OFF HSI if not found in device-tree */
20140d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] == 0U) {
20150d21680cSYann Gautier 		stm32mp1_hsi_set(false);
20167839a050SYann Gautier 	}
20170d21680cSYann Gautier 	stm32mp1_stgen_config();
20187839a050SYann Gautier 
20197839a050SYann Gautier 	/* Software Self-Refresh mode (SSR) during DDR initilialization */
20200d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
20217839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_MASK,
20227839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SSR <<
20237839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SHIFT);
20247839a050SYann Gautier 
20257839a050SYann Gautier 	return 0;
20267839a050SYann Gautier }
20277839a050SYann Gautier 
20287839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name,
20297839a050SYann Gautier 				  enum stm32mp_osc_id index)
20307839a050SYann Gautier {
20317839a050SYann Gautier 	uint32_t frequency;
20327839a050SYann Gautier 
20330d21680cSYann Gautier 	if (fdt_osc_read_freq(name, &frequency) == 0) {
20340d21680cSYann Gautier 		stm32mp1_osc[index] = frequency;
20357839a050SYann Gautier 	}
20367839a050SYann Gautier }
20377839a050SYann Gautier 
20387839a050SYann Gautier static void stm32mp1_osc_init(void)
20397839a050SYann Gautier {
20407839a050SYann Gautier 	enum stm32mp_osc_id i;
20417839a050SYann Gautier 
20427839a050SYann Gautier 	for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
20430d21680cSYann Gautier 		stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
20447839a050SYann Gautier 	}
20457839a050SYann Gautier }
20467839a050SYann Gautier 
2047*37e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES
2048*37e8295aSEtienne Carriere /*
2049*37e8295aSEtienne Carriere  * Get the parent ID of the target parent clock, for tagging as secure
2050*37e8295aSEtienne Carriere  * shared clock dependencies.
2051*37e8295aSEtienne Carriere  */
2052*37e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id)
2053*37e8295aSEtienne Carriere {
2054*37e8295aSEtienne Carriere 	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
2055*37e8295aSEtienne Carriere 	enum stm32mp1_pll_id pll_id;
2056*37e8295aSEtienne Carriere 	uint32_t p_sel;
2057*37e8295aSEtienne Carriere 	uintptr_t rcc_base = stm32mp_rcc_base();
2058*37e8295aSEtienne Carriere 
2059*37e8295aSEtienne Carriere 	switch (parent_id) {
2060*37e8295aSEtienne Carriere 	case _ACLK:
2061*37e8295aSEtienne Carriere 	case _PCLK4:
2062*37e8295aSEtienne Carriere 	case _PCLK5:
2063*37e8295aSEtienne Carriere 		s = _AXIS_SEL;
2064*37e8295aSEtienne Carriere 		break;
2065*37e8295aSEtienne Carriere 	case _PLL1_P:
2066*37e8295aSEtienne Carriere 	case _PLL1_Q:
2067*37e8295aSEtienne Carriere 	case _PLL1_R:
2068*37e8295aSEtienne Carriere 		pll_id = _PLL1;
2069*37e8295aSEtienne Carriere 		break;
2070*37e8295aSEtienne Carriere 	case _PLL2_P:
2071*37e8295aSEtienne Carriere 	case _PLL2_Q:
2072*37e8295aSEtienne Carriere 	case _PLL2_R:
2073*37e8295aSEtienne Carriere 		pll_id = _PLL2;
2074*37e8295aSEtienne Carriere 		break;
2075*37e8295aSEtienne Carriere 	case _PLL3_P:
2076*37e8295aSEtienne Carriere 	case _PLL3_Q:
2077*37e8295aSEtienne Carriere 	case _PLL3_R:
2078*37e8295aSEtienne Carriere 		pll_id = _PLL3;
2079*37e8295aSEtienne Carriere 		break;
2080*37e8295aSEtienne Carriere 	case _PLL4_P:
2081*37e8295aSEtienne Carriere 	case _PLL4_Q:
2082*37e8295aSEtienne Carriere 	case _PLL4_R:
2083*37e8295aSEtienne Carriere 		pll_id = _PLL4;
2084*37e8295aSEtienne Carriere 		break;
2085*37e8295aSEtienne Carriere 	case _PCLK1:
2086*37e8295aSEtienne Carriere 	case _PCLK2:
2087*37e8295aSEtienne Carriere 	case _HCLK2:
2088*37e8295aSEtienne Carriere 	case _HCLK6:
2089*37e8295aSEtienne Carriere 	case _CK_PER:
2090*37e8295aSEtienne Carriere 	case _CK_MPU:
2091*37e8295aSEtienne Carriere 	case _CK_MCU:
2092*37e8295aSEtienne Carriere 	case _USB_PHY_48:
2093*37e8295aSEtienne Carriere 		/* We do not expect to access these */
2094*37e8295aSEtienne Carriere 		panic();
2095*37e8295aSEtienne Carriere 		break;
2096*37e8295aSEtienne Carriere 	default:
2097*37e8295aSEtienne Carriere 		/* Other parents have no parent */
2098*37e8295aSEtienne Carriere 		return -1;
2099*37e8295aSEtienne Carriere 	}
2100*37e8295aSEtienne Carriere 
2101*37e8295aSEtienne Carriere 	if (s != _UNKNOWN_SEL) {
2102*37e8295aSEtienne Carriere 		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
2103*37e8295aSEtienne Carriere 
2104*37e8295aSEtienne Carriere 		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
2105*37e8295aSEtienne Carriere 			sel->msk;
2106*37e8295aSEtienne Carriere 
2107*37e8295aSEtienne Carriere 		if (p_sel < sel->nb_parent) {
2108*37e8295aSEtienne Carriere 			return (int)sel->parent[p_sel];
2109*37e8295aSEtienne Carriere 		}
2110*37e8295aSEtienne Carriere 	} else {
2111*37e8295aSEtienne Carriere 		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
2112*37e8295aSEtienne Carriere 
2113*37e8295aSEtienne Carriere 		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
2114*37e8295aSEtienne Carriere 			RCC_SELR_REFCLK_SRC_MASK;
2115*37e8295aSEtienne Carriere 
2116*37e8295aSEtienne Carriere 		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
2117*37e8295aSEtienne Carriere 			return (int)pll->refclk[p_sel];
2118*37e8295aSEtienne Carriere 		}
2119*37e8295aSEtienne Carriere 	}
2120*37e8295aSEtienne Carriere 
2121*37e8295aSEtienne Carriere 	VERBOSE("No parent selected for %s\n",
2122*37e8295aSEtienne Carriere 		stm32mp1_clk_parent_name[parent_id]);
2123*37e8295aSEtienne Carriere 
2124*37e8295aSEtienne Carriere 	return -1;
2125*37e8295aSEtienne Carriere }
2126*37e8295aSEtienne Carriere 
2127*37e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id)
2128*37e8295aSEtienne Carriere {
2129*37e8295aSEtienne Carriere 	int grandparent_id;
2130*37e8295aSEtienne Carriere 
2131*37e8295aSEtienne Carriere 	switch (parent_id) {
2132*37e8295aSEtienne Carriere 	case _PLL3_P:
2133*37e8295aSEtienne Carriere 	case _PLL3_Q:
2134*37e8295aSEtienne Carriere 	case _PLL3_R:
2135*37e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
2136*37e8295aSEtienne Carriere 		break;
2137*37e8295aSEtienne Carriere 
2138*37e8295aSEtienne Carriere 	/* These clocks are always secure when RCC is secure */
2139*37e8295aSEtienne Carriere 	case _ACLK:
2140*37e8295aSEtienne Carriere 	case _HCLK2:
2141*37e8295aSEtienne Carriere 	case _HCLK6:
2142*37e8295aSEtienne Carriere 	case _PCLK4:
2143*37e8295aSEtienne Carriere 	case _PCLK5:
2144*37e8295aSEtienne Carriere 	case _PLL1_P:
2145*37e8295aSEtienne Carriere 	case _PLL1_Q:
2146*37e8295aSEtienne Carriere 	case _PLL1_R:
2147*37e8295aSEtienne Carriere 	case _PLL2_P:
2148*37e8295aSEtienne Carriere 	case _PLL2_Q:
2149*37e8295aSEtienne Carriere 	case _PLL2_R:
2150*37e8295aSEtienne Carriere 	case _HSI:
2151*37e8295aSEtienne Carriere 	case _HSI_KER:
2152*37e8295aSEtienne Carriere 	case _LSI:
2153*37e8295aSEtienne Carriere 	case _CSI:
2154*37e8295aSEtienne Carriere 	case _CSI_KER:
2155*37e8295aSEtienne Carriere 	case _HSE:
2156*37e8295aSEtienne Carriere 	case _HSE_KER:
2157*37e8295aSEtienne Carriere 	case _HSE_KER_DIV2:
2158*37e8295aSEtienne Carriere 	case _LSE:
2159*37e8295aSEtienne Carriere 		break;
2160*37e8295aSEtienne Carriere 
2161*37e8295aSEtienne Carriere 	default:
2162*37e8295aSEtienne Carriere 		VERBOSE("Cannot secure parent clock %s\n",
2163*37e8295aSEtienne Carriere 			stm32mp1_clk_parent_name[parent_id]);
2164*37e8295aSEtienne Carriere 		panic();
2165*37e8295aSEtienne Carriere 	}
2166*37e8295aSEtienne Carriere 
2167*37e8295aSEtienne Carriere 	grandparent_id = get_parent_id_parent(parent_id);
2168*37e8295aSEtienne Carriere 	if (grandparent_id >= 0) {
2169*37e8295aSEtienne Carriere 		secure_parent_clocks(grandparent_id);
2170*37e8295aSEtienne Carriere 	}
2171*37e8295aSEtienne Carriere }
2172*37e8295aSEtienne Carriere 
2173*37e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
2174*37e8295aSEtienne Carriere {
2175*37e8295aSEtienne Carriere 	int parent_id;
2176*37e8295aSEtienne Carriere 
2177*37e8295aSEtienne Carriere 	if (!stm32mp1_rcc_is_secure()) {
2178*37e8295aSEtienne Carriere 		return;
2179*37e8295aSEtienne Carriere 	}
2180*37e8295aSEtienne Carriere 
2181*37e8295aSEtienne Carriere 	switch (clock_id) {
2182*37e8295aSEtienne Carriere 	case PLL1:
2183*37e8295aSEtienne Carriere 	case PLL2:
2184*37e8295aSEtienne Carriere 		/* PLL1/PLL2 are always secure: nothing to do */
2185*37e8295aSEtienne Carriere 		break;
2186*37e8295aSEtienne Carriere 	case PLL3:
2187*37e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
2188*37e8295aSEtienne Carriere 		break;
2189*37e8295aSEtienne Carriere 	case PLL4:
2190*37e8295aSEtienne Carriere 		ERROR("PLL4 cannot be secured\n");
2191*37e8295aSEtienne Carriere 		panic();
2192*37e8295aSEtienne Carriere 		break;
2193*37e8295aSEtienne Carriere 	default:
2194*37e8295aSEtienne Carriere 		/* Others are expected gateable clock */
2195*37e8295aSEtienne Carriere 		parent_id = stm32mp1_clk_get_parent(clock_id);
2196*37e8295aSEtienne Carriere 		if (parent_id < 0) {
2197*37e8295aSEtienne Carriere 			INFO("No parent found for clock %lu\n", clock_id);
2198*37e8295aSEtienne Carriere 		} else {
2199*37e8295aSEtienne Carriere 			secure_parent_clocks(parent_id);
2200*37e8295aSEtienne Carriere 		}
2201*37e8295aSEtienne Carriere 		break;
2202*37e8295aSEtienne Carriere 	}
2203*37e8295aSEtienne Carriere }
2204*37e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */
2205*37e8295aSEtienne Carriere 
22066cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void)
22076cb45f89SYann Gautier {
2208033b6c3aSEtienne Carriere 	unsigned int idx;
2209033b6c3aSEtienne Carriere 	const unsigned long secure_enable[] = {
2210033b6c3aSEtienne Carriere 		AXIDCG,
2211033b6c3aSEtienne Carriere 		BSEC,
2212033b6c3aSEtienne Carriere 		DDRC1, DDRC1LP,
2213033b6c3aSEtienne Carriere 		DDRC2, DDRC2LP,
2214033b6c3aSEtienne Carriere 		DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
2215033b6c3aSEtienne Carriere 		DDRPHYC, DDRPHYCLP,
2216033b6c3aSEtienne Carriere 		TZC1, TZC2,
2217033b6c3aSEtienne Carriere 		TZPC,
2218033b6c3aSEtienne Carriere 		STGEN_K,
2219033b6c3aSEtienne Carriere 	};
2220033b6c3aSEtienne Carriere 
2221033b6c3aSEtienne Carriere 	for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
2222033b6c3aSEtienne Carriere 		stm32mp_clk_enable(secure_enable[idx]);
2223033b6c3aSEtienne Carriere 	}
2224033b6c3aSEtienne Carriere 
22256cb45f89SYann Gautier 	if (!stm32mp_is_single_core()) {
22266cb45f89SYann Gautier 		stm32mp1_clk_enable_secure(RTCAPB);
22276cb45f89SYann Gautier 	}
22286cb45f89SYann Gautier }
22296cb45f89SYann Gautier 
22307839a050SYann Gautier int stm32mp1_clk_probe(void)
22317839a050SYann Gautier {
22327839a050SYann Gautier 	stm32mp1_osc_init();
22337839a050SYann Gautier 
22346cb45f89SYann Gautier 	sync_earlyboot_clocks_state();
22356cb45f89SYann Gautier 
22367839a050SYann Gautier 	return 0;
22377839a050SYann Gautier }
2238