xref: /rk3399_ARM-atf/drivers/st/clk/stm32mp1_clk.c (revision 9fa9a0c55cc830e609415d2cedd2d34fcbec1008)
17839a050SYann Gautier /*
2964e5ff1SNicolas Le Bayon  * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved
37839a050SYann Gautier  *
47839a050SYann Gautier  * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
57839a050SYann Gautier  */
67839a050SYann Gautier 
77839a050SYann Gautier #include <assert.h>
87839a050SYann Gautier #include <errno.h>
97839a050SYann Gautier #include <stdint.h>
1039b6cc66SAntonio Nino Diaz #include <stdio.h>
1109d40e0eSAntonio Nino Diaz 
1209d40e0eSAntonio Nino Diaz #include <arch.h>
1309d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
1409d40e0eSAntonio Nino Diaz #include <common/debug.h>
1552a616b4SAndre Przywara #include <common/fdt_wrappers.h>
1633667d29SYann Gautier #include <drivers/clk.h>
1709d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h>
18447b2b13SYann Gautier #include <drivers/st/stm32mp_clkfunc.h>
1909d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_clk.h>
2009d40e0eSAntonio Nino Diaz #include <drivers/st/stm32mp1_rcc.h>
2109d40e0eSAntonio Nino Diaz #include <dt-bindings/clock/stm32mp1-clksrc.h>
2209d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
230d21680cSYann Gautier #include <lib/spinlock.h>
2409d40e0eSAntonio Nino Diaz #include <lib/utils_def.h>
25964e5ff1SNicolas Le Bayon #include <libfdt.h>
2609d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
2709d40e0eSAntonio Nino Diaz 
28964e5ff1SNicolas Le Bayon #include <platform_def.h>
29964e5ff1SNicolas Le Bayon 
307839a050SYann Gautier #define MAX_HSI_HZ		64000000
310d21680cSYann Gautier #define USB_PHY_48_MHZ		48000000
327839a050SYann Gautier 
33dfdb057aSYann Gautier #define TIMEOUT_US_200MS	U(200000)
34dfdb057aSYann Gautier #define TIMEOUT_US_1S		U(1000000)
357839a050SYann Gautier 
36dfdb057aSYann Gautier #define PLLRDY_TIMEOUT		TIMEOUT_US_200MS
37dfdb057aSYann Gautier #define CLKSRC_TIMEOUT		TIMEOUT_US_200MS
38dfdb057aSYann Gautier #define CLKDIV_TIMEOUT		TIMEOUT_US_200MS
39dfdb057aSYann Gautier #define HSIDIV_TIMEOUT		TIMEOUT_US_200MS
40dfdb057aSYann Gautier #define OSCRDY_TIMEOUT		TIMEOUT_US_1S
417839a050SYann Gautier 
42f66358afSYann Gautier const char *stm32mp_osc_node_label[NB_OSC] = {
43f66358afSYann Gautier 	[_LSI] = "clk-lsi",
44f66358afSYann Gautier 	[_LSE] = "clk-lse",
45f66358afSYann Gautier 	[_HSI] = "clk-hsi",
46f66358afSYann Gautier 	[_HSE] = "clk-hse",
47f66358afSYann Gautier 	[_CSI] = "clk-csi",
48f66358afSYann Gautier 	[_I2S_CKIN] = "i2s_ckin",
49f66358afSYann Gautier };
50f66358afSYann Gautier 
517839a050SYann Gautier enum stm32mp1_parent_id {
527839a050SYann Gautier /* Oscillators are defined in enum stm32mp_osc_id */
537839a050SYann Gautier 
547839a050SYann Gautier /* Other parent source */
557839a050SYann Gautier 	_HSI_KER = NB_OSC,
567839a050SYann Gautier 	_HSE_KER,
577839a050SYann Gautier 	_HSE_KER_DIV2,
58cbd2e8a6SGabriel Fernandez 	_HSE_RTC,
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,
110288f5cf2SYann Gautier 	_CKPER_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,
128cbd2e8a6SGabriel Fernandez 	[_HSE_RTC] = _UNKNOWN_ID,
1298fbcd9e4SEtienne Carriere 	[_CSI_KER] = CK_CSI,
1308fbcd9e4SEtienne Carriere 	[_PLL1_P] = PLL1_P,
1318fbcd9e4SEtienne Carriere 	[_PLL1_Q] = PLL1_Q,
1328fbcd9e4SEtienne Carriere 	[_PLL1_R] = PLL1_R,
1338fbcd9e4SEtienne Carriere 	[_PLL2_P] = PLL2_P,
1348fbcd9e4SEtienne Carriere 	[_PLL2_Q] = PLL2_Q,
1358fbcd9e4SEtienne Carriere 	[_PLL2_R] = PLL2_R,
1368fbcd9e4SEtienne Carriere 	[_PLL3_P] = PLL3_P,
1378fbcd9e4SEtienne Carriere 	[_PLL3_Q] = PLL3_Q,
1388fbcd9e4SEtienne Carriere 	[_PLL3_R] = PLL3_R,
1398fbcd9e4SEtienne Carriere 	[_PLL4_P] = PLL4_P,
1408fbcd9e4SEtienne Carriere 	[_PLL4_Q] = PLL4_Q,
1418fbcd9e4SEtienne Carriere 	[_PLL4_R] = PLL4_R,
1428fbcd9e4SEtienne Carriere 	[_ACLK] = CK_AXI,
1438fbcd9e4SEtienne Carriere 	[_PCLK1] = CK_AXI,
1448fbcd9e4SEtienne Carriere 	[_PCLK2] = CK_AXI,
1458fbcd9e4SEtienne Carriere 	[_PCLK3] = CK_AXI,
1468fbcd9e4SEtienne Carriere 	[_PCLK4] = CK_AXI,
1478fbcd9e4SEtienne Carriere 	[_PCLK5] = CK_AXI,
1488fbcd9e4SEtienne Carriere 	[_CK_PER] = CK_PER,
1498fbcd9e4SEtienne Carriere 	[_CK_MPU] = CK_MPU,
1508fbcd9e4SEtienne Carriere 	[_CK_MCU] = CK_MCU,
1518fbcd9e4SEtienne Carriere };
1528fbcd9e4SEtienne Carriere 
1538fbcd9e4SEtienne Carriere static unsigned int clock_id2parent_id(unsigned long id)
1548fbcd9e4SEtienne Carriere {
1558fbcd9e4SEtienne Carriere 	unsigned int n;
1568fbcd9e4SEtienne Carriere 
1578fbcd9e4SEtienne Carriere 	for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
1588fbcd9e4SEtienne Carriere 		if (parent_id_clock_id[n] == id) {
1598fbcd9e4SEtienne Carriere 			return n;
1608fbcd9e4SEtienne Carriere 		}
1618fbcd9e4SEtienne Carriere 	}
1628fbcd9e4SEtienne Carriere 
1638fbcd9e4SEtienne Carriere 	return _UNKNOWN_ID;
1648fbcd9e4SEtienne Carriere }
1658fbcd9e4SEtienne Carriere 
1667839a050SYann Gautier enum stm32mp1_pll_id {
1677839a050SYann Gautier 	_PLL1,
1687839a050SYann Gautier 	_PLL2,
1697839a050SYann Gautier 	_PLL3,
1707839a050SYann Gautier 	_PLL4,
1717839a050SYann Gautier 	_PLL_NB
1727839a050SYann Gautier };
1737839a050SYann Gautier 
1747839a050SYann Gautier enum stm32mp1_div_id {
1757839a050SYann Gautier 	_DIV_P,
1767839a050SYann Gautier 	_DIV_Q,
1777839a050SYann Gautier 	_DIV_R,
1787839a050SYann Gautier 	_DIV_NB,
1797839a050SYann Gautier };
1807839a050SYann Gautier 
1817839a050SYann Gautier enum stm32mp1_clksrc_id {
1827839a050SYann Gautier 	CLKSRC_MPU,
1837839a050SYann Gautier 	CLKSRC_AXI,
184b053a22eSYann Gautier 	CLKSRC_MCU,
1857839a050SYann Gautier 	CLKSRC_PLL12,
1867839a050SYann Gautier 	CLKSRC_PLL3,
1877839a050SYann Gautier 	CLKSRC_PLL4,
1887839a050SYann Gautier 	CLKSRC_RTC,
1897839a050SYann Gautier 	CLKSRC_MCO1,
1907839a050SYann Gautier 	CLKSRC_MCO2,
1917839a050SYann Gautier 	CLKSRC_NB
1927839a050SYann Gautier };
1937839a050SYann Gautier 
1947839a050SYann Gautier enum stm32mp1_clkdiv_id {
1957839a050SYann Gautier 	CLKDIV_MPU,
1967839a050SYann Gautier 	CLKDIV_AXI,
197b053a22eSYann Gautier 	CLKDIV_MCU,
1987839a050SYann Gautier 	CLKDIV_APB1,
1997839a050SYann Gautier 	CLKDIV_APB2,
2007839a050SYann Gautier 	CLKDIV_APB3,
2017839a050SYann Gautier 	CLKDIV_APB4,
2027839a050SYann Gautier 	CLKDIV_APB5,
2037839a050SYann Gautier 	CLKDIV_RTC,
2047839a050SYann Gautier 	CLKDIV_MCO1,
2057839a050SYann Gautier 	CLKDIV_MCO2,
2067839a050SYann Gautier 	CLKDIV_NB
2077839a050SYann Gautier };
2087839a050SYann Gautier 
2097839a050SYann Gautier enum stm32mp1_pllcfg {
2107839a050SYann Gautier 	PLLCFG_M,
2117839a050SYann Gautier 	PLLCFG_N,
2127839a050SYann Gautier 	PLLCFG_P,
2137839a050SYann Gautier 	PLLCFG_Q,
2147839a050SYann Gautier 	PLLCFG_R,
2157839a050SYann Gautier 	PLLCFG_O,
2167839a050SYann Gautier 	PLLCFG_NB
2177839a050SYann Gautier };
2187839a050SYann Gautier 
2197839a050SYann Gautier enum stm32mp1_pllcsg {
2207839a050SYann Gautier 	PLLCSG_MOD_PER,
2217839a050SYann Gautier 	PLLCSG_INC_STEP,
2227839a050SYann Gautier 	PLLCSG_SSCG_MODE,
2237839a050SYann Gautier 	PLLCSG_NB
2247839a050SYann Gautier };
2257839a050SYann Gautier 
2267839a050SYann Gautier enum stm32mp1_plltype {
2277839a050SYann Gautier 	PLL_800,
2287839a050SYann Gautier 	PLL_1600,
2297839a050SYann Gautier 	PLL_TYPE_NB
2307839a050SYann Gautier };
2317839a050SYann Gautier 
2327839a050SYann Gautier struct stm32mp1_pll {
2337839a050SYann Gautier 	uint8_t refclk_min;
2347839a050SYann Gautier 	uint8_t refclk_max;
2357839a050SYann Gautier 	uint8_t divn_max;
2367839a050SYann Gautier };
2377839a050SYann Gautier 
2387839a050SYann Gautier struct stm32mp1_clk_gate {
2397839a050SYann Gautier 	uint16_t offset;
2407839a050SYann Gautier 	uint8_t bit;
2417839a050SYann Gautier 	uint8_t index;
2427839a050SYann Gautier 	uint8_t set_clr;
243aaa09b71SYann Gautier 	uint8_t secure;
2440d21680cSYann Gautier 	uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
2450d21680cSYann Gautier 	uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
2467839a050SYann Gautier };
2477839a050SYann Gautier 
2487839a050SYann Gautier struct stm32mp1_clk_sel {
2497839a050SYann Gautier 	uint16_t offset;
2507839a050SYann Gautier 	uint8_t src;
2517839a050SYann Gautier 	uint8_t msk;
2527839a050SYann Gautier 	uint8_t nb_parent;
2537839a050SYann Gautier 	const uint8_t *parent;
2547839a050SYann Gautier };
2557839a050SYann Gautier 
2567839a050SYann Gautier #define REFCLK_SIZE 4
2577839a050SYann Gautier struct stm32mp1_clk_pll {
2587839a050SYann Gautier 	enum stm32mp1_plltype plltype;
2597839a050SYann Gautier 	uint16_t rckxselr;
2607839a050SYann Gautier 	uint16_t pllxcfgr1;
2617839a050SYann Gautier 	uint16_t pllxcfgr2;
2627839a050SYann Gautier 	uint16_t pllxfracr;
2637839a050SYann Gautier 	uint16_t pllxcr;
2647839a050SYann Gautier 	uint16_t pllxcsgr;
2657839a050SYann Gautier 	enum stm32mp_osc_id refclk[REFCLK_SIZE];
2667839a050SYann Gautier };
2677839a050SYann Gautier 
2680d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */
269aaa09b71SYann Gautier #define _CLK_SELEC(sec, off, b, idx, s)			\
2707839a050SYann Gautier 	{						\
2717839a050SYann Gautier 		.offset = (off),			\
2727839a050SYann Gautier 		.bit = (b),				\
2737839a050SYann Gautier 		.index = (idx),				\
2747839a050SYann Gautier 		.set_clr = 0,				\
275aaa09b71SYann Gautier 		.secure = (sec),			\
2767839a050SYann Gautier 		.sel = (s),				\
2777839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
2787839a050SYann Gautier 	}
2797839a050SYann Gautier 
2800d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */
281aaa09b71SYann Gautier #define _CLK_FIXED(sec, off, b, idx, f)			\
2827839a050SYann Gautier 	{						\
2837839a050SYann Gautier 		.offset = (off),			\
2847839a050SYann Gautier 		.bit = (b),				\
2857839a050SYann Gautier 		.index = (idx),				\
2867839a050SYann Gautier 		.set_clr = 0,				\
287aaa09b71SYann Gautier 		.secure = (sec),			\
2887839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
2897839a050SYann Gautier 		.fixed = (f),				\
2907839a050SYann Gautier 	}
2917839a050SYann Gautier 
2920d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */
293aaa09b71SYann Gautier #define _CLK_SC_SELEC(sec, off, b, idx, s)			\
2947839a050SYann Gautier 	{						\
2957839a050SYann Gautier 		.offset = (off),			\
2967839a050SYann Gautier 		.bit = (b),				\
2977839a050SYann Gautier 		.index = (idx),				\
2987839a050SYann Gautier 		.set_clr = 1,				\
299aaa09b71SYann Gautier 		.secure = (sec),			\
3007839a050SYann Gautier 		.sel = (s),				\
3017839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
3027839a050SYann Gautier 	}
3037839a050SYann Gautier 
3040d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */
305aaa09b71SYann Gautier #define _CLK_SC_FIXED(sec, off, b, idx, f)			\
3067839a050SYann Gautier 	{						\
3077839a050SYann Gautier 		.offset = (off),			\
3087839a050SYann Gautier 		.bit = (b),				\
3097839a050SYann Gautier 		.index = (idx),				\
3107839a050SYann Gautier 		.set_clr = 1,				\
311aaa09b71SYann Gautier 		.secure = (sec),			\
3127839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
3137839a050SYann Gautier 		.fixed = (f),				\
3147839a050SYann Gautier 	}
3157839a050SYann Gautier 
316d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents)		\
317d4151d2fSYann Gautier 	[_ ## _label ## _SEL] = {				\
318d4151d2fSYann Gautier 		.offset = _rcc_selr,				\
319d4151d2fSYann Gautier 		.src = _rcc_selr ## _ ## _label ## SRC_SHIFT,	\
3208ae08dcdSEtienne Carriere 		.msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \
3218ae08dcdSEtienne Carriere 		       (_rcc_selr ## _ ## _label ## SRC_SHIFT), \
322d4151d2fSYann Gautier 		.parent = (_parents),				\
323d4151d2fSYann Gautier 		.nb_parent = ARRAY_SIZE(_parents)		\
3247839a050SYann Gautier 	}
3257839a050SYann Gautier 
3260d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3,		\
3277839a050SYann Gautier 		 off4, off5, off6,			\
3287839a050SYann Gautier 		 p1, p2, p3, p4)			\
3297839a050SYann Gautier 	[(idx)] = {					\
3307839a050SYann Gautier 		.plltype = (type),			\
3317839a050SYann Gautier 		.rckxselr = (off1),			\
3327839a050SYann Gautier 		.pllxcfgr1 = (off2),			\
3337839a050SYann Gautier 		.pllxcfgr2 = (off3),			\
3347839a050SYann Gautier 		.pllxfracr = (off4),			\
3357839a050SYann Gautier 		.pllxcr = (off5),			\
3367839a050SYann Gautier 		.pllxcsgr = (off6),			\
3377839a050SYann Gautier 		.refclk[0] = (p1),			\
3387839a050SYann Gautier 		.refclk[1] = (p2),			\
3397839a050SYann Gautier 		.refclk[2] = (p3),			\
3407839a050SYann Gautier 		.refclk[3] = (p4),			\
3417839a050SYann Gautier 	}
3427839a050SYann Gautier 
3430d21680cSYann Gautier #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
3440d21680cSYann Gautier 
345aaa09b71SYann Gautier #define SEC		1
346aaa09b71SYann Gautier #define N_S		0
347aaa09b71SYann Gautier 
3487839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
349aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK),
350aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
351aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK),
352aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
353aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
354aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
355aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
356aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
357aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK),
358aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
359aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
3607839a050SYann Gautier 
3617418cf39SYann Gautier #if defined(IMAGE_BL32)
362aaa09b71SYann Gautier 	_CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
3637418cf39SYann Gautier #endif
364aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
365aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
366aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
367aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
368aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
369aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
370aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
371aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
372aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
373aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
3747839a050SYann Gautier 
3757418cf39SYann Gautier #if defined(IMAGE_BL32)
376aaa09b71SYann Gautier 	_CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
3777418cf39SYann Gautier #endif
378aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
3797839a050SYann Gautier 
380aaa09b71SYann Gautier 	_CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
381f33b2433SYann Gautier 
382aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
383aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
384aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
3857839a050SYann Gautier 
386aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
387aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
388aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
389aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
390aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
391aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
392aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
393aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
394aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
395aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
396aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
3977839a050SYann Gautier 
3987418cf39SYann Gautier #if defined(IMAGE_BL32)
399aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
400aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
4017418cf39SYann Gautier #endif
4027839a050SYann Gautier 
403aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
404aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
405aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
406aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
407aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
408aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
409aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
410aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
411aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
412aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
413aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
4147839a050SYann Gautier 
415aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
416aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
417aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
418aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
419aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
4207839a050SYann Gautier 
4217418cf39SYann Gautier #if defined(IMAGE_BL2)
422aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
423aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
4247418cf39SYann Gautier #endif
425aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
426aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
4277418cf39SYann Gautier #if defined(IMAGE_BL32)
428aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
4297418cf39SYann Gautier #endif
4307839a050SYann Gautier 
431aaa09b71SYann Gautier 	_CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL),
432aaa09b71SYann Gautier 	_CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
4337839a050SYann Gautier };
4347839a050SYann Gautier 
4350d21680cSYann Gautier static const uint8_t i2c12_parents[] = {
4360d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4370d21680cSYann Gautier };
4380d21680cSYann Gautier 
4390d21680cSYann Gautier static const uint8_t i2c35_parents[] = {
4400d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4410d21680cSYann Gautier };
4420d21680cSYann Gautier 
4430d21680cSYann Gautier static const uint8_t stgen_parents[] = {
4440d21680cSYann Gautier 	_HSI_KER, _HSE_KER
4450d21680cSYann Gautier };
4460d21680cSYann Gautier 
4470d21680cSYann Gautier static const uint8_t i2c46_parents[] = {
4480d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
4490d21680cSYann Gautier };
4500d21680cSYann Gautier 
4510d21680cSYann Gautier static const uint8_t spi6_parents[] = {
4520d21680cSYann Gautier 	_PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
4530d21680cSYann Gautier };
4540d21680cSYann Gautier 
4550d21680cSYann Gautier static const uint8_t usart1_parents[] = {
4560d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
4570d21680cSYann Gautier };
4580d21680cSYann Gautier 
4590d21680cSYann Gautier static const uint8_t rng1_parents[] = {
4600d21680cSYann Gautier 	_CSI, _PLL4_R, _LSE, _LSI
4610d21680cSYann Gautier };
4620d21680cSYann Gautier 
4630d21680cSYann Gautier static const uint8_t uart6_parents[] = {
4640d21680cSYann Gautier 	_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4650d21680cSYann Gautier };
4660d21680cSYann Gautier 
4670d21680cSYann Gautier static const uint8_t uart234578_parents[] = {
4680d21680cSYann Gautier 	_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4690d21680cSYann Gautier };
4700d21680cSYann Gautier 
4710d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = {
4720d21680cSYann Gautier 	_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
4730d21680cSYann Gautier };
4740d21680cSYann Gautier 
4750d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = {
4760d21680cSYann Gautier 	_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
4770d21680cSYann Gautier };
4780d21680cSYann Gautier 
4790d21680cSYann Gautier static const uint8_t qspi_parents[] = {
4800d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4810d21680cSYann Gautier };
4820d21680cSYann Gautier 
4830d21680cSYann Gautier static const uint8_t fmc_parents[] = {
4840d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4850d21680cSYann Gautier };
4860d21680cSYann Gautier 
487b8fe48b6SEtienne Carriere static const uint8_t axiss_parents[] = {
488b8fe48b6SEtienne Carriere 	_HSI, _HSE, _PLL2_P
4890d21680cSYann Gautier };
4900d21680cSYann Gautier 
491b8fe48b6SEtienne Carriere static const uint8_t mcuss_parents[] = {
492b8fe48b6SEtienne Carriere 	_HSI, _HSE, _CSI, _PLL3_P
493b053a22eSYann Gautier };
494b053a22eSYann Gautier 
4950d21680cSYann Gautier static const uint8_t usbphy_parents[] = {
4960d21680cSYann Gautier 	_HSE_KER, _PLL4_R, _HSE_KER_DIV2
4970d21680cSYann Gautier };
4980d21680cSYann Gautier 
4990d21680cSYann Gautier static const uint8_t usbo_parents[] = {
5000d21680cSYann Gautier 	_PLL4_R, _USB_PHY_48
5010d21680cSYann Gautier };
5027839a050SYann Gautier 
5038fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = {
5048fbcd9e4SEtienne Carriere 	_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
5058fbcd9e4SEtienne Carriere };
5068fbcd9e4SEtienne Carriere 
5078fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = {
5088fbcd9e4SEtienne Carriere 	_HSI, _HSE, _CSI,
5098fbcd9e4SEtienne Carriere };
5108fbcd9e4SEtienne Carriere 
511016af006SEtienne Carriere static const uint8_t rtc_parents[] = {
512cbd2e8a6SGabriel Fernandez 	_UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
513016af006SEtienne Carriere };
514016af006SEtienne Carriere 
5157839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
516d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
517d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
518d4151d2fSYann Gautier 	_CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
519d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
520d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
521d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
522d4151d2fSYann Gautier 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
5238fbcd9e4SEtienne Carriere 	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
524288f5cf2SYann Gautier 	_CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents),
525016af006SEtienne Carriere 	_CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
526d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
527d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
528d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
529d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
530d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
531d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
532d4151d2fSYann Gautier 	_CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
533d4151d2fSYann Gautier 	_CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
534b8fe48b6SEtienne Carriere 	_CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents),
535b8fe48b6SEtienne Carriere 	_CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents),
536d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
537d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
5387839a050SYann Gautier };
5397839a050SYann Gautier 
5407839a050SYann Gautier /* Define characteristic of PLL according type */
5417839a050SYann Gautier #define DIVN_MIN	24
5427839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
5437839a050SYann Gautier 	[PLL_800] = {
5447839a050SYann Gautier 		.refclk_min = 4,
5457839a050SYann Gautier 		.refclk_max = 16,
5467839a050SYann Gautier 		.divn_max = 99,
5477839a050SYann Gautier 	},
5487839a050SYann Gautier 	[PLL_1600] = {
5497839a050SYann Gautier 		.refclk_min = 8,
5507839a050SYann Gautier 		.refclk_max = 16,
5517839a050SYann Gautier 		.divn_max = 199,
5527839a050SYann Gautier 	},
5537839a050SYann Gautier };
5547839a050SYann Gautier 
5557839a050SYann Gautier /* PLLNCFGR2 register divider by output */
5567839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = {
5577839a050SYann Gautier 	[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
5587839a050SYann Gautier 	[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
5590d21680cSYann Gautier 	[_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
5607839a050SYann Gautier };
5617839a050SYann Gautier 
5627839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
5630d21680cSYann Gautier 	_CLK_PLL(_PLL1, PLL_1600,
5647839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
5657839a050SYann Gautier 		 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
5667839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5670d21680cSYann Gautier 	_CLK_PLL(_PLL2, PLL_1600,
5687839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
5697839a050SYann Gautier 		 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
5707839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5710d21680cSYann Gautier 	_CLK_PLL(_PLL3, PLL_800,
5727839a050SYann Gautier 		 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
5737839a050SYann Gautier 		 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
5747839a050SYann Gautier 		 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
5750d21680cSYann Gautier 	_CLK_PLL(_PLL4, PLL_800,
5767839a050SYann Gautier 		 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
5777839a050SYann Gautier 		 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
5787839a050SYann Gautier 		 _HSI, _HSE, _CSI, _I2S_CKIN),
5797839a050SYann Gautier };
5807839a050SYann Gautier 
5817839a050SYann Gautier /* Prescaler table lookups for clock computation */
582b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
583b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = {
584b053a22eSYann Gautier 	0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
585b053a22eSYann Gautier };
5867839a050SYann Gautier 
5877839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
5887839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
5897839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
5907839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = {
5917839a050SYann Gautier 	0, 1, 2, 3, 4, 4, 4, 4
5927839a050SYann Gautier };
5937839a050SYann Gautier 
5947839a050SYann Gautier /* div = /1 /2 /3 /4 */
5957839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = {
5967839a050SYann Gautier 	1, 2, 3, 4, 4, 4, 4, 4
5977839a050SYann Gautier };
5987839a050SYann Gautier 
59937e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
60037e8295aSEtienne Carriere 	[_HSI] = "HSI",
60137e8295aSEtienne Carriere 	[_HSE] = "HSE",
60237e8295aSEtienne Carriere 	[_CSI] = "CSI",
60337e8295aSEtienne Carriere 	[_LSI] = "LSI",
60437e8295aSEtienne Carriere 	[_LSE] = "LSE",
60537e8295aSEtienne Carriere 	[_I2S_CKIN] = "I2S_CKIN",
60637e8295aSEtienne Carriere 	[_HSI_KER] = "HSI_KER",
60737e8295aSEtienne Carriere 	[_HSE_KER] = "HSE_KER",
60837e8295aSEtienne Carriere 	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
609cbd2e8a6SGabriel Fernandez 	[_HSE_RTC] = "HSE_RTC",
61037e8295aSEtienne Carriere 	[_CSI_KER] = "CSI_KER",
61137e8295aSEtienne Carriere 	[_PLL1_P] = "PLL1_P",
61237e8295aSEtienne Carriere 	[_PLL1_Q] = "PLL1_Q",
61337e8295aSEtienne Carriere 	[_PLL1_R] = "PLL1_R",
61437e8295aSEtienne Carriere 	[_PLL2_P] = "PLL2_P",
61537e8295aSEtienne Carriere 	[_PLL2_Q] = "PLL2_Q",
61637e8295aSEtienne Carriere 	[_PLL2_R] = "PLL2_R",
61737e8295aSEtienne Carriere 	[_PLL3_P] = "PLL3_P",
61837e8295aSEtienne Carriere 	[_PLL3_Q] = "PLL3_Q",
61937e8295aSEtienne Carriere 	[_PLL3_R] = "PLL3_R",
62037e8295aSEtienne Carriere 	[_PLL4_P] = "PLL4_P",
62137e8295aSEtienne Carriere 	[_PLL4_Q] = "PLL4_Q",
62237e8295aSEtienne Carriere 	[_PLL4_R] = "PLL4_R",
62337e8295aSEtienne Carriere 	[_ACLK] = "ACLK",
62437e8295aSEtienne Carriere 	[_PCLK1] = "PCLK1",
62537e8295aSEtienne Carriere 	[_PCLK2] = "PCLK2",
62637e8295aSEtienne Carriere 	[_PCLK3] = "PCLK3",
62737e8295aSEtienne Carriere 	[_PCLK4] = "PCLK4",
62837e8295aSEtienne Carriere 	[_PCLK5] = "PCLK5",
62937e8295aSEtienne Carriere 	[_HCLK6] = "KCLK6",
63037e8295aSEtienne Carriere 	[_HCLK2] = "HCLK2",
63137e8295aSEtienne Carriere 	[_CK_PER] = "CK_PER",
63237e8295aSEtienne Carriere 	[_CK_MPU] = "CK_MPU",
63337e8295aSEtienne Carriere 	[_CK_MCU] = "CK_MCU",
63437e8295aSEtienne Carriere 	[_USB_PHY_48] = "USB_PHY_48",
63537e8295aSEtienne Carriere };
63637e8295aSEtienne Carriere 
6370d21680cSYann Gautier /* RCC clock device driver private */
6380d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC];
6390d21680cSYann Gautier static struct spinlock reg_lock;
6400d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES];
6410d21680cSYann Gautier static struct spinlock refcount_lock;
6427839a050SYann Gautier 
6430d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
6440d21680cSYann Gautier {
6450d21680cSYann Gautier 	return &stm32mp1_clk_gate[idx];
6460d21680cSYann Gautier }
6477839a050SYann Gautier 
6483d69149aSYann Gautier #if defined(IMAGE_BL32)
6493d69149aSYann Gautier static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate)
6503d69149aSYann Gautier {
6513d69149aSYann Gautier 	return gate->secure == N_S;
6523d69149aSYann Gautier }
6533d69149aSYann Gautier #endif
6543d69149aSYann Gautier 
6550d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
6560d21680cSYann Gautier {
6570d21680cSYann Gautier 	return &stm32mp1_clk_sel[idx];
6580d21680cSYann Gautier }
6590d21680cSYann Gautier 
6600d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
6610d21680cSYann Gautier {
6620d21680cSYann Gautier 	return &stm32mp1_clk_pll[idx];
6630d21680cSYann Gautier }
6640d21680cSYann Gautier 
6650d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock)
6660d21680cSYann Gautier {
667e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6680d21680cSYann Gautier 		/* Assume interrupts are masked */
6690d21680cSYann Gautier 		spin_lock(lock);
6700d21680cSYann Gautier 	}
671e463d3f4SYann Gautier }
6720d21680cSYann Gautier 
6730d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock)
6740d21680cSYann Gautier {
675e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6760d21680cSYann Gautier 		spin_unlock(lock);
6770d21680cSYann Gautier 	}
678e463d3f4SYann Gautier }
6790d21680cSYann Gautier 
6800d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void)
6810d21680cSYann Gautier {
6820d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6831bb9072aSEtienne Carriere 	uint32_t mask = RCC_TZCR_TZEN;
6840d21680cSYann Gautier 
6851bb9072aSEtienne Carriere 	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
6860d21680cSYann Gautier }
6870d21680cSYann Gautier 
688b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void)
689b053a22eSYann Gautier {
690b053a22eSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6911bb9072aSEtienne Carriere 	uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT;
692b053a22eSYann Gautier 
6931bb9072aSEtienne Carriere 	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
694b053a22eSYann Gautier }
695b053a22eSYann Gautier 
6960d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void)
6970d21680cSYann Gautier {
6980d21680cSYann Gautier 	stm32mp1_clk_lock(&reg_lock);
6990d21680cSYann Gautier }
7000d21680cSYann Gautier 
7010d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void)
7020d21680cSYann Gautier {
7030d21680cSYann Gautier 	stm32mp1_clk_unlock(&reg_lock);
7040d21680cSYann Gautier }
7050d21680cSYann Gautier 
7060d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
7077839a050SYann Gautier {
7087839a050SYann Gautier 	if (idx >= NB_OSC) {
7097839a050SYann Gautier 		return 0;
7107839a050SYann Gautier 	}
7117839a050SYann Gautier 
7120d21680cSYann Gautier 	return stm32mp1_osc[idx];
7137839a050SYann Gautier }
7147839a050SYann Gautier 
7150d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id)
7167839a050SYann Gautier {
7170d21680cSYann Gautier 	unsigned int i;
7187839a050SYann Gautier 
7190d21680cSYann Gautier 	for (i = 0U; i < NB_GATES; i++) {
7200d21680cSYann Gautier 		if (gate_ref(i)->index == id) {
7217839a050SYann Gautier 			return i;
7227839a050SYann Gautier 		}
7237839a050SYann Gautier 	}
7247839a050SYann Gautier 
72544fb470bSYann Gautier 	ERROR("%s: clk id %lu not found\n", __func__, id);
7267839a050SYann Gautier 
7277839a050SYann Gautier 	return -EINVAL;
7287839a050SYann Gautier }
7297839a050SYann Gautier 
7300d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
7317839a050SYann Gautier {
7320d21680cSYann Gautier 	return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
7337839a050SYann Gautier }
7347839a050SYann Gautier 
7350d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
7367839a050SYann Gautier {
7370d21680cSYann Gautier 	return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
7387839a050SYann Gautier }
7397839a050SYann Gautier 
7400d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id)
7417839a050SYann Gautier {
7420d21680cSYann Gautier 	const struct stm32mp1_clk_sel *sel;
7438fbcd9e4SEtienne Carriere 	uint32_t p_sel;
7447839a050SYann Gautier 	int i;
7457839a050SYann Gautier 	enum stm32mp1_parent_id p;
7467839a050SYann Gautier 	enum stm32mp1_parent_sel s;
7470d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7487839a050SYann Gautier 
7498fbcd9e4SEtienne Carriere 	/* Few non gateable clock have a static parent ID, find them */
7508fbcd9e4SEtienne Carriere 	i = (int)clock_id2parent_id(id);
7518fbcd9e4SEtienne Carriere 	if (i != _UNKNOWN_ID) {
7528fbcd9e4SEtienne Carriere 		return i;
7537839a050SYann Gautier 	}
7547839a050SYann Gautier 
7550d21680cSYann Gautier 	i = stm32mp1_clk_get_gated_id(id);
7567839a050SYann Gautier 	if (i < 0) {
7570d21680cSYann Gautier 		panic();
7587839a050SYann Gautier 	}
7597839a050SYann Gautier 
7600d21680cSYann Gautier 	p = stm32mp1_clk_get_fixed_parent(i);
7617839a050SYann Gautier 	if (p < _PARENT_NB) {
7627839a050SYann Gautier 		return (int)p;
7637839a050SYann Gautier 	}
7647839a050SYann Gautier 
7650d21680cSYann Gautier 	s = stm32mp1_clk_get_sel(i);
7660d21680cSYann Gautier 	if (s == _UNKNOWN_SEL) {
7670d21680cSYann Gautier 		return -EINVAL;
7680d21680cSYann Gautier 	}
7697839a050SYann Gautier 	if (s >= _PARENT_SEL_NB) {
7700d21680cSYann Gautier 		panic();
7717839a050SYann Gautier 	}
7727839a050SYann Gautier 
7730d21680cSYann Gautier 	sel = clk_sel_ref(s);
7748ae08dcdSEtienne Carriere 	p_sel = (mmio_read_32(rcc_base + sel->offset) &
7758ae08dcdSEtienne Carriere 		 (sel->msk << sel->src)) >> sel->src;
7760d21680cSYann Gautier 	if (p_sel < sel->nb_parent) {
7770d21680cSYann Gautier 		return (int)sel->parent[p_sel];
7787839a050SYann Gautier 	}
7797839a050SYann Gautier 
7807839a050SYann Gautier 	return -EINVAL;
7817839a050SYann Gautier }
7827839a050SYann Gautier 
7830d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
7847839a050SYann Gautier {
7850d21680cSYann Gautier 	uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
7860d21680cSYann Gautier 	uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
7877839a050SYann Gautier 
7880d21680cSYann Gautier 	return stm32mp1_clk_get_fixed(pll->refclk[src]);
7897839a050SYann Gautier }
7907839a050SYann Gautier 
7917839a050SYann Gautier /*
7927839a050SYann Gautier  * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
7937839a050SYann Gautier  * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
7947839a050SYann Gautier  * - PLL3 & PLL4 => return VCO     with Fpll_y_ck = FVCO / (DIVy + 1)
7957839a050SYann Gautier  * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
7967839a050SYann Gautier  */
7970d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
7987839a050SYann Gautier {
7997839a050SYann Gautier 	unsigned long refclk, fvco;
8007839a050SYann Gautier 	uint32_t cfgr1, fracr, divm, divn;
8010d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
8027839a050SYann Gautier 
8030d21680cSYann Gautier 	cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
8040d21680cSYann Gautier 	fracr = mmio_read_32(rcc_base + pll->pllxfracr);
8057839a050SYann Gautier 
8067839a050SYann Gautier 	divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
8077839a050SYann Gautier 	divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
8087839a050SYann Gautier 
8090d21680cSYann Gautier 	refclk = stm32mp1_pll_get_fref(pll);
8107839a050SYann Gautier 
8117839a050SYann Gautier 	/*
8127839a050SYann Gautier 	 * With FRACV :
8137839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
8147839a050SYann Gautier 	 * Without FRACV
8157839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
8167839a050SYann Gautier 	 */
8177839a050SYann Gautier 	if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
8180d21680cSYann Gautier 		uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
8190d21680cSYann Gautier 				 RCC_PLLNFRACR_FRACV_SHIFT;
8207839a050SYann Gautier 		unsigned long long numerator, denominator;
8217839a050SYann Gautier 
8220d21680cSYann Gautier 		numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
8230d21680cSYann Gautier 		numerator = refclk * numerator;
8247839a050SYann Gautier 		denominator = ((unsigned long long)divm + 1U) << 13;
8257839a050SYann Gautier 		fvco = (unsigned long)(numerator / denominator);
8267839a050SYann Gautier 	} else {
8277839a050SYann Gautier 		fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
8287839a050SYann Gautier 	}
8297839a050SYann Gautier 
8307839a050SYann Gautier 	return fvco;
8317839a050SYann Gautier }
8327839a050SYann Gautier 
8330d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
8347839a050SYann Gautier 					    enum stm32mp1_div_id div_id)
8357839a050SYann Gautier {
8360d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
8377839a050SYann Gautier 	unsigned long dfout;
8387839a050SYann Gautier 	uint32_t cfgr2, divy;
8397839a050SYann Gautier 
8407839a050SYann Gautier 	if (div_id >= _DIV_NB) {
8417839a050SYann Gautier 		return 0;
8427839a050SYann Gautier 	}
8437839a050SYann Gautier 
8440d21680cSYann Gautier 	cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
8457839a050SYann Gautier 	divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
8467839a050SYann Gautier 
8470d21680cSYann Gautier 	dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
8487839a050SYann Gautier 
8497839a050SYann Gautier 	return dfout;
8507839a050SYann Gautier }
8517839a050SYann Gautier 
8520d21680cSYann Gautier static unsigned long get_clock_rate(int p)
8537839a050SYann Gautier {
8547839a050SYann Gautier 	uint32_t reg, clkdiv;
8557839a050SYann Gautier 	unsigned long clock = 0;
8560d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
8577839a050SYann Gautier 
8587839a050SYann Gautier 	switch (p) {
8597839a050SYann Gautier 	case _CK_MPU:
8607839a050SYann Gautier 	/* MPU sub system */
8610d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
8627839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8637839a050SYann Gautier 		case RCC_MPCKSELR_HSI:
8640d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8657839a050SYann Gautier 			break;
8667839a050SYann Gautier 		case RCC_MPCKSELR_HSE:
8670d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8687839a050SYann Gautier 			break;
8697839a050SYann Gautier 		case RCC_MPCKSELR_PLL:
8700d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8717839a050SYann Gautier 			break;
8727839a050SYann Gautier 		case RCC_MPCKSELR_PLL_MPUDIV:
8730d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8747839a050SYann Gautier 
8750d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
8767839a050SYann Gautier 			clkdiv = reg & RCC_MPUDIV_MASK;
877602ae2f2SGabriel Fernandez 			clock >>= stm32mp1_mpu_div[clkdiv];
8787839a050SYann Gautier 			break;
8797839a050SYann Gautier 		default:
8807839a050SYann Gautier 			break;
8817839a050SYann Gautier 		}
8827839a050SYann Gautier 		break;
8837839a050SYann Gautier 	/* AXI sub system */
8847839a050SYann Gautier 	case _ACLK:
8857839a050SYann Gautier 	case _HCLK2:
8867839a050SYann Gautier 	case _HCLK6:
8877839a050SYann Gautier 	case _PCLK4:
8887839a050SYann Gautier 	case _PCLK5:
8890d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
8907839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8917839a050SYann Gautier 		case RCC_ASSCKSELR_HSI:
8920d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8937839a050SYann Gautier 			break;
8947839a050SYann Gautier 		case RCC_ASSCKSELR_HSE:
8950d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8967839a050SYann Gautier 			break;
8977839a050SYann Gautier 		case RCC_ASSCKSELR_PLL:
8980d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
8997839a050SYann Gautier 			break;
9007839a050SYann Gautier 		default:
9017839a050SYann Gautier 			break;
9027839a050SYann Gautier 		}
9037839a050SYann Gautier 
9047839a050SYann Gautier 		/* System clock divider */
9050d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
9067839a050SYann Gautier 		clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
9077839a050SYann Gautier 
9087839a050SYann Gautier 		switch (p) {
9097839a050SYann Gautier 		case _PCLK4:
9100d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
9117839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
9127839a050SYann Gautier 			break;
9137839a050SYann Gautier 		case _PCLK5:
9140d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
9157839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
9167839a050SYann Gautier 			break;
9177839a050SYann Gautier 		default:
9187839a050SYann Gautier 			break;
9197839a050SYann Gautier 		}
9207839a050SYann Gautier 		break;
921b053a22eSYann Gautier 	/* MCU sub system */
922b053a22eSYann Gautier 	case _CK_MCU:
923b053a22eSYann Gautier 	case _PCLK1:
924b053a22eSYann Gautier 	case _PCLK2:
925b053a22eSYann Gautier 	case _PCLK3:
926b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
927b053a22eSYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
928b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSI:
929b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
930b053a22eSYann Gautier 			break;
931b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSE:
932b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
933b053a22eSYann Gautier 			break;
934b053a22eSYann Gautier 		case RCC_MSSCKSELR_CSI:
935b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
936b053a22eSYann Gautier 			break;
937b053a22eSYann Gautier 		case RCC_MSSCKSELR_PLL:
938b053a22eSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
939b053a22eSYann Gautier 			break;
940b053a22eSYann Gautier 		default:
941b053a22eSYann Gautier 			break;
942b053a22eSYann Gautier 		}
943b053a22eSYann Gautier 
944b053a22eSYann Gautier 		/* MCU clock divider */
945b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
946b053a22eSYann Gautier 		clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
947b053a22eSYann Gautier 
948b053a22eSYann Gautier 		switch (p) {
949b053a22eSYann Gautier 		case _PCLK1:
950b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
951b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
952b053a22eSYann Gautier 			break;
953b053a22eSYann Gautier 		case _PCLK2:
954b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
955b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
956b053a22eSYann Gautier 			break;
957b053a22eSYann Gautier 		case _PCLK3:
958b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
959b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
960b053a22eSYann Gautier 			break;
961b053a22eSYann Gautier 		case _CK_MCU:
962b053a22eSYann Gautier 		default:
963b053a22eSYann Gautier 			break;
964b053a22eSYann Gautier 		}
965b053a22eSYann Gautier 		break;
9667839a050SYann Gautier 	case _CK_PER:
9670d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
9687839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
9697839a050SYann Gautier 		case RCC_CPERCKSELR_HSI:
9700d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
9717839a050SYann Gautier 			break;
9727839a050SYann Gautier 		case RCC_CPERCKSELR_HSE:
9730d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
9747839a050SYann Gautier 			break;
9757839a050SYann Gautier 		case RCC_CPERCKSELR_CSI:
9760d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
9777839a050SYann Gautier 			break;
9787839a050SYann Gautier 		default:
9797839a050SYann Gautier 			break;
9807839a050SYann Gautier 		}
9817839a050SYann Gautier 		break;
9827839a050SYann Gautier 	case _HSI:
9837839a050SYann Gautier 	case _HSI_KER:
9840d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSI);
9857839a050SYann Gautier 		break;
9867839a050SYann Gautier 	case _CSI:
9877839a050SYann Gautier 	case _CSI_KER:
9880d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_CSI);
9897839a050SYann Gautier 		break;
9907839a050SYann Gautier 	case _HSE:
9917839a050SYann Gautier 	case _HSE_KER:
9920d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE);
9937839a050SYann Gautier 		break;
9947839a050SYann Gautier 	case _HSE_KER_DIV2:
9950d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
9967839a050SYann Gautier 		break;
997cbd2e8a6SGabriel Fernandez 	case _HSE_RTC:
998cbd2e8a6SGabriel Fernandez 		clock = stm32mp1_clk_get_fixed(_HSE);
999cbd2e8a6SGabriel Fernandez 		clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
1000cbd2e8a6SGabriel Fernandez 		break;
10017839a050SYann Gautier 	case _LSI:
10020d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSI);
10037839a050SYann Gautier 		break;
10047839a050SYann Gautier 	case _LSE:
10050d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSE);
10067839a050SYann Gautier 		break;
10077839a050SYann Gautier 	/* PLL */
10087839a050SYann Gautier 	case _PLL1_P:
10090d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
10107839a050SYann Gautier 		break;
10117839a050SYann Gautier 	case _PLL1_Q:
10120d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
10137839a050SYann Gautier 		break;
10147839a050SYann Gautier 	case _PLL1_R:
10150d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
10167839a050SYann Gautier 		break;
10177839a050SYann Gautier 	case _PLL2_P:
10180d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
10197839a050SYann Gautier 		break;
10207839a050SYann Gautier 	case _PLL2_Q:
10210d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
10227839a050SYann Gautier 		break;
10237839a050SYann Gautier 	case _PLL2_R:
10240d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
10257839a050SYann Gautier 		break;
10267839a050SYann Gautier 	case _PLL3_P:
10270d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
10287839a050SYann Gautier 		break;
10297839a050SYann Gautier 	case _PLL3_Q:
10300d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
10317839a050SYann Gautier 		break;
10327839a050SYann Gautier 	case _PLL3_R:
10330d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
10347839a050SYann Gautier 		break;
10357839a050SYann Gautier 	case _PLL4_P:
10360d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
10377839a050SYann Gautier 		break;
10387839a050SYann Gautier 	case _PLL4_Q:
10390d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
10407839a050SYann Gautier 		break;
10417839a050SYann Gautier 	case _PLL4_R:
10420d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
10437839a050SYann Gautier 		break;
10447839a050SYann Gautier 	/* Other */
10457839a050SYann Gautier 	case _USB_PHY_48:
10460d21680cSYann Gautier 		clock = USB_PHY_48_MHZ;
10477839a050SYann Gautier 		break;
10487839a050SYann Gautier 	default:
10497839a050SYann Gautier 		break;
10507839a050SYann Gautier 	}
10517839a050SYann Gautier 
10527839a050SYann Gautier 	return clock;
10537839a050SYann Gautier }
10547839a050SYann Gautier 
10550d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate)
10560d21680cSYann Gautier {
10570d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10580d21680cSYann Gautier 
105925be845eSEtienne Carriere 	VERBOSE("Enable clock %u\n", gate->index);
106025be845eSEtienne Carriere 
10610d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10620d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
10630d21680cSYann Gautier 	} else {
10640d21680cSYann Gautier 		mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
10650d21680cSYann Gautier 	}
10660d21680cSYann Gautier }
10670d21680cSYann Gautier 
10680d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate)
10690d21680cSYann Gautier {
10700d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10710d21680cSYann Gautier 
107225be845eSEtienne Carriere 	VERBOSE("Disable clock %u\n", gate->index);
107325be845eSEtienne Carriere 
10740d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10750d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
10760d21680cSYann Gautier 			      BIT(gate->bit));
10770d21680cSYann Gautier 	} else {
10780d21680cSYann Gautier 		mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
10790d21680cSYann Gautier 	}
10800d21680cSYann Gautier }
10810d21680cSYann Gautier 
10820d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
10830d21680cSYann Gautier {
10840d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10850d21680cSYann Gautier 
10860d21680cSYann Gautier 	return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
10870d21680cSYann Gautier }
10880d21680cSYann Gautier 
108935848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */
109035848200SEtienne Carriere static bool clock_is_always_on(unsigned long id)
109135848200SEtienne Carriere {
109235848200SEtienne Carriere 	switch (id) {
109335848200SEtienne Carriere 	case CK_HSE:
109435848200SEtienne Carriere 	case CK_CSI:
109535848200SEtienne Carriere 	case CK_LSI:
109635848200SEtienne Carriere 	case CK_LSE:
109735848200SEtienne Carriere 	case CK_HSI:
109835848200SEtienne Carriere 	case CK_HSE_DIV2:
109935848200SEtienne Carriere 	case PLL1_Q:
110035848200SEtienne Carriere 	case PLL1_R:
110135848200SEtienne Carriere 	case PLL2_P:
110235848200SEtienne Carriere 	case PLL2_Q:
110335848200SEtienne Carriere 	case PLL2_R:
110435848200SEtienne Carriere 	case PLL3_P:
110535848200SEtienne Carriere 	case PLL3_Q:
110635848200SEtienne Carriere 	case PLL3_R:
1107bf39318dSYann Gautier 	case CK_AXI:
1108bf39318dSYann Gautier 	case CK_MPU:
1109bf39318dSYann Gautier 	case CK_MCU:
11105b111c74SHE Shushan 	case RTC:
111135848200SEtienne Carriere 		return true;
111235848200SEtienne Carriere 	default:
111335848200SEtienne Carriere 		return false;
111435848200SEtienne Carriere 	}
111535848200SEtienne Carriere }
111635848200SEtienne Carriere 
11172444d231SYann Gautier static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt)
11180d21680cSYann Gautier {
11190d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
112035848200SEtienne Carriere 	int i;
11210d21680cSYann Gautier 
112235848200SEtienne Carriere 	if (clock_is_always_on(id)) {
112335848200SEtienne Carriere 		return;
112435848200SEtienne Carriere 	}
112535848200SEtienne Carriere 
112635848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11270d21680cSYann Gautier 	if (i < 0) {
112844fb470bSYann Gautier 		ERROR("Clock %lu can't be enabled\n", id);
11290d21680cSYann Gautier 		panic();
11300d21680cSYann Gautier 	}
11310d21680cSYann Gautier 
11320d21680cSYann Gautier 	gate = gate_ref(i);
11332444d231SYann Gautier 
11342444d231SYann Gautier 	if (!with_refcnt) {
11352444d231SYann Gautier 		__clk_enable(gate);
11362444d231SYann Gautier 		return;
11372444d231SYann Gautier 	}
11380d21680cSYann Gautier 
11393d69149aSYann Gautier #if defined(IMAGE_BL32)
11403d69149aSYann Gautier 	if (gate_is_non_secure(gate)) {
11413d69149aSYann Gautier 		/* Enable non-secure clock w/o any refcounting */
11423d69149aSYann Gautier 		__clk_enable(gate);
11433d69149aSYann Gautier 		return;
11443d69149aSYann Gautier 	}
11453d69149aSYann Gautier #endif
11463d69149aSYann Gautier 
11470d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11480d21680cSYann Gautier 
11492444d231SYann Gautier 	if (gate_refcounts[i] == 0U) {
11500d21680cSYann Gautier 		__clk_enable(gate);
11510d21680cSYann Gautier 	}
11520d21680cSYann Gautier 
11532444d231SYann Gautier 	gate_refcounts[i]++;
11542444d231SYann Gautier 	if (gate_refcounts[i] == UINT_MAX) {
11552444d231SYann Gautier 		ERROR("Clock %lu refcount reached max value\n", id);
11562444d231SYann Gautier 		panic();
11572444d231SYann Gautier 	}
11582444d231SYann Gautier 
11590d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
11600d21680cSYann Gautier }
11610d21680cSYann Gautier 
11622444d231SYann Gautier static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt)
11630d21680cSYann Gautier {
11640d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
116535848200SEtienne Carriere 	int i;
11660d21680cSYann Gautier 
116735848200SEtienne Carriere 	if (clock_is_always_on(id)) {
116835848200SEtienne Carriere 		return;
116935848200SEtienne Carriere 	}
117035848200SEtienne Carriere 
117135848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11720d21680cSYann Gautier 	if (i < 0) {
117344fb470bSYann Gautier 		ERROR("Clock %lu can't be disabled\n", id);
11740d21680cSYann Gautier 		panic();
11750d21680cSYann Gautier 	}
11760d21680cSYann Gautier 
11770d21680cSYann Gautier 	gate = gate_ref(i);
11782444d231SYann Gautier 
11792444d231SYann Gautier 	if (!with_refcnt) {
11802444d231SYann Gautier 		__clk_disable(gate);
11812444d231SYann Gautier 		return;
11822444d231SYann Gautier 	}
11830d21680cSYann Gautier 
11843d69149aSYann Gautier #if defined(IMAGE_BL32)
11853d69149aSYann Gautier 	if (gate_is_non_secure(gate)) {
11863d69149aSYann Gautier 		/* Don't disable non-secure clocks */
11873d69149aSYann Gautier 		return;
11883d69149aSYann Gautier 	}
11893d69149aSYann Gautier #endif
11903d69149aSYann Gautier 
11910d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11920d21680cSYann Gautier 
11932444d231SYann Gautier 	if (gate_refcounts[i] == 0U) {
11942444d231SYann Gautier 		ERROR("Clock %lu refcount reached 0\n", id);
11952444d231SYann Gautier 		panic();
11962444d231SYann Gautier 	}
11972444d231SYann Gautier 	gate_refcounts[i]--;
11982444d231SYann Gautier 
11992444d231SYann Gautier 	if (gate_refcounts[i] == 0U) {
12000d21680cSYann Gautier 		__clk_disable(gate);
12010d21680cSYann Gautier 	}
12020d21680cSYann Gautier 
12030d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
12040d21680cSYann Gautier }
12050d21680cSYann Gautier 
120633667d29SYann Gautier static int stm32mp_clk_enable(unsigned long id)
12070d21680cSYann Gautier {
12080d21680cSYann Gautier 	__stm32mp1_clk_enable(id, true);
120933667d29SYann Gautier 
121033667d29SYann Gautier 	return 0;
12110d21680cSYann Gautier }
12120d21680cSYann Gautier 
121333667d29SYann Gautier static void stm32mp_clk_disable(unsigned long id)
12140d21680cSYann Gautier {
12150d21680cSYann Gautier 	__stm32mp1_clk_disable(id, true);
12160d21680cSYann Gautier }
12170d21680cSYann Gautier 
121833667d29SYann Gautier static bool stm32mp_clk_is_enabled(unsigned long id)
12197839a050SYann Gautier {
122035848200SEtienne Carriere 	int i;
12217839a050SYann Gautier 
122235848200SEtienne Carriere 	if (clock_is_always_on(id)) {
122335848200SEtienne Carriere 		return true;
122435848200SEtienne Carriere 	}
122535848200SEtienne Carriere 
122635848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
12277839a050SYann Gautier 	if (i < 0) {
12280d21680cSYann Gautier 		panic();
12297839a050SYann Gautier 	}
12307839a050SYann Gautier 
12310d21680cSYann Gautier 	return __clk_is_enabled(gate_ref(i));
12327839a050SYann Gautier }
12337839a050SYann Gautier 
123433667d29SYann Gautier static unsigned long stm32mp_clk_get_rate(unsigned long id)
12357839a050SYann Gautier {
123633667d29SYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
12370d21680cSYann Gautier 	int p = stm32mp1_clk_get_parent(id);
123833667d29SYann Gautier 	uint32_t prescaler, timpre;
123933667d29SYann Gautier 	unsigned long parent_rate;
12407839a050SYann Gautier 
12417839a050SYann Gautier 	if (p < 0) {
12427839a050SYann Gautier 		return 0;
12437839a050SYann Gautier 	}
12447839a050SYann Gautier 
124533667d29SYann Gautier 	parent_rate = get_clock_rate(p);
124633667d29SYann Gautier 
124733667d29SYann Gautier 	switch (id) {
124833667d29SYann Gautier 	case TIM2_K:
124933667d29SYann Gautier 	case TIM3_K:
125033667d29SYann Gautier 	case TIM4_K:
125133667d29SYann Gautier 	case TIM5_K:
125233667d29SYann Gautier 	case TIM6_K:
125333667d29SYann Gautier 	case TIM7_K:
125433667d29SYann Gautier 	case TIM12_K:
125533667d29SYann Gautier 	case TIM13_K:
125633667d29SYann Gautier 	case TIM14_K:
125733667d29SYann Gautier 		prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) &
125833667d29SYann Gautier 			    RCC_APBXDIV_MASK;
125933667d29SYann Gautier 		timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) &
126033667d29SYann Gautier 			 RCC_TIMGXPRER_TIMGXPRE;
126133667d29SYann Gautier 		break;
126233667d29SYann Gautier 
126333667d29SYann Gautier 	case TIM1_K:
126433667d29SYann Gautier 	case TIM8_K:
126533667d29SYann Gautier 	case TIM15_K:
126633667d29SYann Gautier 	case TIM16_K:
126733667d29SYann Gautier 	case TIM17_K:
126833667d29SYann Gautier 		prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) &
126933667d29SYann Gautier 			    RCC_APBXDIV_MASK;
127033667d29SYann Gautier 		timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) &
127133667d29SYann Gautier 			 RCC_TIMGXPRER_TIMGXPRE;
127233667d29SYann Gautier 		break;
127333667d29SYann Gautier 
127433667d29SYann Gautier 	default:
127533667d29SYann Gautier 		return parent_rate;
127633667d29SYann Gautier 	}
127733667d29SYann Gautier 
127833667d29SYann Gautier 	if (prescaler == 0U) {
127933667d29SYann Gautier 		return parent_rate;
128033667d29SYann Gautier 	}
128133667d29SYann Gautier 
128233667d29SYann Gautier 	return parent_rate * (timpre + 1U) * 2U;
12837839a050SYann Gautier }
12847839a050SYann Gautier 
12850d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
12867839a050SYann Gautier {
12870d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12887839a050SYann Gautier 
12890d21680cSYann Gautier 	if (enable) {
12907839a050SYann Gautier 		mmio_setbits_32(address, mask_on);
12917839a050SYann Gautier 	} else {
12927839a050SYann Gautier 		mmio_clrbits_32(address, mask_on);
12937839a050SYann Gautier 	}
12947839a050SYann Gautier }
12957839a050SYann Gautier 
12960d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
12977839a050SYann Gautier {
12980d21680cSYann Gautier 	uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
12990d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
13000d21680cSYann Gautier 
13010d21680cSYann Gautier 	mmio_write_32(address, mask_on);
13027839a050SYann Gautier }
13037839a050SYann Gautier 
13040d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
13057839a050SYann Gautier {
1306dfdb057aSYann Gautier 	uint64_t timeout;
13077839a050SYann Gautier 	uint32_t mask_test;
13080d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
13097839a050SYann Gautier 
13100d21680cSYann Gautier 	if (enable) {
13117839a050SYann Gautier 		mask_test = mask_rdy;
13127839a050SYann Gautier 	} else {
13137839a050SYann Gautier 		mask_test = 0;
13147839a050SYann Gautier 	}
13157839a050SYann Gautier 
1316dfdb057aSYann Gautier 	timeout = timeout_init_us(OSCRDY_TIMEOUT);
13177839a050SYann Gautier 	while ((mmio_read_32(address) & mask_rdy) != mask_test) {
1318dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
13190d21680cSYann Gautier 			ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
13207839a050SYann Gautier 			      mask_rdy, address, enable, mmio_read_32(address));
13217839a050SYann Gautier 			return -ETIMEDOUT;
13227839a050SYann Gautier 		}
13237839a050SYann Gautier 	}
13247839a050SYann Gautier 
13257839a050SYann Gautier 	return 0;
13267839a050SYann Gautier }
13277839a050SYann Gautier 
13280d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
13297839a050SYann Gautier {
13307839a050SYann Gautier 	uint32_t value;
13310d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13327839a050SYann Gautier 
13330d21680cSYann Gautier 	if (digbyp) {
13340d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
13350d21680cSYann Gautier 	}
13360d21680cSYann Gautier 
13370d21680cSYann Gautier 	if (bypass || digbyp) {
13380d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
13397839a050SYann Gautier 	}
13407839a050SYann Gautier 
13417839a050SYann Gautier 	/*
13427839a050SYann Gautier 	 * Warning: not recommended to switch directly from "high drive"
13437839a050SYann Gautier 	 * to "medium low drive", and vice-versa.
13447839a050SYann Gautier 	 */
13450d21680cSYann Gautier 	value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
13467839a050SYann Gautier 		RCC_BDCR_LSEDRV_SHIFT;
13477839a050SYann Gautier 
13487839a050SYann Gautier 	while (value != lsedrv) {
13497839a050SYann Gautier 		if (value > lsedrv) {
13507839a050SYann Gautier 			value--;
13517839a050SYann Gautier 		} else {
13527839a050SYann Gautier 			value++;
13537839a050SYann Gautier 		}
13547839a050SYann Gautier 
13550d21680cSYann Gautier 		mmio_clrsetbits_32(rcc_base + RCC_BDCR,
13567839a050SYann Gautier 				   RCC_BDCR_LSEDRV_MASK,
13577839a050SYann Gautier 				   value << RCC_BDCR_LSEDRV_SHIFT);
13587839a050SYann Gautier 	}
13597839a050SYann Gautier 
13600d21680cSYann Gautier 	stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
13617839a050SYann Gautier }
13627839a050SYann Gautier 
13630d21680cSYann Gautier static void stm32mp1_lse_wait(void)
13647839a050SYann Gautier {
13650d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
13667839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13677839a050SYann Gautier 	}
13687839a050SYann Gautier }
13697839a050SYann Gautier 
13700d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable)
13717839a050SYann Gautier {
13720d21680cSYann Gautier 	stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
13730d21680cSYann Gautier 
13740d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
13757839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13767839a050SYann Gautier 	}
13777839a050SYann Gautier }
13787839a050SYann Gautier 
13790d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
13807839a050SYann Gautier {
13810d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13820d21680cSYann Gautier 
13830d21680cSYann Gautier 	if (digbyp) {
13840d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
13857839a050SYann Gautier 	}
13867839a050SYann Gautier 
13870d21680cSYann Gautier 	if (bypass || digbyp) {
13880d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
13890d21680cSYann Gautier 	}
13900d21680cSYann Gautier 
13910d21680cSYann Gautier 	stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
13920d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
13937839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13947839a050SYann Gautier 	}
13957839a050SYann Gautier 
13967839a050SYann Gautier 	if (css) {
13970d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
13987839a050SYann Gautier 	}
139931e9750bSLionel Debieve 
140031e9750bSLionel Debieve #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
140131e9750bSLionel Debieve 	if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) &&
140231e9750bSLionel Debieve 	    (!(digbyp || bypass))) {
140331e9750bSLionel Debieve 		panic();
140431e9750bSLionel Debieve 	}
140531e9750bSLionel Debieve #endif
14067839a050SYann Gautier }
14077839a050SYann Gautier 
14080d21680cSYann Gautier static void stm32mp1_csi_set(bool enable)
14097839a050SYann Gautier {
14100d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
14110d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
14127839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
14137839a050SYann Gautier 	}
14147839a050SYann Gautier }
14157839a050SYann Gautier 
14160d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable)
14177839a050SYann Gautier {
14180d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
14190d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
14207839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
14217839a050SYann Gautier 	}
14227839a050SYann Gautier }
14237839a050SYann Gautier 
14240d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv)
14257839a050SYann Gautier {
1426dfdb057aSYann Gautier 	uint64_t timeout;
14270d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
14280d21680cSYann Gautier 	uintptr_t address = rcc_base + RCC_OCRDYR;
14297839a050SYann Gautier 
14300d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
14317839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK,
14327839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
14337839a050SYann Gautier 
1434dfdb057aSYann Gautier 	timeout = timeout_init_us(HSIDIV_TIMEOUT);
14357839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
1436dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
14370d21680cSYann Gautier 			ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
14387839a050SYann Gautier 			      address, mmio_read_32(address));
14397839a050SYann Gautier 			return -ETIMEDOUT;
14407839a050SYann Gautier 		}
14417839a050SYann Gautier 	}
14427839a050SYann Gautier 
14437839a050SYann Gautier 	return 0;
14447839a050SYann Gautier }
14457839a050SYann Gautier 
14460d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq)
14477839a050SYann Gautier {
14487839a050SYann Gautier 	uint8_t hsidiv;
14497839a050SYann Gautier 	uint32_t hsidivfreq = MAX_HSI_HZ;
14507839a050SYann Gautier 
14517839a050SYann Gautier 	for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
14527839a050SYann Gautier 		if (hsidivfreq == hsifreq) {
14537839a050SYann Gautier 			break;
14547839a050SYann Gautier 		}
14557839a050SYann Gautier 
14567839a050SYann Gautier 		hsidivfreq /= 2U;
14577839a050SYann Gautier 	}
14587839a050SYann Gautier 
14597839a050SYann Gautier 	if (hsidiv == 4U) {
14607839a050SYann Gautier 		ERROR("Invalid clk-hsi frequency\n");
14617839a050SYann Gautier 		return -1;
14627839a050SYann Gautier 	}
14637839a050SYann Gautier 
14647839a050SYann Gautier 	if (hsidiv != 0U) {
14650d21680cSYann Gautier 		return stm32mp1_set_hsidiv(hsidiv);
14667839a050SYann Gautier 	}
14677839a050SYann Gautier 
14687839a050SYann Gautier 	return 0;
14697839a050SYann Gautier }
14707839a050SYann Gautier 
14710d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
14720d21680cSYann Gautier 				    unsigned int clksrc,
14730d21680cSYann Gautier 				    uint32_t *pllcfg, int plloff)
14747839a050SYann Gautier {
14750d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
14760d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
14770d21680cSYann Gautier 	uintptr_t pllxcr = rcc_base + pll->pllxcr;
14780d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
14790d21680cSYann Gautier 	uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
14800d21680cSYann Gautier 	unsigned long refclk;
14810d21680cSYann Gautier 	uint32_t ifrge = 0U;
1482be858cffSAndre Przywara 	uint32_t src, value, fracv = 0;
1483be858cffSAndre Przywara 	void *fdt;
14847839a050SYann Gautier 
14850d21680cSYann Gautier 	/* Check PLL output */
14860d21680cSYann Gautier 	if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
14870d21680cSYann Gautier 		return false;
14887839a050SYann Gautier 	}
14897839a050SYann Gautier 
14900d21680cSYann Gautier 	/* Check current clksrc */
14910d21680cSYann Gautier 	src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
14920d21680cSYann Gautier 	if (src != (clksrc & RCC_SELR_SRC_MASK)) {
14930d21680cSYann Gautier 		return false;
14940d21680cSYann Gautier 	}
14950d21680cSYann Gautier 
14960d21680cSYann Gautier 	/* Check Div */
14970d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
14980d21680cSYann Gautier 
14990d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
15000d21680cSYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
15010d21680cSYann Gautier 
15020d21680cSYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
15030d21680cSYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
15040d21680cSYann Gautier 		return false;
15050d21680cSYann Gautier 	}
15060d21680cSYann Gautier 
15070d21680cSYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
15080d21680cSYann Gautier 		ifrge = 1U;
15090d21680cSYann Gautier 	}
15100d21680cSYann Gautier 
15110d21680cSYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
15120d21680cSYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
15130d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
15140d21680cSYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
15150d21680cSYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
15160d21680cSYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
15170d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
15180d21680cSYann Gautier 		return false;
15190d21680cSYann Gautier 	}
15200d21680cSYann Gautier 
15210d21680cSYann Gautier 	/* Fractional configuration */
1522be858cffSAndre Przywara 	if (fdt_get_address(&fdt) == 1) {
1523be858cffSAndre Przywara 		fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1524be858cffSAndre Przywara 	}
15250d21680cSYann Gautier 
15260d21680cSYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
15270d21680cSYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
15280d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
15290d21680cSYann Gautier 		return false;
15300d21680cSYann Gautier 	}
15310d21680cSYann Gautier 
15320d21680cSYann Gautier 	/* Output config */
15330d21680cSYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
15340d21680cSYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
15350d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
15360d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
15370d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
15380d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
15390d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
15400d21680cSYann Gautier 		return false;
15410d21680cSYann Gautier 	}
15420d21680cSYann Gautier 
15430d21680cSYann Gautier 	return true;
15440d21680cSYann Gautier }
15450d21680cSYann Gautier 
15460d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
15477839a050SYann Gautier {
15480d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15490d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
15500d21680cSYann Gautier 
1551dd98aec8SYann Gautier 	/* Preserve RCC_PLLNCR_SSCG_CTRL value */
1552dd98aec8SYann Gautier 	mmio_clrsetbits_32(pllxcr,
1553dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1554dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVREN,
1555dd98aec8SYann Gautier 			   RCC_PLLNCR_PLLON);
15560d21680cSYann Gautier }
15570d21680cSYann Gautier 
15580d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
15590d21680cSYann Gautier {
15600d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15610d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1562dfdb057aSYann Gautier 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
15637839a050SYann Gautier 
15647839a050SYann Gautier 	/* Wait PLL lock */
15657839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
1566dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
1567*9fa9a0c5SYann Gautier 			ERROR("PLL%u start failed @ 0x%lx: 0x%x\n",
15687839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
15697839a050SYann Gautier 			return -ETIMEDOUT;
15707839a050SYann Gautier 		}
15717839a050SYann Gautier 	}
15727839a050SYann Gautier 
15737839a050SYann Gautier 	/* Start the requested output */
15747839a050SYann Gautier 	mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
15757839a050SYann Gautier 
15767839a050SYann Gautier 	return 0;
15777839a050SYann Gautier }
15787839a050SYann Gautier 
15790d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
15807839a050SYann Gautier {
15810d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15820d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1583dfdb057aSYann Gautier 	uint64_t timeout;
15847839a050SYann Gautier 
15857839a050SYann Gautier 	/* Stop all output */
15867839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
15877839a050SYann Gautier 			RCC_PLLNCR_DIVREN);
15887839a050SYann Gautier 
15897839a050SYann Gautier 	/* Stop PLL */
15907839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
15917839a050SYann Gautier 
1592dfdb057aSYann Gautier 	timeout = timeout_init_us(PLLRDY_TIMEOUT);
15937839a050SYann Gautier 	/* Wait PLL stopped */
15947839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
1595dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
1596*9fa9a0c5SYann Gautier 			ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n",
15977839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
15987839a050SYann Gautier 			return -ETIMEDOUT;
15997839a050SYann Gautier 		}
16007839a050SYann Gautier 	}
16017839a050SYann Gautier 
16027839a050SYann Gautier 	return 0;
16037839a050SYann Gautier }
16047839a050SYann Gautier 
16050d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
16067839a050SYann Gautier 				       uint32_t *pllcfg)
16077839a050SYann Gautier {
16080d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16090d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
16107839a050SYann Gautier 	uint32_t value;
16117839a050SYann Gautier 
16127839a050SYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
16137839a050SYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
16147839a050SYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
16157839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
16167839a050SYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
16177839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
16180d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr2, value);
16197839a050SYann Gautier }
16207839a050SYann Gautier 
16210d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
16227839a050SYann Gautier 			       uint32_t *pllcfg, uint32_t fracv)
16237839a050SYann Gautier {
16240d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16250d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
16260d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
16277839a050SYann Gautier 	unsigned long refclk;
16287839a050SYann Gautier 	uint32_t ifrge = 0;
16297839a050SYann Gautier 	uint32_t src, value;
16307839a050SYann Gautier 
16310d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) &
16327839a050SYann Gautier 		RCC_SELR_REFCLK_SRC_MASK;
16337839a050SYann Gautier 
16340d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
16357839a050SYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
16367839a050SYann Gautier 
16377839a050SYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
16387839a050SYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
16397839a050SYann Gautier 		return -EINVAL;
16407839a050SYann Gautier 	}
16417839a050SYann Gautier 
16427839a050SYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
16437839a050SYann Gautier 		ifrge = 1U;
16447839a050SYann Gautier 	}
16457839a050SYann Gautier 
16467839a050SYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
16477839a050SYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
16487839a050SYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
16497839a050SYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
16507839a050SYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
16517839a050SYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
16520d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr1, value);
16537839a050SYann Gautier 
16547839a050SYann Gautier 	/* Fractional configuration */
16557839a050SYann Gautier 	value = 0;
16560d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16577839a050SYann Gautier 
16587839a050SYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
16590d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16607839a050SYann Gautier 
16617839a050SYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
16620d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16637839a050SYann Gautier 
16640d21680cSYann Gautier 	stm32mp1_pll_config_output(pll_id, pllcfg);
16657839a050SYann Gautier 
16667839a050SYann Gautier 	return 0;
16677839a050SYann Gautier }
16687839a050SYann Gautier 
16690d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
16707839a050SYann Gautier {
16710d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16727839a050SYann Gautier 	uint32_t pllxcsg = 0;
16737839a050SYann Gautier 
16747839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
16757839a050SYann Gautier 		    RCC_PLLNCSGR_MOD_PER_MASK;
16767839a050SYann Gautier 
16777839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
16787839a050SYann Gautier 		    RCC_PLLNCSGR_INC_STEP_MASK;
16797839a050SYann Gautier 
16807839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
16817839a050SYann Gautier 		    RCC_PLLNCSGR_SSCG_MODE_MASK;
16827839a050SYann Gautier 
16830d21680cSYann Gautier 	mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
1684dd98aec8SYann Gautier 
1685dd98aec8SYann Gautier 	mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
1686dd98aec8SYann Gautier 			RCC_PLLNCR_SSCG_CTRL);
16877839a050SYann Gautier }
16887839a050SYann Gautier 
16890d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc)
16907839a050SYann Gautier {
16910d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
1692dfdb057aSYann Gautier 	uint64_t timeout;
16937839a050SYann Gautier 
16940d21680cSYann Gautier 	mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
16957839a050SYann Gautier 			   clksrc & RCC_SELR_SRC_MASK);
16967839a050SYann Gautier 
1697dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
16980d21680cSYann Gautier 	while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
1699dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
17000d21680cSYann Gautier 			ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
17010d21680cSYann Gautier 			      clksrc_address, mmio_read_32(clksrc_address));
17027839a050SYann Gautier 			return -ETIMEDOUT;
17037839a050SYann Gautier 		}
17047839a050SYann Gautier 	}
17057839a050SYann Gautier 
17067839a050SYann Gautier 	return 0;
17077839a050SYann Gautier }
17087839a050SYann Gautier 
17090d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
17107839a050SYann Gautier {
1711dfdb057aSYann Gautier 	uint64_t timeout;
17127839a050SYann Gautier 
17137839a050SYann Gautier 	mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
17147839a050SYann Gautier 			   clkdiv & RCC_DIVR_DIV_MASK);
17157839a050SYann Gautier 
1716dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
17177839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
1718dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
17190d21680cSYann Gautier 			ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
17207839a050SYann Gautier 			      clkdiv, address, mmio_read_32(address));
17217839a050SYann Gautier 			return -ETIMEDOUT;
17227839a050SYann Gautier 		}
17237839a050SYann Gautier 	}
17247839a050SYann Gautier 
17257839a050SYann Gautier 	return 0;
17267839a050SYann Gautier }
17277839a050SYann Gautier 
17280d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
17297839a050SYann Gautier {
17300d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
17317839a050SYann Gautier 
17327839a050SYann Gautier 	/*
17337839a050SYann Gautier 	 * Binding clksrc :
17347839a050SYann Gautier 	 *      bit15-4 offset
17357839a050SYann Gautier 	 *      bit3:   disable
17367839a050SYann Gautier 	 *      bit2-0: MCOSEL[2:0]
17377839a050SYann Gautier 	 */
17387839a050SYann Gautier 	if ((clksrc & 0x8U) != 0U) {
17390d21680cSYann Gautier 		mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
17407839a050SYann Gautier 	} else {
17410d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
17427839a050SYann Gautier 				   RCC_MCOCFG_MCOSRC_MASK,
17437839a050SYann Gautier 				   clksrc & RCC_MCOCFG_MCOSRC_MASK);
17440d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
17457839a050SYann Gautier 				   RCC_MCOCFG_MCODIV_MASK,
17467839a050SYann Gautier 				   clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
17470d21680cSYann Gautier 		mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
17487839a050SYann Gautier 	}
17497839a050SYann Gautier }
17507839a050SYann Gautier 
17510d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
17527839a050SYann Gautier {
17530d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
17547839a050SYann Gautier 
17557839a050SYann Gautier 	if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
17567839a050SYann Gautier 	    (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
17577839a050SYann Gautier 		mmio_clrsetbits_32(address,
17587839a050SYann Gautier 				   RCC_BDCR_RTCSRC_MASK,
175915509093SYann Gautier 				   (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
17607839a050SYann Gautier 
17617839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
17627839a050SYann Gautier 	}
17637839a050SYann Gautier 
17647839a050SYann Gautier 	if (lse_css) {
17657839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_LSECSSON);
17667839a050SYann Gautier 	}
17677839a050SYann Gautier }
17687839a050SYann Gautier 
17690d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs)
17707839a050SYann Gautier {
17710d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
17727839a050SYann Gautier 	uint32_t value = pkcs & 0xFU;
17737839a050SYann Gautier 	uint32_t mask = 0xFU;
17747839a050SYann Gautier 
17757839a050SYann Gautier 	if ((pkcs & BIT(31)) != 0U) {
17767839a050SYann Gautier 		mask <<= 4;
17777839a050SYann Gautier 		value <<= 4;
17787839a050SYann Gautier 	}
17797839a050SYann Gautier 
17807839a050SYann Gautier 	mmio_clrsetbits_32(address, mask, value);
17817839a050SYann Gautier }
17827839a050SYann Gautier 
1783964e5ff1SNicolas Le Bayon static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg,
1784964e5ff1SNicolas Le Bayon 					uint32_t *fracv, uint32_t *csg,
1785964e5ff1SNicolas Le Bayon 					bool *csg_set)
1786964e5ff1SNicolas Le Bayon {
1787964e5ff1SNicolas Le Bayon 	void *fdt;
1788964e5ff1SNicolas Le Bayon 	int ret;
1789964e5ff1SNicolas Le Bayon 
1790964e5ff1SNicolas Le Bayon 	if (fdt_get_address(&fdt) == 0) {
1791964e5ff1SNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
1792964e5ff1SNicolas Le Bayon 	}
1793964e5ff1SNicolas Le Bayon 
1794964e5ff1SNicolas Le Bayon 	ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB,
1795964e5ff1SNicolas Le Bayon 				    pllcfg);
1796964e5ff1SNicolas Le Bayon 	if (ret < 0) {
1797964e5ff1SNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
1798964e5ff1SNicolas Le Bayon 	}
1799964e5ff1SNicolas Le Bayon 
1800964e5ff1SNicolas Le Bayon 	*fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1801964e5ff1SNicolas Le Bayon 
1802964e5ff1SNicolas Le Bayon 	ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB,
1803964e5ff1SNicolas Le Bayon 				    csg);
1804964e5ff1SNicolas Le Bayon 
1805964e5ff1SNicolas Le Bayon 	*csg_set = (ret == 0);
1806964e5ff1SNicolas Le Bayon 
1807964e5ff1SNicolas Le Bayon 	if (ret == -FDT_ERR_NOTFOUND) {
1808964e5ff1SNicolas Le Bayon 		ret = 0;
1809964e5ff1SNicolas Le Bayon 	}
1810964e5ff1SNicolas Le Bayon 
1811964e5ff1SNicolas Le Bayon 	return ret;
1812964e5ff1SNicolas Le Bayon }
1813964e5ff1SNicolas Le Bayon 
18147839a050SYann Gautier int stm32mp1_clk_init(void)
18157839a050SYann Gautier {
18160d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
1817964e5ff1SNicolas Le Bayon 	uint32_t pllfracv[_PLL_NB];
1818964e5ff1SNicolas Le Bayon 	uint32_t pllcsg[_PLL_NB][PLLCSG_NB];
18197839a050SYann Gautier 	unsigned int clksrc[CLKSRC_NB];
18207839a050SYann Gautier 	unsigned int clkdiv[CLKDIV_NB];
18217839a050SYann Gautier 	unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
18227839a050SYann Gautier 	int plloff[_PLL_NB];
18237839a050SYann Gautier 	int ret, len;
18247839a050SYann Gautier 	enum stm32mp1_pll_id i;
1825964e5ff1SNicolas Le Bayon 	bool pllcsg_set[_PLL_NB];
1826964e5ff1SNicolas Le Bayon 	bool pllcfg_valid[_PLL_NB];
18277839a050SYann Gautier 	bool lse_css = false;
18280d21680cSYann Gautier 	bool pll3_preserve = false;
18290d21680cSYann Gautier 	bool pll4_preserve = false;
18300d21680cSYann Gautier 	bool pll4_bootrom = false;
18313e6fab43SYann Gautier 	const fdt32_t *pkcs_cell;
183252a616b4SAndre Przywara 	void *fdt;
1833bf1af154SPatrick Delaunay 	int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
1834bf1af154SPatrick Delaunay 	int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
183552a616b4SAndre Przywara 
183652a616b4SAndre Przywara 	if (fdt_get_address(&fdt) == 0) {
18378f97c4faSYann Gautier 		return -FDT_ERR_NOTFOUND;
183852a616b4SAndre Przywara 	}
18397839a050SYann Gautier 
184052a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
184152a616b4SAndre Przywara 					clksrc);
18427839a050SYann Gautier 	if (ret < 0) {
18437839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
18447839a050SYann Gautier 	}
18457839a050SYann Gautier 
184652a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
184752a616b4SAndre Przywara 					clkdiv);
18487839a050SYann Gautier 	if (ret < 0) {
18497839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
18507839a050SYann Gautier 	}
18517839a050SYann Gautier 
18527839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
18537839a050SYann Gautier 		char name[12];
18547839a050SYann Gautier 
1855*9fa9a0c5SYann Gautier 		snprintf(name, sizeof(name), "st,pll@%u", i);
18567839a050SYann Gautier 		plloff[i] = fdt_rcc_subnode_offset(name);
18577839a050SYann Gautier 
1858964e5ff1SNicolas Le Bayon 		pllcfg_valid[i] = fdt_check_node(plloff[i]);
1859964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
18607839a050SYann Gautier 			continue;
18617839a050SYann Gautier 		}
18627839a050SYann Gautier 
1863964e5ff1SNicolas Le Bayon 		ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i],
1864964e5ff1SNicolas Le Bayon 						   &pllfracv[i], pllcsg[i],
1865964e5ff1SNicolas Le Bayon 						   &pllcsg_set[i]);
1866964e5ff1SNicolas Le Bayon 		if (ret != 0) {
1867964e5ff1SNicolas Le Bayon 			return ret;
18687839a050SYann Gautier 		}
18697839a050SYann Gautier 	}
18707839a050SYann Gautier 
18710d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
18720d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
18737839a050SYann Gautier 
18747839a050SYann Gautier 	/*
18757839a050SYann Gautier 	 * Switch ON oscillator found in device-tree.
18767839a050SYann Gautier 	 * Note: HSI already ON after BootROM stage.
18777839a050SYann Gautier 	 */
18780d21680cSYann Gautier 	if (stm32mp1_osc[_LSI] != 0U) {
18790d21680cSYann Gautier 		stm32mp1_lsi_set(true);
18807839a050SYann Gautier 	}
18810d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
1882b208e3daSGabriel Fernandez 		const char *name = stm32mp_osc_node_label[_LSE];
18830d21680cSYann Gautier 		bool bypass, digbyp;
18847839a050SYann Gautier 		uint32_t lsedrv;
18857839a050SYann Gautier 
1886b208e3daSGabriel Fernandez 		bypass = fdt_clk_read_bool(name, "st,bypass");
1887b208e3daSGabriel Fernandez 		digbyp = fdt_clk_read_bool(name, "st,digbypass");
1888b208e3daSGabriel Fernandez 		lse_css = fdt_clk_read_bool(name, "st,css");
1889b208e3daSGabriel Fernandez 		lsedrv = fdt_clk_read_uint32_default(name, "st,drive",
18907839a050SYann Gautier 						     LSEDRV_MEDIUM_HIGH);
18910d21680cSYann Gautier 		stm32mp1_lse_enable(bypass, digbyp, lsedrv);
18927839a050SYann Gautier 	}
18930d21680cSYann Gautier 	if (stm32mp1_osc[_HSE] != 0U) {
1894b208e3daSGabriel Fernandez 		const char *name = stm32mp_osc_node_label[_HSE];
18950d21680cSYann Gautier 		bool bypass, digbyp, css;
18967839a050SYann Gautier 
1897b208e3daSGabriel Fernandez 		bypass = fdt_clk_read_bool(name, "st,bypass");
1898b208e3daSGabriel Fernandez 		digbyp = fdt_clk_read_bool(name, "st,digbypass");
1899b208e3daSGabriel Fernandez 		css = fdt_clk_read_bool(name, "st,css");
19000d21680cSYann Gautier 		stm32mp1_hse_enable(bypass, digbyp, css);
19017839a050SYann Gautier 	}
19027839a050SYann Gautier 	/*
19037839a050SYann Gautier 	 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
19047839a050SYann Gautier 	 * => switch on CSI even if node is not present in device tree
19057839a050SYann Gautier 	 */
19060d21680cSYann Gautier 	stm32mp1_csi_set(true);
19077839a050SYann Gautier 
19087839a050SYann Gautier 	/* Come back to HSI */
19090d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
19107839a050SYann Gautier 	if (ret != 0) {
19117839a050SYann Gautier 		return ret;
19127839a050SYann Gautier 	}
19130d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
19147839a050SYann Gautier 	if (ret != 0) {
19157839a050SYann Gautier 		return ret;
19167839a050SYann Gautier 	}
1917b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
1918b053a22eSYann Gautier 	if (ret != 0) {
1919b053a22eSYann Gautier 		return ret;
1920b053a22eSYann Gautier 	}
19217839a050SYann Gautier 
19220d21680cSYann Gautier 	if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
19230d21680cSYann Gautier 	     RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
19240d21680cSYann Gautier 		pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
19250d21680cSYann Gautier 							clksrc[CLKSRC_PLL3],
19260d21680cSYann Gautier 							pllcfg[_PLL3],
19270d21680cSYann Gautier 							plloff[_PLL3]);
19280d21680cSYann Gautier 		pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
19290d21680cSYann Gautier 							clksrc[CLKSRC_PLL4],
19300d21680cSYann Gautier 							pllcfg[_PLL4],
19310d21680cSYann Gautier 							plloff[_PLL4]);
19320d21680cSYann Gautier 	}
1933bf1af154SPatrick Delaunay 	/* Don't initialize PLL4, when used by BOOTROM */
1934bf1af154SPatrick Delaunay 	if ((stm32mp_get_boot_itf_selected() ==
1935bf1af154SPatrick Delaunay 	     BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) &&
1936bf1af154SPatrick Delaunay 	    ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
1937bf1af154SPatrick Delaunay 		pll4_bootrom = true;
1938bf1af154SPatrick Delaunay 		pll4_preserve = true;
1939bf1af154SPatrick Delaunay 	}
19400d21680cSYann Gautier 
19417839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
19420d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
19430d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve)) {
19447839a050SYann Gautier 			continue;
19450d21680cSYann Gautier 		}
19460d21680cSYann Gautier 
19470d21680cSYann Gautier 		ret = stm32mp1_pll_stop(i);
19487839a050SYann Gautier 		if (ret != 0) {
19497839a050SYann Gautier 			return ret;
19507839a050SYann Gautier 		}
19517839a050SYann Gautier 	}
19527839a050SYann Gautier 
19537839a050SYann Gautier 	/* Configure HSIDIV */
19540d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] != 0U) {
19550d21680cSYann Gautier 		ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
19567839a050SYann Gautier 		if (ret != 0) {
19577839a050SYann Gautier 			return ret;
19587839a050SYann Gautier 		}
1959591d80c8SLionel Debieve 
1960591d80c8SLionel Debieve 		stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K));
19617839a050SYann Gautier 	}
19627839a050SYann Gautier 
19637839a050SYann Gautier 	/* Select DIV */
19647839a050SYann Gautier 	/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
19650d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_MPCKDIVR,
19667839a050SYann Gautier 		      clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
19670d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
19687839a050SYann Gautier 	if (ret != 0) {
19697839a050SYann Gautier 		return ret;
19707839a050SYann Gautier 	}
19710d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
19727839a050SYann Gautier 	if (ret != 0) {
19737839a050SYann Gautier 		return ret;
19747839a050SYann Gautier 	}
19750d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
19767839a050SYann Gautier 	if (ret != 0) {
19777839a050SYann Gautier 		return ret;
19787839a050SYann Gautier 	}
1979b053a22eSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
1980b053a22eSYann Gautier 	if (ret != 0) {
1981b053a22eSYann Gautier 		return ret;
1982b053a22eSYann Gautier 	}
19830d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
19847839a050SYann Gautier 	if (ret != 0) {
19857839a050SYann Gautier 		return ret;
19867839a050SYann Gautier 	}
19870d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
19887839a050SYann Gautier 	if (ret != 0) {
19897839a050SYann Gautier 		return ret;
19907839a050SYann Gautier 	}
19910d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
19927839a050SYann Gautier 	if (ret != 0) {
19937839a050SYann Gautier 		return ret;
19947839a050SYann Gautier 	}
19957839a050SYann Gautier 
19967839a050SYann Gautier 	/* No ready bit for RTC */
19970d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_RTCDIVR,
19987839a050SYann Gautier 		      clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
19997839a050SYann Gautier 
20007839a050SYann Gautier 	/* Configure PLLs source */
20010d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
20027839a050SYann Gautier 	if (ret != 0) {
20037839a050SYann Gautier 		return ret;
20047839a050SYann Gautier 	}
20057839a050SYann Gautier 
20060d21680cSYann Gautier 	if (!pll3_preserve) {
20070d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
20087839a050SYann Gautier 		if (ret != 0) {
20097839a050SYann Gautier 			return ret;
20107839a050SYann Gautier 		}
20110d21680cSYann Gautier 	}
20120d21680cSYann Gautier 
20130d21680cSYann Gautier 	if (!pll4_preserve) {
20140d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
20150d21680cSYann Gautier 		if (ret != 0) {
20160d21680cSYann Gautier 			return ret;
20170d21680cSYann Gautier 		}
20180d21680cSYann Gautier 	}
20197839a050SYann Gautier 
20207839a050SYann Gautier 	/* Configure and start PLLs */
20217839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
20220d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
20230d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
20240d21680cSYann Gautier 			continue;
20250d21680cSYann Gautier 		}
20260d21680cSYann Gautier 
2027964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
20287839a050SYann Gautier 			continue;
20297839a050SYann Gautier 		}
20307839a050SYann Gautier 
20310d21680cSYann Gautier 		if ((i == _PLL4) && pll4_bootrom) {
20320d21680cSYann Gautier 			/* Set output divider if not done by the Bootrom */
20330d21680cSYann Gautier 			stm32mp1_pll_config_output(i, pllcfg[i]);
20340d21680cSYann Gautier 			continue;
20350d21680cSYann Gautier 		}
20360d21680cSYann Gautier 
2037964e5ff1SNicolas Le Bayon 		ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]);
20387839a050SYann Gautier 		if (ret != 0) {
20397839a050SYann Gautier 			return ret;
20407839a050SYann Gautier 		}
2041964e5ff1SNicolas Le Bayon 
2042964e5ff1SNicolas Le Bayon 		if (pllcsg_set[i]) {
2043964e5ff1SNicolas Le Bayon 			stm32mp1_pll_csg(i, pllcsg[i]);
20447839a050SYann Gautier 		}
20457839a050SYann Gautier 
20460d21680cSYann Gautier 		stm32mp1_pll_start(i);
20477839a050SYann Gautier 	}
20487839a050SYann Gautier 	/* Wait and start PLLs ouptut when ready */
20497839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
2050964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
20517839a050SYann Gautier 			continue;
20527839a050SYann Gautier 		}
20537839a050SYann Gautier 
20540d21680cSYann Gautier 		ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
20557839a050SYann Gautier 		if (ret != 0) {
20567839a050SYann Gautier 			return ret;
20577839a050SYann Gautier 		}
20587839a050SYann Gautier 	}
20597839a050SYann Gautier 	/* Wait LSE ready before to use it */
20600d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
20610d21680cSYann Gautier 		stm32mp1_lse_wait();
20627839a050SYann Gautier 	}
20637839a050SYann Gautier 
20647839a050SYann Gautier 	/* Configure with expected clock source */
20650d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
20667839a050SYann Gautier 	if (ret != 0) {
20677839a050SYann Gautier 		return ret;
20687839a050SYann Gautier 	}
20690d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
20707839a050SYann Gautier 	if (ret != 0) {
20717839a050SYann Gautier 		return ret;
20727839a050SYann Gautier 	}
2073b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
2074b053a22eSYann Gautier 	if (ret != 0) {
2075b053a22eSYann Gautier 		return ret;
2076b053a22eSYann Gautier 	}
20770d21680cSYann Gautier 	stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
20787839a050SYann Gautier 
20797839a050SYann Gautier 	/* Configure PKCK */
20807839a050SYann Gautier 	pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
20817839a050SYann Gautier 	if (pkcs_cell != NULL) {
20827839a050SYann Gautier 		bool ckper_disabled = false;
20837839a050SYann Gautier 		uint32_t j;
2084bf1af154SPatrick Delaunay 		uint32_t usbreg_bootrom = 0U;
2085bf1af154SPatrick Delaunay 
2086bf1af154SPatrick Delaunay 		if (pll4_bootrom) {
2087bf1af154SPatrick Delaunay 			usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
2088bf1af154SPatrick Delaunay 		}
20897839a050SYann Gautier 
20907839a050SYann Gautier 		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
20913e6fab43SYann Gautier 			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
20927839a050SYann Gautier 
20937839a050SYann Gautier 			if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
20947839a050SYann Gautier 				ckper_disabled = true;
20957839a050SYann Gautier 				continue;
20967839a050SYann Gautier 			}
20970d21680cSYann Gautier 			stm32mp1_pkcs_config(pkcs);
20987839a050SYann Gautier 		}
20997839a050SYann Gautier 
21007839a050SYann Gautier 		/*
21017839a050SYann Gautier 		 * CKPER is source for some peripheral clocks
21027839a050SYann Gautier 		 * (FMC-NAND / QPSI-NOR) and switching source is allowed
21037839a050SYann Gautier 		 * only if previous clock is still ON
21047839a050SYann Gautier 		 * => deactivated CKPER only after switching clock
21057839a050SYann Gautier 		 */
21067839a050SYann Gautier 		if (ckper_disabled) {
21070d21680cSYann Gautier 			stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
21087839a050SYann Gautier 		}
2109bf1af154SPatrick Delaunay 
2110bf1af154SPatrick Delaunay 		if (pll4_bootrom) {
2111bf1af154SPatrick Delaunay 			uint32_t usbreg_value, usbreg_mask;
2112bf1af154SPatrick Delaunay 			const struct stm32mp1_clk_sel *sel;
2113bf1af154SPatrick Delaunay 
2114bf1af154SPatrick Delaunay 			sel = clk_sel_ref(_USBPHY_SEL);
2115bf1af154SPatrick Delaunay 			usbreg_mask = (uint32_t)sel->msk << sel->src;
2116bf1af154SPatrick Delaunay 			sel = clk_sel_ref(_USBO_SEL);
2117bf1af154SPatrick Delaunay 			usbreg_mask |= (uint32_t)sel->msk << sel->src;
2118bf1af154SPatrick Delaunay 
2119bf1af154SPatrick Delaunay 			usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
2120bf1af154SPatrick Delaunay 				       usbreg_mask;
2121bf1af154SPatrick Delaunay 			usbreg_bootrom &= usbreg_mask;
2122bf1af154SPatrick Delaunay 			if (usbreg_bootrom != usbreg_value) {
2123bf1af154SPatrick Delaunay 				VERBOSE("forbidden new USB clk path\n");
2124bf1af154SPatrick Delaunay 				VERBOSE("vs bootrom on USB boot\n");
2125bf1af154SPatrick Delaunay 				return -FDT_ERR_BADVALUE;
2126bf1af154SPatrick Delaunay 			}
2127bf1af154SPatrick Delaunay 		}
21287839a050SYann Gautier 	}
21297839a050SYann Gautier 
21307839a050SYann Gautier 	/* Switch OFF HSI if not found in device-tree */
21310d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] == 0U) {
21320d21680cSYann Gautier 		stm32mp1_hsi_set(false);
21337839a050SYann Gautier 	}
2134591d80c8SLionel Debieve 
2135591d80c8SLionel Debieve 	stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K));
21367839a050SYann Gautier 
21377839a050SYann Gautier 	/* Software Self-Refresh mode (SSR) during DDR initilialization */
21380d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
21397839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_MASK,
21407839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SSR <<
21417839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SHIFT);
21427839a050SYann Gautier 
21437839a050SYann Gautier 	return 0;
21447839a050SYann Gautier }
21457839a050SYann Gautier 
21467839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name,
21477839a050SYann Gautier 				  enum stm32mp_osc_id index)
21487839a050SYann Gautier {
21497839a050SYann Gautier 	uint32_t frequency;
21507839a050SYann Gautier 
21510d21680cSYann Gautier 	if (fdt_osc_read_freq(name, &frequency) == 0) {
21520d21680cSYann Gautier 		stm32mp1_osc[index] = frequency;
21537839a050SYann Gautier 	}
21547839a050SYann Gautier }
21557839a050SYann Gautier 
21567839a050SYann Gautier static void stm32mp1_osc_init(void)
21577839a050SYann Gautier {
21587839a050SYann Gautier 	enum stm32mp_osc_id i;
21597839a050SYann Gautier 
21607839a050SYann Gautier 	for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
21610d21680cSYann Gautier 		stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
21627839a050SYann Gautier 	}
21637839a050SYann Gautier }
21647839a050SYann Gautier 
216537e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES
216637e8295aSEtienne Carriere /*
216737e8295aSEtienne Carriere  * Get the parent ID of the target parent clock, for tagging as secure
216837e8295aSEtienne Carriere  * shared clock dependencies.
216937e8295aSEtienne Carriere  */
217037e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id)
217137e8295aSEtienne Carriere {
217237e8295aSEtienne Carriere 	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
217337e8295aSEtienne Carriere 	enum stm32mp1_pll_id pll_id;
217437e8295aSEtienne Carriere 	uint32_t p_sel;
217537e8295aSEtienne Carriere 	uintptr_t rcc_base = stm32mp_rcc_base();
217637e8295aSEtienne Carriere 
217737e8295aSEtienne Carriere 	switch (parent_id) {
217837e8295aSEtienne Carriere 	case _ACLK:
217937e8295aSEtienne Carriere 	case _PCLK4:
218037e8295aSEtienne Carriere 	case _PCLK5:
218137e8295aSEtienne Carriere 		s = _AXIS_SEL;
218237e8295aSEtienne Carriere 		break;
218337e8295aSEtienne Carriere 	case _PLL1_P:
218437e8295aSEtienne Carriere 	case _PLL1_Q:
218537e8295aSEtienne Carriere 	case _PLL1_R:
218637e8295aSEtienne Carriere 		pll_id = _PLL1;
218737e8295aSEtienne Carriere 		break;
218837e8295aSEtienne Carriere 	case _PLL2_P:
218937e8295aSEtienne Carriere 	case _PLL2_Q:
219037e8295aSEtienne Carriere 	case _PLL2_R:
219137e8295aSEtienne Carriere 		pll_id = _PLL2;
219237e8295aSEtienne Carriere 		break;
219337e8295aSEtienne Carriere 	case _PLL3_P:
219437e8295aSEtienne Carriere 	case _PLL3_Q:
219537e8295aSEtienne Carriere 	case _PLL3_R:
219637e8295aSEtienne Carriere 		pll_id = _PLL3;
219737e8295aSEtienne Carriere 		break;
219837e8295aSEtienne Carriere 	case _PLL4_P:
219937e8295aSEtienne Carriere 	case _PLL4_Q:
220037e8295aSEtienne Carriere 	case _PLL4_R:
220137e8295aSEtienne Carriere 		pll_id = _PLL4;
220237e8295aSEtienne Carriere 		break;
220337e8295aSEtienne Carriere 	case _PCLK1:
220437e8295aSEtienne Carriere 	case _PCLK2:
220537e8295aSEtienne Carriere 	case _HCLK2:
220637e8295aSEtienne Carriere 	case _HCLK6:
220737e8295aSEtienne Carriere 	case _CK_PER:
220837e8295aSEtienne Carriere 	case _CK_MPU:
220937e8295aSEtienne Carriere 	case _CK_MCU:
221037e8295aSEtienne Carriere 	case _USB_PHY_48:
221137e8295aSEtienne Carriere 		/* We do not expect to access these */
221237e8295aSEtienne Carriere 		panic();
221337e8295aSEtienne Carriere 		break;
221437e8295aSEtienne Carriere 	default:
221537e8295aSEtienne Carriere 		/* Other parents have no parent */
221637e8295aSEtienne Carriere 		return -1;
221737e8295aSEtienne Carriere 	}
221837e8295aSEtienne Carriere 
221937e8295aSEtienne Carriere 	if (s != _UNKNOWN_SEL) {
222037e8295aSEtienne Carriere 		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
222137e8295aSEtienne Carriere 
222237e8295aSEtienne Carriere 		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
222337e8295aSEtienne Carriere 			sel->msk;
222437e8295aSEtienne Carriere 
222537e8295aSEtienne Carriere 		if (p_sel < sel->nb_parent) {
222637e8295aSEtienne Carriere 			return (int)sel->parent[p_sel];
222737e8295aSEtienne Carriere 		}
222837e8295aSEtienne Carriere 	} else {
222937e8295aSEtienne Carriere 		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
223037e8295aSEtienne Carriere 
223137e8295aSEtienne Carriere 		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
223237e8295aSEtienne Carriere 			RCC_SELR_REFCLK_SRC_MASK;
223337e8295aSEtienne Carriere 
223437e8295aSEtienne Carriere 		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
223537e8295aSEtienne Carriere 			return (int)pll->refclk[p_sel];
223637e8295aSEtienne Carriere 		}
223737e8295aSEtienne Carriere 	}
223837e8295aSEtienne Carriere 
223937e8295aSEtienne Carriere 	VERBOSE("No parent selected for %s\n",
224037e8295aSEtienne Carriere 		stm32mp1_clk_parent_name[parent_id]);
224137e8295aSEtienne Carriere 
224237e8295aSEtienne Carriere 	return -1;
224337e8295aSEtienne Carriere }
224437e8295aSEtienne Carriere 
224537e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id)
224637e8295aSEtienne Carriere {
224737e8295aSEtienne Carriere 	int grandparent_id;
224837e8295aSEtienne Carriere 
224937e8295aSEtienne Carriere 	switch (parent_id) {
225037e8295aSEtienne Carriere 	case _PLL3_P:
225137e8295aSEtienne Carriere 	case _PLL3_Q:
225237e8295aSEtienne Carriere 	case _PLL3_R:
225337e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
225437e8295aSEtienne Carriere 		break;
225537e8295aSEtienne Carriere 
225637e8295aSEtienne Carriere 	/* These clocks are always secure when RCC is secure */
225737e8295aSEtienne Carriere 	case _ACLK:
225837e8295aSEtienne Carriere 	case _HCLK2:
225937e8295aSEtienne Carriere 	case _HCLK6:
226037e8295aSEtienne Carriere 	case _PCLK4:
226137e8295aSEtienne Carriere 	case _PCLK5:
226237e8295aSEtienne Carriere 	case _PLL1_P:
226337e8295aSEtienne Carriere 	case _PLL1_Q:
226437e8295aSEtienne Carriere 	case _PLL1_R:
226537e8295aSEtienne Carriere 	case _PLL2_P:
226637e8295aSEtienne Carriere 	case _PLL2_Q:
226737e8295aSEtienne Carriere 	case _PLL2_R:
226837e8295aSEtienne Carriere 	case _HSI:
226937e8295aSEtienne Carriere 	case _HSI_KER:
227037e8295aSEtienne Carriere 	case _LSI:
227137e8295aSEtienne Carriere 	case _CSI:
227237e8295aSEtienne Carriere 	case _CSI_KER:
227337e8295aSEtienne Carriere 	case _HSE:
227437e8295aSEtienne Carriere 	case _HSE_KER:
227537e8295aSEtienne Carriere 	case _HSE_KER_DIV2:
2276cbd2e8a6SGabriel Fernandez 	case _HSE_RTC:
227737e8295aSEtienne Carriere 	case _LSE:
227837e8295aSEtienne Carriere 		break;
227937e8295aSEtienne Carriere 
228037e8295aSEtienne Carriere 	default:
228137e8295aSEtienne Carriere 		VERBOSE("Cannot secure parent clock %s\n",
228237e8295aSEtienne Carriere 			stm32mp1_clk_parent_name[parent_id]);
228337e8295aSEtienne Carriere 		panic();
228437e8295aSEtienne Carriere 	}
228537e8295aSEtienne Carriere 
228637e8295aSEtienne Carriere 	grandparent_id = get_parent_id_parent(parent_id);
228737e8295aSEtienne Carriere 	if (grandparent_id >= 0) {
228837e8295aSEtienne Carriere 		secure_parent_clocks(grandparent_id);
228937e8295aSEtienne Carriere 	}
229037e8295aSEtienne Carriere }
229137e8295aSEtienne Carriere 
229237e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
229337e8295aSEtienne Carriere {
229437e8295aSEtienne Carriere 	int parent_id;
229537e8295aSEtienne Carriere 
229637e8295aSEtienne Carriere 	if (!stm32mp1_rcc_is_secure()) {
229737e8295aSEtienne Carriere 		return;
229837e8295aSEtienne Carriere 	}
229937e8295aSEtienne Carriere 
230037e8295aSEtienne Carriere 	switch (clock_id) {
230137e8295aSEtienne Carriere 	case PLL1:
230237e8295aSEtienne Carriere 	case PLL2:
230337e8295aSEtienne Carriere 		/* PLL1/PLL2 are always secure: nothing to do */
230437e8295aSEtienne Carriere 		break;
230537e8295aSEtienne Carriere 	case PLL3:
230637e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
230737e8295aSEtienne Carriere 		break;
230837e8295aSEtienne Carriere 	case PLL4:
230937e8295aSEtienne Carriere 		ERROR("PLL4 cannot be secured\n");
231037e8295aSEtienne Carriere 		panic();
231137e8295aSEtienne Carriere 		break;
231237e8295aSEtienne Carriere 	default:
231337e8295aSEtienne Carriere 		/* Others are expected gateable clock */
231437e8295aSEtienne Carriere 		parent_id = stm32mp1_clk_get_parent(clock_id);
231537e8295aSEtienne Carriere 		if (parent_id < 0) {
231637e8295aSEtienne Carriere 			INFO("No parent found for clock %lu\n", clock_id);
231737e8295aSEtienne Carriere 		} else {
231837e8295aSEtienne Carriere 			secure_parent_clocks(parent_id);
231937e8295aSEtienne Carriere 		}
232037e8295aSEtienne Carriere 		break;
232137e8295aSEtienne Carriere 	}
232237e8295aSEtienne Carriere }
232337e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */
232437e8295aSEtienne Carriere 
23256cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void)
23266cb45f89SYann Gautier {
2327033b6c3aSEtienne Carriere 	unsigned int idx;
2328033b6c3aSEtienne Carriere 	const unsigned long secure_enable[] = {
2329033b6c3aSEtienne Carriere 		AXIDCG,
2330033b6c3aSEtienne Carriere 		BSEC,
2331033b6c3aSEtienne Carriere 		DDRC1, DDRC1LP,
2332033b6c3aSEtienne Carriere 		DDRC2, DDRC2LP,
2333033b6c3aSEtienne Carriere 		DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
2334033b6c3aSEtienne Carriere 		DDRPHYC, DDRPHYCLP,
2335373f06beSLionel Debieve 		RTCAPB,
2336033b6c3aSEtienne Carriere 		TZC1, TZC2,
2337033b6c3aSEtienne Carriere 		TZPC,
2338033b6c3aSEtienne Carriere 		STGEN_K,
2339033b6c3aSEtienne Carriere 	};
2340033b6c3aSEtienne Carriere 
2341033b6c3aSEtienne Carriere 	for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
2342033b6c3aSEtienne Carriere 		stm32mp_clk_enable(secure_enable[idx]);
2343033b6c3aSEtienne Carriere 	}
23446cb45f89SYann Gautier }
23456cb45f89SYann Gautier 
234633667d29SYann Gautier static const struct clk_ops stm32mp_clk_ops = {
234733667d29SYann Gautier 	.enable		= stm32mp_clk_enable,
234833667d29SYann Gautier 	.disable	= stm32mp_clk_disable,
234933667d29SYann Gautier 	.is_enabled	= stm32mp_clk_is_enabled,
235033667d29SYann Gautier 	.get_rate	= stm32mp_clk_get_rate,
235133667d29SYann Gautier 	.get_parent	= stm32mp1_clk_get_parent,
235233667d29SYann Gautier };
235333667d29SYann Gautier 
23547839a050SYann Gautier int stm32mp1_clk_probe(void)
23557839a050SYann Gautier {
2356812daf91SLionel Debieve #if defined(IMAGE_BL32)
2357812daf91SLionel Debieve 	if (!fdt_get_rcc_secure_state()) {
2358812daf91SLionel Debieve 		mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U);
2359812daf91SLionel Debieve 	}
2360812daf91SLionel Debieve #endif
2361812daf91SLionel Debieve 
23627839a050SYann Gautier 	stm32mp1_osc_init();
23637839a050SYann Gautier 
23646cb45f89SYann Gautier 	sync_earlyboot_clocks_state();
23656cb45f89SYann Gautier 
236633667d29SYann Gautier 	clk_register(&stm32mp_clk_ops);
236733667d29SYann Gautier 
23687839a050SYann Gautier 	return 0;
23697839a050SYann Gautier }
2370