xref: /rk3399_ARM-atf/drivers/st/clk/stm32mp1_clk.c (revision 1b491eead580d7849a45a38f2c6a935a5d8d1160)
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 };
2367839a050SYann Gautier 
2377839a050SYann Gautier struct stm32mp1_clk_gate {
2387839a050SYann Gautier 	uint16_t offset;
2397839a050SYann Gautier 	uint8_t bit;
2407839a050SYann Gautier 	uint8_t index;
2417839a050SYann Gautier 	uint8_t set_clr;
242aaa09b71SYann Gautier 	uint8_t secure;
2430d21680cSYann Gautier 	uint8_t sel; /* Relates to enum stm32mp1_parent_sel */
2440d21680cSYann Gautier 	uint8_t fixed; /* Relates to enum stm32mp1_parent_id */
2457839a050SYann Gautier };
2467839a050SYann Gautier 
2477839a050SYann Gautier struct stm32mp1_clk_sel {
2487839a050SYann Gautier 	uint16_t offset;
2497839a050SYann Gautier 	uint8_t src;
2507839a050SYann Gautier 	uint8_t msk;
2517839a050SYann Gautier 	uint8_t nb_parent;
2527839a050SYann Gautier 	const uint8_t *parent;
2537839a050SYann Gautier };
2547839a050SYann Gautier 
2557839a050SYann Gautier #define REFCLK_SIZE 4
2567839a050SYann Gautier struct stm32mp1_clk_pll {
2577839a050SYann Gautier 	enum stm32mp1_plltype plltype;
2587839a050SYann Gautier 	uint16_t rckxselr;
2597839a050SYann Gautier 	uint16_t pllxcfgr1;
2607839a050SYann Gautier 	uint16_t pllxcfgr2;
2617839a050SYann Gautier 	uint16_t pllxfracr;
2627839a050SYann Gautier 	uint16_t pllxcr;
2637839a050SYann Gautier 	uint16_t pllxcsgr;
2647839a050SYann Gautier 	enum stm32mp_osc_id refclk[REFCLK_SIZE];
2657839a050SYann Gautier };
2667839a050SYann Gautier 
2670d21680cSYann Gautier /* Clocks with selectable source and non set/clr register access */
268aaa09b71SYann Gautier #define _CLK_SELEC(sec, off, b, idx, s)			\
2697839a050SYann Gautier 	{						\
2707839a050SYann Gautier 		.offset = (off),			\
2717839a050SYann Gautier 		.bit = (b),				\
2727839a050SYann Gautier 		.index = (idx),				\
2737839a050SYann Gautier 		.set_clr = 0,				\
274aaa09b71SYann Gautier 		.secure = (sec),			\
2757839a050SYann Gautier 		.sel = (s),				\
2767839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
2777839a050SYann Gautier 	}
2787839a050SYann Gautier 
2790d21680cSYann Gautier /* Clocks with fixed source and non set/clr register access */
280aaa09b71SYann Gautier #define _CLK_FIXED(sec, off, b, idx, f)			\
2817839a050SYann Gautier 	{						\
2827839a050SYann Gautier 		.offset = (off),			\
2837839a050SYann Gautier 		.bit = (b),				\
2847839a050SYann Gautier 		.index = (idx),				\
2857839a050SYann Gautier 		.set_clr = 0,				\
286aaa09b71SYann Gautier 		.secure = (sec),			\
2877839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
2887839a050SYann Gautier 		.fixed = (f),				\
2897839a050SYann Gautier 	}
2907839a050SYann Gautier 
2910d21680cSYann Gautier /* Clocks with selectable source and set/clr register access */
292aaa09b71SYann Gautier #define _CLK_SC_SELEC(sec, off, b, idx, s)			\
2937839a050SYann Gautier 	{						\
2947839a050SYann Gautier 		.offset = (off),			\
2957839a050SYann Gautier 		.bit = (b),				\
2967839a050SYann Gautier 		.index = (idx),				\
2977839a050SYann Gautier 		.set_clr = 1,				\
298aaa09b71SYann Gautier 		.secure = (sec),			\
2997839a050SYann Gautier 		.sel = (s),				\
3007839a050SYann Gautier 		.fixed = _UNKNOWN_ID,			\
3017839a050SYann Gautier 	}
3027839a050SYann Gautier 
3030d21680cSYann Gautier /* Clocks with fixed source and set/clr register access */
304aaa09b71SYann Gautier #define _CLK_SC_FIXED(sec, off, b, idx, f)			\
3057839a050SYann Gautier 	{						\
3067839a050SYann Gautier 		.offset = (off),			\
3077839a050SYann Gautier 		.bit = (b),				\
3087839a050SYann Gautier 		.index = (idx),				\
3097839a050SYann Gautier 		.set_clr = 1,				\
310aaa09b71SYann Gautier 		.secure = (sec),			\
3117839a050SYann Gautier 		.sel = _UNKNOWN_SEL,			\
3127839a050SYann Gautier 		.fixed = (f),				\
3137839a050SYann Gautier 	}
3147839a050SYann Gautier 
315d4151d2fSYann Gautier #define _CLK_PARENT_SEL(_label, _rcc_selr, _parents)		\
316d4151d2fSYann Gautier 	[_ ## _label ## _SEL] = {				\
317d4151d2fSYann Gautier 		.offset = _rcc_selr,				\
318d4151d2fSYann Gautier 		.src = _rcc_selr ## _ ## _label ## SRC_SHIFT,	\
3198ae08dcdSEtienne Carriere 		.msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \
3208ae08dcdSEtienne Carriere 		       (_rcc_selr ## _ ## _label ## SRC_SHIFT), \
321d4151d2fSYann Gautier 		.parent = (_parents),				\
322d4151d2fSYann Gautier 		.nb_parent = ARRAY_SIZE(_parents)		\
3237839a050SYann Gautier 	}
3247839a050SYann Gautier 
3250d21680cSYann Gautier #define _CLK_PLL(idx, type, off1, off2, off3,		\
3267839a050SYann Gautier 		 off4, off5, off6,			\
3277839a050SYann Gautier 		 p1, p2, p3, p4)			\
3287839a050SYann Gautier 	[(idx)] = {					\
3297839a050SYann Gautier 		.plltype = (type),			\
3307839a050SYann Gautier 		.rckxselr = (off1),			\
3317839a050SYann Gautier 		.pllxcfgr1 = (off2),			\
3327839a050SYann Gautier 		.pllxcfgr2 = (off3),			\
3337839a050SYann Gautier 		.pllxfracr = (off4),			\
3347839a050SYann Gautier 		.pllxcr = (off5),			\
3357839a050SYann Gautier 		.pllxcsgr = (off6),			\
3367839a050SYann Gautier 		.refclk[0] = (p1),			\
3377839a050SYann Gautier 		.refclk[1] = (p2),			\
3387839a050SYann Gautier 		.refclk[2] = (p3),			\
3397839a050SYann Gautier 		.refclk[3] = (p4),			\
3407839a050SYann Gautier 	}
3417839a050SYann Gautier 
3420d21680cSYann Gautier #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
3430d21680cSYann Gautier 
344aaa09b71SYann Gautier #define SEC		1
345aaa09b71SYann Gautier #define N_S		0
346aaa09b71SYann Gautier 
3477839a050SYann Gautier static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
348aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK),
349aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK),
350aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK),
351aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK),
352aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
353aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R),
354aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4),
355aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4),
356aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK),
357aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4),
358aaa09b71SYann Gautier 	_CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4),
3597839a050SYann Gautier 
3607418cf39SYann Gautier #if defined(IMAGE_BL32)
361aaa09b71SYann Gautier 	_CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1),
3627418cf39SYann Gautier #endif
363aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
364aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
365aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
366aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
367aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
368aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
369aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL),
370aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL),
371aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL),
372aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
3737839a050SYann Gautier 
3747418cf39SYann Gautier #if defined(IMAGE_BL32)
375aaa09b71SYann Gautier 	_CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2),
3767418cf39SYann Gautier #endif
377aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
3787839a050SYann Gautier 
379aaa09b71SYann Gautier 	_CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID),
380f33b2433SYann Gautier 
381aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
382aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
383aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
3847839a050SYann Gautier 
385aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
386aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
387aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
388aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL),
389aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
390aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5),
391aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5),
392aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5),
393aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5),
394aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5),
395aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
3967839a050SYann Gautier 
3977418cf39SYann Gautier #if defined(IMAGE_BL32)
398aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
399aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
4007418cf39SYann Gautier #endif
4017839a050SYann Gautier 
402aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
403aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
404aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
405aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
406aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
407aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
408aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
409aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
410aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
411aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
412aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
4137839a050SYann Gautier 
414aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5),
415aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5),
416aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5),
417aaa09b71SYann Gautier 	_CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL),
418aaa09b71SYann Gautier 	_CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5),
4197839a050SYann Gautier 
4207418cf39SYann Gautier #if defined(IMAGE_BL2)
421aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
422aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
4237418cf39SYann Gautier #endif
424aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
425aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
4267418cf39SYann Gautier #if defined(IMAGE_BL32)
427aaa09b71SYann Gautier 	_CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
4287418cf39SYann Gautier #endif
4297839a050SYann Gautier 
430aaa09b71SYann Gautier 	_CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL),
431aaa09b71SYann Gautier 	_CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
4327839a050SYann Gautier };
4337839a050SYann Gautier 
4340d21680cSYann Gautier static const uint8_t i2c12_parents[] = {
4350d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4360d21680cSYann Gautier };
4370d21680cSYann Gautier 
4380d21680cSYann Gautier static const uint8_t i2c35_parents[] = {
4390d21680cSYann Gautier 	_PCLK1, _PLL4_R, _HSI_KER, _CSI_KER
4400d21680cSYann Gautier };
4410d21680cSYann Gautier 
4420d21680cSYann Gautier static const uint8_t stgen_parents[] = {
4430d21680cSYann Gautier 	_HSI_KER, _HSE_KER
4440d21680cSYann Gautier };
4450d21680cSYann Gautier 
4460d21680cSYann Gautier static const uint8_t i2c46_parents[] = {
4470d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER
4480d21680cSYann Gautier };
4490d21680cSYann Gautier 
4500d21680cSYann Gautier static const uint8_t spi6_parents[] = {
4510d21680cSYann Gautier 	_PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q
4520d21680cSYann Gautier };
4530d21680cSYann Gautier 
4540d21680cSYann Gautier static const uint8_t usart1_parents[] = {
4550d21680cSYann Gautier 	_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER
4560d21680cSYann Gautier };
4570d21680cSYann Gautier 
4580d21680cSYann Gautier static const uint8_t rng1_parents[] = {
4590d21680cSYann Gautier 	_CSI, _PLL4_R, _LSE, _LSI
4600d21680cSYann Gautier };
4610d21680cSYann Gautier 
4620d21680cSYann Gautier static const uint8_t uart6_parents[] = {
4630d21680cSYann Gautier 	_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4640d21680cSYann Gautier };
4650d21680cSYann Gautier 
4660d21680cSYann Gautier static const uint8_t uart234578_parents[] = {
4670d21680cSYann Gautier 	_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER
4680d21680cSYann Gautier };
4690d21680cSYann Gautier 
4700d21680cSYann Gautier static const uint8_t sdmmc12_parents[] = {
4710d21680cSYann Gautier 	_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER
4720d21680cSYann Gautier };
4730d21680cSYann Gautier 
4740d21680cSYann Gautier static const uint8_t sdmmc3_parents[] = {
4750d21680cSYann Gautier 	_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER
4760d21680cSYann Gautier };
4770d21680cSYann Gautier 
4780d21680cSYann Gautier static const uint8_t qspi_parents[] = {
4790d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4800d21680cSYann Gautier };
4810d21680cSYann Gautier 
4820d21680cSYann Gautier static const uint8_t fmc_parents[] = {
4830d21680cSYann Gautier 	_ACLK, _PLL3_R, _PLL4_P, _CK_PER
4840d21680cSYann Gautier };
4850d21680cSYann Gautier 
486b8fe48b6SEtienne Carriere static const uint8_t axiss_parents[] = {
487b8fe48b6SEtienne Carriere 	_HSI, _HSE, _PLL2_P
4880d21680cSYann Gautier };
4890d21680cSYann Gautier 
490b8fe48b6SEtienne Carriere static const uint8_t mcuss_parents[] = {
491b8fe48b6SEtienne Carriere 	_HSI, _HSE, _CSI, _PLL3_P
492b053a22eSYann Gautier };
493b053a22eSYann Gautier 
4940d21680cSYann Gautier static const uint8_t usbphy_parents[] = {
4950d21680cSYann Gautier 	_HSE_KER, _PLL4_R, _HSE_KER_DIV2
4960d21680cSYann Gautier };
4970d21680cSYann Gautier 
4980d21680cSYann Gautier static const uint8_t usbo_parents[] = {
4990d21680cSYann Gautier 	_PLL4_R, _USB_PHY_48
5000d21680cSYann Gautier };
5017839a050SYann Gautier 
5028fbcd9e4SEtienne Carriere static const uint8_t mpu_parents[] = {
5038fbcd9e4SEtienne Carriere 	_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
5048fbcd9e4SEtienne Carriere };
5058fbcd9e4SEtienne Carriere 
5068fbcd9e4SEtienne Carriere static const uint8_t per_parents[] = {
5078fbcd9e4SEtienne Carriere 	_HSI, _HSE, _CSI,
5088fbcd9e4SEtienne Carriere };
5098fbcd9e4SEtienne Carriere 
510016af006SEtienne Carriere static const uint8_t rtc_parents[] = {
511cbd2e8a6SGabriel Fernandez 	_UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
512016af006SEtienne Carriere };
513016af006SEtienne Carriere 
5147839a050SYann Gautier static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
515d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
516d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
517d4151d2fSYann Gautier 	_CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents),
518d4151d2fSYann Gautier 	_CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents),
519d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
520d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
521d4151d2fSYann Gautier 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
5228fbcd9e4SEtienne Carriere 	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
523288f5cf2SYann Gautier 	_CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents),
524016af006SEtienne Carriere 	_CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
525d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
526d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
527d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
528d4151d2fSYann Gautier 	_CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents),
529d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents),
530d4151d2fSYann Gautier 	_CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents),
531d4151d2fSYann Gautier 	_CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents),
532d4151d2fSYann Gautier 	_CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents),
533b8fe48b6SEtienne Carriere 	_CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents),
534b8fe48b6SEtienne Carriere 	_CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents),
535d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents),
536d4151d2fSYann Gautier 	_CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents),
5377839a050SYann Gautier };
5387839a050SYann Gautier 
5397839a050SYann Gautier /* Define characteristic of PLL according type */
5407839a050SYann Gautier #define DIVN_MIN	24
5417839a050SYann Gautier static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
5427839a050SYann Gautier 	[PLL_800] = {
5437839a050SYann Gautier 		.refclk_min = 4,
5447839a050SYann Gautier 		.refclk_max = 16,
5457839a050SYann Gautier 	},
5467839a050SYann Gautier 	[PLL_1600] = {
5477839a050SYann Gautier 		.refclk_min = 8,
5487839a050SYann Gautier 		.refclk_max = 16,
5497839a050SYann Gautier 	},
5507839a050SYann Gautier };
5517839a050SYann Gautier 
5527839a050SYann Gautier /* PLLNCFGR2 register divider by output */
5537839a050SYann Gautier static const uint8_t pllncfgr2[_DIV_NB] = {
5547839a050SYann Gautier 	[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
5557839a050SYann Gautier 	[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
5560d21680cSYann Gautier 	[_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT,
5577839a050SYann Gautier };
5587839a050SYann Gautier 
5597839a050SYann Gautier static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
5600d21680cSYann Gautier 	_CLK_PLL(_PLL1, PLL_1600,
5617839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
5627839a050SYann Gautier 		 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
5637839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5640d21680cSYann Gautier 	_CLK_PLL(_PLL2, PLL_1600,
5657839a050SYann Gautier 		 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
5667839a050SYann Gautier 		 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
5677839a050SYann Gautier 		 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
5680d21680cSYann Gautier 	_CLK_PLL(_PLL3, PLL_800,
5697839a050SYann Gautier 		 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
5707839a050SYann Gautier 		 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
5717839a050SYann Gautier 		 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
5720d21680cSYann Gautier 	_CLK_PLL(_PLL4, PLL_800,
5737839a050SYann Gautier 		 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
5747839a050SYann Gautier 		 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
5757839a050SYann Gautier 		 _HSI, _HSE, _CSI, _I2S_CKIN),
5767839a050SYann Gautier };
5777839a050SYann Gautier 
5787839a050SYann Gautier /* Prescaler table lookups for clock computation */
579b053a22eSYann Gautier /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */
580b053a22eSYann Gautier static const uint8_t stm32mp1_mcu_div[16] = {
581b053a22eSYann Gautier 	0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9
582b053a22eSYann Gautier };
5837839a050SYann Gautier 
5847839a050SYann Gautier /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
5857839a050SYann Gautier #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
5867839a050SYann Gautier #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
5877839a050SYann Gautier static const uint8_t stm32mp1_mpu_apbx_div[8] = {
5887839a050SYann Gautier 	0, 1, 2, 3, 4, 4, 4, 4
5897839a050SYann Gautier };
5907839a050SYann Gautier 
5917839a050SYann Gautier /* div = /1 /2 /3 /4 */
5927839a050SYann Gautier static const uint8_t stm32mp1_axi_div[8] = {
5937839a050SYann Gautier 	1, 2, 3, 4, 4, 4, 4, 4
5947839a050SYann Gautier };
5957839a050SYann Gautier 
59637e8295aSEtienne Carriere static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
59737e8295aSEtienne Carriere 	[_HSI] = "HSI",
59837e8295aSEtienne Carriere 	[_HSE] = "HSE",
59937e8295aSEtienne Carriere 	[_CSI] = "CSI",
60037e8295aSEtienne Carriere 	[_LSI] = "LSI",
60137e8295aSEtienne Carriere 	[_LSE] = "LSE",
60237e8295aSEtienne Carriere 	[_I2S_CKIN] = "I2S_CKIN",
60337e8295aSEtienne Carriere 	[_HSI_KER] = "HSI_KER",
60437e8295aSEtienne Carriere 	[_HSE_KER] = "HSE_KER",
60537e8295aSEtienne Carriere 	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
606cbd2e8a6SGabriel Fernandez 	[_HSE_RTC] = "HSE_RTC",
60737e8295aSEtienne Carriere 	[_CSI_KER] = "CSI_KER",
60837e8295aSEtienne Carriere 	[_PLL1_P] = "PLL1_P",
60937e8295aSEtienne Carriere 	[_PLL1_Q] = "PLL1_Q",
61037e8295aSEtienne Carriere 	[_PLL1_R] = "PLL1_R",
61137e8295aSEtienne Carriere 	[_PLL2_P] = "PLL2_P",
61237e8295aSEtienne Carriere 	[_PLL2_Q] = "PLL2_Q",
61337e8295aSEtienne Carriere 	[_PLL2_R] = "PLL2_R",
61437e8295aSEtienne Carriere 	[_PLL3_P] = "PLL3_P",
61537e8295aSEtienne Carriere 	[_PLL3_Q] = "PLL3_Q",
61637e8295aSEtienne Carriere 	[_PLL3_R] = "PLL3_R",
61737e8295aSEtienne Carriere 	[_PLL4_P] = "PLL4_P",
61837e8295aSEtienne Carriere 	[_PLL4_Q] = "PLL4_Q",
61937e8295aSEtienne Carriere 	[_PLL4_R] = "PLL4_R",
62037e8295aSEtienne Carriere 	[_ACLK] = "ACLK",
62137e8295aSEtienne Carriere 	[_PCLK1] = "PCLK1",
62237e8295aSEtienne Carriere 	[_PCLK2] = "PCLK2",
62337e8295aSEtienne Carriere 	[_PCLK3] = "PCLK3",
62437e8295aSEtienne Carriere 	[_PCLK4] = "PCLK4",
62537e8295aSEtienne Carriere 	[_PCLK5] = "PCLK5",
62637e8295aSEtienne Carriere 	[_HCLK6] = "KCLK6",
62737e8295aSEtienne Carriere 	[_HCLK2] = "HCLK2",
62837e8295aSEtienne Carriere 	[_CK_PER] = "CK_PER",
62937e8295aSEtienne Carriere 	[_CK_MPU] = "CK_MPU",
63037e8295aSEtienne Carriere 	[_CK_MCU] = "CK_MCU",
63137e8295aSEtienne Carriere 	[_USB_PHY_48] = "USB_PHY_48",
63237e8295aSEtienne Carriere };
63337e8295aSEtienne Carriere 
6340d21680cSYann Gautier /* RCC clock device driver private */
6350d21680cSYann Gautier static unsigned long stm32mp1_osc[NB_OSC];
6360d21680cSYann Gautier static struct spinlock reg_lock;
6370d21680cSYann Gautier static unsigned int gate_refcounts[NB_GATES];
6380d21680cSYann Gautier static struct spinlock refcount_lock;
6397839a050SYann Gautier 
6400d21680cSYann Gautier static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx)
6410d21680cSYann Gautier {
6420d21680cSYann Gautier 	return &stm32mp1_clk_gate[idx];
6430d21680cSYann Gautier }
6447839a050SYann Gautier 
6453d69149aSYann Gautier #if defined(IMAGE_BL32)
6463d69149aSYann Gautier static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate)
6473d69149aSYann Gautier {
6483d69149aSYann Gautier 	return gate->secure == N_S;
6493d69149aSYann Gautier }
6503d69149aSYann Gautier #endif
6513d69149aSYann Gautier 
6520d21680cSYann Gautier static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx)
6530d21680cSYann Gautier {
6540d21680cSYann Gautier 	return &stm32mp1_clk_sel[idx];
6550d21680cSYann Gautier }
6560d21680cSYann Gautier 
6570d21680cSYann Gautier static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
6580d21680cSYann Gautier {
6590d21680cSYann Gautier 	return &stm32mp1_clk_pll[idx];
6600d21680cSYann Gautier }
6610d21680cSYann Gautier 
6620d21680cSYann Gautier static void stm32mp1_clk_lock(struct spinlock *lock)
6630d21680cSYann Gautier {
664e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6650d21680cSYann Gautier 		/* Assume interrupts are masked */
6660d21680cSYann Gautier 		spin_lock(lock);
6670d21680cSYann Gautier 	}
668e463d3f4SYann Gautier }
6690d21680cSYann Gautier 
6700d21680cSYann Gautier static void stm32mp1_clk_unlock(struct spinlock *lock)
6710d21680cSYann Gautier {
672e463d3f4SYann Gautier 	if (stm32mp_lock_available()) {
6730d21680cSYann Gautier 		spin_unlock(lock);
6740d21680cSYann Gautier 	}
675e463d3f4SYann Gautier }
6760d21680cSYann Gautier 
6770d21680cSYann Gautier bool stm32mp1_rcc_is_secure(void)
6780d21680cSYann Gautier {
6790d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6801bb9072aSEtienne Carriere 	uint32_t mask = RCC_TZCR_TZEN;
6810d21680cSYann Gautier 
6821bb9072aSEtienne Carriere 	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
6830d21680cSYann Gautier }
6840d21680cSYann Gautier 
685b053a22eSYann Gautier bool stm32mp1_rcc_is_mckprot(void)
686b053a22eSYann Gautier {
687b053a22eSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
6881bb9072aSEtienne Carriere 	uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT;
689b053a22eSYann Gautier 
6901bb9072aSEtienne Carriere 	return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask;
691b053a22eSYann Gautier }
692b053a22eSYann Gautier 
6930d21680cSYann Gautier void stm32mp1_clk_rcc_regs_lock(void)
6940d21680cSYann Gautier {
6950d21680cSYann Gautier 	stm32mp1_clk_lock(&reg_lock);
6960d21680cSYann Gautier }
6970d21680cSYann Gautier 
6980d21680cSYann Gautier void stm32mp1_clk_rcc_regs_unlock(void)
6990d21680cSYann Gautier {
7000d21680cSYann Gautier 	stm32mp1_clk_unlock(&reg_lock);
7010d21680cSYann Gautier }
7020d21680cSYann Gautier 
7030d21680cSYann Gautier static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx)
7047839a050SYann Gautier {
7057839a050SYann Gautier 	if (idx >= NB_OSC) {
7067839a050SYann Gautier 		return 0;
7077839a050SYann Gautier 	}
7087839a050SYann Gautier 
7090d21680cSYann Gautier 	return stm32mp1_osc[idx];
7107839a050SYann Gautier }
7117839a050SYann Gautier 
7120d21680cSYann Gautier static int stm32mp1_clk_get_gated_id(unsigned long id)
7137839a050SYann Gautier {
7140d21680cSYann Gautier 	unsigned int i;
7157839a050SYann Gautier 
7160d21680cSYann Gautier 	for (i = 0U; i < NB_GATES; i++) {
7170d21680cSYann Gautier 		if (gate_ref(i)->index == id) {
7187839a050SYann Gautier 			return i;
7197839a050SYann Gautier 		}
7207839a050SYann Gautier 	}
7217839a050SYann Gautier 
72244fb470bSYann Gautier 	ERROR("%s: clk id %lu not found\n", __func__, id);
7237839a050SYann Gautier 
7247839a050SYann Gautier 	return -EINVAL;
7257839a050SYann Gautier }
7267839a050SYann Gautier 
7270d21680cSYann Gautier static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i)
7287839a050SYann Gautier {
7290d21680cSYann Gautier 	return (enum stm32mp1_parent_sel)(gate_ref(i)->sel);
7307839a050SYann Gautier }
7317839a050SYann Gautier 
7320d21680cSYann Gautier static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i)
7337839a050SYann Gautier {
7340d21680cSYann Gautier 	return (enum stm32mp1_parent_id)(gate_ref(i)->fixed);
7357839a050SYann Gautier }
7367839a050SYann Gautier 
7370d21680cSYann Gautier static int stm32mp1_clk_get_parent(unsigned long id)
7387839a050SYann Gautier {
7390d21680cSYann Gautier 	const struct stm32mp1_clk_sel *sel;
7408fbcd9e4SEtienne Carriere 	uint32_t p_sel;
7417839a050SYann Gautier 	int i;
7427839a050SYann Gautier 	enum stm32mp1_parent_id p;
7437839a050SYann Gautier 	enum stm32mp1_parent_sel s;
7440d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7457839a050SYann Gautier 
7468fbcd9e4SEtienne Carriere 	/* Few non gateable clock have a static parent ID, find them */
7478fbcd9e4SEtienne Carriere 	i = (int)clock_id2parent_id(id);
7488fbcd9e4SEtienne Carriere 	if (i != _UNKNOWN_ID) {
7498fbcd9e4SEtienne Carriere 		return i;
7507839a050SYann Gautier 	}
7517839a050SYann Gautier 
7520d21680cSYann Gautier 	i = stm32mp1_clk_get_gated_id(id);
7537839a050SYann Gautier 	if (i < 0) {
7540d21680cSYann Gautier 		panic();
7557839a050SYann Gautier 	}
7567839a050SYann Gautier 
7570d21680cSYann Gautier 	p = stm32mp1_clk_get_fixed_parent(i);
7587839a050SYann Gautier 	if (p < _PARENT_NB) {
7597839a050SYann Gautier 		return (int)p;
7607839a050SYann Gautier 	}
7617839a050SYann Gautier 
7620d21680cSYann Gautier 	s = stm32mp1_clk_get_sel(i);
7630d21680cSYann Gautier 	if (s == _UNKNOWN_SEL) {
7640d21680cSYann Gautier 		return -EINVAL;
7650d21680cSYann Gautier 	}
7667839a050SYann Gautier 	if (s >= _PARENT_SEL_NB) {
7670d21680cSYann Gautier 		panic();
7687839a050SYann Gautier 	}
7697839a050SYann Gautier 
7700d21680cSYann Gautier 	sel = clk_sel_ref(s);
7718ae08dcdSEtienne Carriere 	p_sel = (mmio_read_32(rcc_base + sel->offset) &
7728ae08dcdSEtienne Carriere 		 (sel->msk << sel->src)) >> sel->src;
7730d21680cSYann Gautier 	if (p_sel < sel->nb_parent) {
7740d21680cSYann Gautier 		return (int)sel->parent[p_sel];
7757839a050SYann Gautier 	}
7767839a050SYann Gautier 
7777839a050SYann Gautier 	return -EINVAL;
7787839a050SYann Gautier }
7797839a050SYann Gautier 
7800d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll)
7817839a050SYann Gautier {
7820d21680cSYann Gautier 	uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr);
7830d21680cSYann Gautier 	uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK;
7847839a050SYann Gautier 
7850d21680cSYann Gautier 	return stm32mp1_clk_get_fixed(pll->refclk[src]);
7867839a050SYann Gautier }
7877839a050SYann Gautier 
7887839a050SYann Gautier /*
7897839a050SYann Gautier  * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
7907839a050SYann Gautier  * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
7917839a050SYann Gautier  * - PLL3 & PLL4 => return VCO     with Fpll_y_ck = FVCO / (DIVy + 1)
7927839a050SYann Gautier  * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
7937839a050SYann Gautier  */
7940d21680cSYann Gautier static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll)
7957839a050SYann Gautier {
7967839a050SYann Gautier 	unsigned long refclk, fvco;
7977839a050SYann Gautier 	uint32_t cfgr1, fracr, divm, divn;
7980d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
7997839a050SYann Gautier 
8000d21680cSYann Gautier 	cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1);
8010d21680cSYann Gautier 	fracr = mmio_read_32(rcc_base + pll->pllxfracr);
8027839a050SYann Gautier 
8037839a050SYann Gautier 	divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
8047839a050SYann Gautier 	divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
8057839a050SYann Gautier 
8060d21680cSYann Gautier 	refclk = stm32mp1_pll_get_fref(pll);
8077839a050SYann Gautier 
8087839a050SYann Gautier 	/*
8097839a050SYann Gautier 	 * With FRACV :
8107839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
8117839a050SYann Gautier 	 * Without FRACV
8127839a050SYann Gautier 	 *   Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
8137839a050SYann Gautier 	 */
8147839a050SYann Gautier 	if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
8150d21680cSYann Gautier 		uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >>
8160d21680cSYann Gautier 				 RCC_PLLNFRACR_FRACV_SHIFT;
8177839a050SYann Gautier 		unsigned long long numerator, denominator;
8187839a050SYann Gautier 
8190d21680cSYann Gautier 		numerator = (((unsigned long long)divn + 1U) << 13) + fracv;
8200d21680cSYann Gautier 		numerator = refclk * numerator;
8217839a050SYann Gautier 		denominator = ((unsigned long long)divm + 1U) << 13;
8227839a050SYann Gautier 		fvco = (unsigned long)(numerator / denominator);
8237839a050SYann Gautier 	} else {
8247839a050SYann Gautier 		fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
8257839a050SYann Gautier 	}
8267839a050SYann Gautier 
8277839a050SYann Gautier 	return fvco;
8287839a050SYann Gautier }
8297839a050SYann Gautier 
8300d21680cSYann Gautier static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id,
8317839a050SYann Gautier 					    enum stm32mp1_div_id div_id)
8327839a050SYann Gautier {
8330d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
8347839a050SYann Gautier 	unsigned long dfout;
8357839a050SYann Gautier 	uint32_t cfgr2, divy;
8367839a050SYann Gautier 
8377839a050SYann Gautier 	if (div_id >= _DIV_NB) {
8387839a050SYann Gautier 		return 0;
8397839a050SYann Gautier 	}
8407839a050SYann Gautier 
8410d21680cSYann Gautier 	cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2);
8427839a050SYann Gautier 	divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
8437839a050SYann Gautier 
8440d21680cSYann Gautier 	dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U);
8457839a050SYann Gautier 
8467839a050SYann Gautier 	return dfout;
8477839a050SYann Gautier }
8487839a050SYann Gautier 
8490d21680cSYann Gautier static unsigned long get_clock_rate(int p)
8507839a050SYann Gautier {
8517839a050SYann Gautier 	uint32_t reg, clkdiv;
8527839a050SYann Gautier 	unsigned long clock = 0;
8530d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
8547839a050SYann Gautier 
8557839a050SYann Gautier 	switch (p) {
8567839a050SYann Gautier 	case _CK_MPU:
8577839a050SYann Gautier 	/* MPU sub system */
8580d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MPCKSELR);
8597839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8607839a050SYann Gautier 		case RCC_MPCKSELR_HSI:
8610d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8627839a050SYann Gautier 			break;
8637839a050SYann Gautier 		case RCC_MPCKSELR_HSE:
8640d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8657839a050SYann Gautier 			break;
8667839a050SYann Gautier 		case RCC_MPCKSELR_PLL:
8670d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8687839a050SYann Gautier 			break;
8697839a050SYann Gautier 		case RCC_MPCKSELR_PLL_MPUDIV:
8700d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
8717839a050SYann Gautier 
8720d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_MPCKDIVR);
8737839a050SYann Gautier 			clkdiv = reg & RCC_MPUDIV_MASK;
874602ae2f2SGabriel Fernandez 			clock >>= stm32mp1_mpu_div[clkdiv];
8757839a050SYann Gautier 			break;
8767839a050SYann Gautier 		default:
8777839a050SYann Gautier 			break;
8787839a050SYann Gautier 		}
8797839a050SYann Gautier 		break;
8807839a050SYann Gautier 	/* AXI sub system */
8817839a050SYann Gautier 	case _ACLK:
8827839a050SYann Gautier 	case _HCLK2:
8837839a050SYann Gautier 	case _HCLK6:
8847839a050SYann Gautier 	case _PCLK4:
8857839a050SYann Gautier 	case _PCLK5:
8860d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_ASSCKSELR);
8877839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
8887839a050SYann Gautier 		case RCC_ASSCKSELR_HSI:
8890d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
8907839a050SYann Gautier 			break;
8917839a050SYann Gautier 		case RCC_ASSCKSELR_HSE:
8920d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
8937839a050SYann Gautier 			break;
8947839a050SYann Gautier 		case RCC_ASSCKSELR_PLL:
8950d21680cSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
8967839a050SYann Gautier 			break;
8977839a050SYann Gautier 		default:
8987839a050SYann Gautier 			break;
8997839a050SYann Gautier 		}
9007839a050SYann Gautier 
9017839a050SYann Gautier 		/* System clock divider */
9020d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_AXIDIVR);
9037839a050SYann Gautier 		clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
9047839a050SYann Gautier 
9057839a050SYann Gautier 		switch (p) {
9067839a050SYann Gautier 		case _PCLK4:
9070d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB4DIVR);
9087839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
9097839a050SYann Gautier 			break;
9107839a050SYann Gautier 		case _PCLK5:
9110d21680cSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB5DIVR);
9127839a050SYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
9137839a050SYann Gautier 			break;
9147839a050SYann Gautier 		default:
9157839a050SYann Gautier 			break;
9167839a050SYann Gautier 		}
9177839a050SYann Gautier 		break;
918b053a22eSYann Gautier 	/* MCU sub system */
919b053a22eSYann Gautier 	case _CK_MCU:
920b053a22eSYann Gautier 	case _PCLK1:
921b053a22eSYann Gautier 	case _PCLK2:
922b053a22eSYann Gautier 	case _PCLK3:
923b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MSSCKSELR);
924b053a22eSYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
925b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSI:
926b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
927b053a22eSYann Gautier 			break;
928b053a22eSYann Gautier 		case RCC_MSSCKSELR_HSE:
929b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
930b053a22eSYann Gautier 			break;
931b053a22eSYann Gautier 		case RCC_MSSCKSELR_CSI:
932b053a22eSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
933b053a22eSYann Gautier 			break;
934b053a22eSYann Gautier 		case RCC_MSSCKSELR_PLL:
935b053a22eSYann Gautier 			clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
936b053a22eSYann Gautier 			break;
937b053a22eSYann Gautier 		default:
938b053a22eSYann Gautier 			break;
939b053a22eSYann Gautier 		}
940b053a22eSYann Gautier 
941b053a22eSYann Gautier 		/* MCU clock divider */
942b053a22eSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_MCUDIVR);
943b053a22eSYann Gautier 		clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK];
944b053a22eSYann Gautier 
945b053a22eSYann Gautier 		switch (p) {
946b053a22eSYann Gautier 		case _PCLK1:
947b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB1DIVR);
948b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
949b053a22eSYann Gautier 			break;
950b053a22eSYann Gautier 		case _PCLK2:
951b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB2DIVR);
952b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
953b053a22eSYann Gautier 			break;
954b053a22eSYann Gautier 		case _PCLK3:
955b053a22eSYann Gautier 			reg = mmio_read_32(rcc_base + RCC_APB3DIVR);
956b053a22eSYann Gautier 			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
957b053a22eSYann Gautier 			break;
958b053a22eSYann Gautier 		case _CK_MCU:
959b053a22eSYann Gautier 		default:
960b053a22eSYann Gautier 			break;
961b053a22eSYann Gautier 		}
962b053a22eSYann Gautier 		break;
9637839a050SYann Gautier 	case _CK_PER:
9640d21680cSYann Gautier 		reg = mmio_read_32(rcc_base + RCC_CPERCKSELR);
9657839a050SYann Gautier 		switch (reg & RCC_SELR_SRC_MASK) {
9667839a050SYann Gautier 		case RCC_CPERCKSELR_HSI:
9670d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSI);
9687839a050SYann Gautier 			break;
9697839a050SYann Gautier 		case RCC_CPERCKSELR_HSE:
9700d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_HSE);
9717839a050SYann Gautier 			break;
9727839a050SYann Gautier 		case RCC_CPERCKSELR_CSI:
9730d21680cSYann Gautier 			clock = stm32mp1_clk_get_fixed(_CSI);
9747839a050SYann Gautier 			break;
9757839a050SYann Gautier 		default:
9767839a050SYann Gautier 			break;
9777839a050SYann Gautier 		}
9787839a050SYann Gautier 		break;
9797839a050SYann Gautier 	case _HSI:
9807839a050SYann Gautier 	case _HSI_KER:
9810d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSI);
9827839a050SYann Gautier 		break;
9837839a050SYann Gautier 	case _CSI:
9847839a050SYann Gautier 	case _CSI_KER:
9850d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_CSI);
9867839a050SYann Gautier 		break;
9877839a050SYann Gautier 	case _HSE:
9887839a050SYann Gautier 	case _HSE_KER:
9890d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE);
9907839a050SYann Gautier 		break;
9917839a050SYann Gautier 	case _HSE_KER_DIV2:
9920d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
9937839a050SYann Gautier 		break;
994cbd2e8a6SGabriel Fernandez 	case _HSE_RTC:
995cbd2e8a6SGabriel Fernandez 		clock = stm32mp1_clk_get_fixed(_HSE);
996cbd2e8a6SGabriel Fernandez 		clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
997cbd2e8a6SGabriel Fernandez 		break;
9987839a050SYann Gautier 	case _LSI:
9990d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSI);
10007839a050SYann Gautier 		break;
10017839a050SYann Gautier 	case _LSE:
10020d21680cSYann Gautier 		clock = stm32mp1_clk_get_fixed(_LSE);
10037839a050SYann Gautier 		break;
10047839a050SYann Gautier 	/* PLL */
10057839a050SYann Gautier 	case _PLL1_P:
10060d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P);
10077839a050SYann Gautier 		break;
10087839a050SYann Gautier 	case _PLL1_Q:
10090d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q);
10107839a050SYann Gautier 		break;
10117839a050SYann Gautier 	case _PLL1_R:
10120d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R);
10137839a050SYann Gautier 		break;
10147839a050SYann Gautier 	case _PLL2_P:
10150d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P);
10167839a050SYann Gautier 		break;
10177839a050SYann Gautier 	case _PLL2_Q:
10180d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q);
10197839a050SYann Gautier 		break;
10207839a050SYann Gautier 	case _PLL2_R:
10210d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R);
10227839a050SYann Gautier 		break;
10237839a050SYann Gautier 	case _PLL3_P:
10240d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P);
10257839a050SYann Gautier 		break;
10267839a050SYann Gautier 	case _PLL3_Q:
10270d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q);
10287839a050SYann Gautier 		break;
10297839a050SYann Gautier 	case _PLL3_R:
10300d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R);
10317839a050SYann Gautier 		break;
10327839a050SYann Gautier 	case _PLL4_P:
10330d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P);
10347839a050SYann Gautier 		break;
10357839a050SYann Gautier 	case _PLL4_Q:
10360d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q);
10377839a050SYann Gautier 		break;
10387839a050SYann Gautier 	case _PLL4_R:
10390d21680cSYann Gautier 		clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R);
10407839a050SYann Gautier 		break;
10417839a050SYann Gautier 	/* Other */
10427839a050SYann Gautier 	case _USB_PHY_48:
10430d21680cSYann Gautier 		clock = USB_PHY_48_MHZ;
10447839a050SYann Gautier 		break;
10457839a050SYann Gautier 	default:
10467839a050SYann Gautier 		break;
10477839a050SYann Gautier 	}
10487839a050SYann Gautier 
10497839a050SYann Gautier 	return clock;
10507839a050SYann Gautier }
10517839a050SYann Gautier 
10520d21680cSYann Gautier static void __clk_enable(struct stm32mp1_clk_gate const *gate)
10530d21680cSYann Gautier {
10540d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10550d21680cSYann Gautier 
105625be845eSEtienne Carriere 	VERBOSE("Enable clock %u\n", gate->index);
105725be845eSEtienne Carriere 
10580d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10590d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
10600d21680cSYann Gautier 	} else {
10610d21680cSYann Gautier 		mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
10620d21680cSYann Gautier 	}
10630d21680cSYann Gautier }
10640d21680cSYann Gautier 
10650d21680cSYann Gautier static void __clk_disable(struct stm32mp1_clk_gate const *gate)
10660d21680cSYann Gautier {
10670d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10680d21680cSYann Gautier 
106925be845eSEtienne Carriere 	VERBOSE("Disable clock %u\n", gate->index);
107025be845eSEtienne Carriere 
10710d21680cSYann Gautier 	if (gate->set_clr != 0U) {
10720d21680cSYann Gautier 		mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
10730d21680cSYann Gautier 			      BIT(gate->bit));
10740d21680cSYann Gautier 	} else {
10750d21680cSYann Gautier 		mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
10760d21680cSYann Gautier 	}
10770d21680cSYann Gautier }
10780d21680cSYann Gautier 
10790d21680cSYann Gautier static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
10800d21680cSYann Gautier {
10810d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
10820d21680cSYann Gautier 
10830d21680cSYann Gautier 	return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit);
10840d21680cSYann Gautier }
10850d21680cSYann Gautier 
108635848200SEtienne Carriere /* Oscillators and PLLs are not gated at runtime */
108735848200SEtienne Carriere static bool clock_is_always_on(unsigned long id)
108835848200SEtienne Carriere {
108935848200SEtienne Carriere 	switch (id) {
109035848200SEtienne Carriere 	case CK_HSE:
109135848200SEtienne Carriere 	case CK_CSI:
109235848200SEtienne Carriere 	case CK_LSI:
109335848200SEtienne Carriere 	case CK_LSE:
109435848200SEtienne Carriere 	case CK_HSI:
109535848200SEtienne Carriere 	case CK_HSE_DIV2:
109635848200SEtienne Carriere 	case PLL1_Q:
109735848200SEtienne Carriere 	case PLL1_R:
109835848200SEtienne Carriere 	case PLL2_P:
109935848200SEtienne Carriere 	case PLL2_Q:
110035848200SEtienne Carriere 	case PLL2_R:
110135848200SEtienne Carriere 	case PLL3_P:
110235848200SEtienne Carriere 	case PLL3_Q:
110335848200SEtienne Carriere 	case PLL3_R:
1104bf39318dSYann Gautier 	case CK_AXI:
1105bf39318dSYann Gautier 	case CK_MPU:
1106bf39318dSYann Gautier 	case CK_MCU:
11075b111c74SHE Shushan 	case RTC:
110835848200SEtienne Carriere 		return true;
110935848200SEtienne Carriere 	default:
111035848200SEtienne Carriere 		return false;
111135848200SEtienne Carriere 	}
111235848200SEtienne Carriere }
111335848200SEtienne Carriere 
11142444d231SYann Gautier static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt)
11150d21680cSYann Gautier {
11160d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
111735848200SEtienne Carriere 	int i;
11180d21680cSYann Gautier 
111935848200SEtienne Carriere 	if (clock_is_always_on(id)) {
112035848200SEtienne Carriere 		return;
112135848200SEtienne Carriere 	}
112235848200SEtienne Carriere 
112335848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11240d21680cSYann Gautier 	if (i < 0) {
112544fb470bSYann Gautier 		ERROR("Clock %lu can't be enabled\n", id);
11260d21680cSYann Gautier 		panic();
11270d21680cSYann Gautier 	}
11280d21680cSYann Gautier 
11290d21680cSYann Gautier 	gate = gate_ref(i);
11302444d231SYann Gautier 
11312444d231SYann Gautier 	if (!with_refcnt) {
11322444d231SYann Gautier 		__clk_enable(gate);
11332444d231SYann Gautier 		return;
11342444d231SYann Gautier 	}
11350d21680cSYann Gautier 
11363d69149aSYann Gautier #if defined(IMAGE_BL32)
11373d69149aSYann Gautier 	if (gate_is_non_secure(gate)) {
11383d69149aSYann Gautier 		/* Enable non-secure clock w/o any refcounting */
11393d69149aSYann Gautier 		__clk_enable(gate);
11403d69149aSYann Gautier 		return;
11413d69149aSYann Gautier 	}
11423d69149aSYann Gautier #endif
11433d69149aSYann Gautier 
11440d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11450d21680cSYann Gautier 
11462444d231SYann Gautier 	if (gate_refcounts[i] == 0U) {
11470d21680cSYann Gautier 		__clk_enable(gate);
11480d21680cSYann Gautier 	}
11490d21680cSYann Gautier 
11502444d231SYann Gautier 	gate_refcounts[i]++;
11512444d231SYann Gautier 	if (gate_refcounts[i] == UINT_MAX) {
11522444d231SYann Gautier 		ERROR("Clock %lu refcount reached max value\n", id);
11532444d231SYann Gautier 		panic();
11542444d231SYann Gautier 	}
11552444d231SYann Gautier 
11560d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
11570d21680cSYann Gautier }
11580d21680cSYann Gautier 
11592444d231SYann Gautier static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt)
11600d21680cSYann Gautier {
11610d21680cSYann Gautier 	const struct stm32mp1_clk_gate *gate;
116235848200SEtienne Carriere 	int i;
11630d21680cSYann Gautier 
116435848200SEtienne Carriere 	if (clock_is_always_on(id)) {
116535848200SEtienne Carriere 		return;
116635848200SEtienne Carriere 	}
116735848200SEtienne Carriere 
116835848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
11690d21680cSYann Gautier 	if (i < 0) {
117044fb470bSYann Gautier 		ERROR("Clock %lu can't be disabled\n", id);
11710d21680cSYann Gautier 		panic();
11720d21680cSYann Gautier 	}
11730d21680cSYann Gautier 
11740d21680cSYann Gautier 	gate = gate_ref(i);
11752444d231SYann Gautier 
11762444d231SYann Gautier 	if (!with_refcnt) {
11772444d231SYann Gautier 		__clk_disable(gate);
11782444d231SYann Gautier 		return;
11792444d231SYann Gautier 	}
11800d21680cSYann Gautier 
11813d69149aSYann Gautier #if defined(IMAGE_BL32)
11823d69149aSYann Gautier 	if (gate_is_non_secure(gate)) {
11833d69149aSYann Gautier 		/* Don't disable non-secure clocks */
11843d69149aSYann Gautier 		return;
11853d69149aSYann Gautier 	}
11863d69149aSYann Gautier #endif
11873d69149aSYann Gautier 
11880d21680cSYann Gautier 	stm32mp1_clk_lock(&refcount_lock);
11890d21680cSYann Gautier 
11902444d231SYann Gautier 	if (gate_refcounts[i] == 0U) {
11912444d231SYann Gautier 		ERROR("Clock %lu refcount reached 0\n", id);
11922444d231SYann Gautier 		panic();
11932444d231SYann Gautier 	}
11942444d231SYann Gautier 	gate_refcounts[i]--;
11952444d231SYann Gautier 
11962444d231SYann Gautier 	if (gate_refcounts[i] == 0U) {
11970d21680cSYann Gautier 		__clk_disable(gate);
11980d21680cSYann Gautier 	}
11990d21680cSYann Gautier 
12000d21680cSYann Gautier 	stm32mp1_clk_unlock(&refcount_lock);
12010d21680cSYann Gautier }
12020d21680cSYann Gautier 
120333667d29SYann Gautier static int stm32mp_clk_enable(unsigned long id)
12040d21680cSYann Gautier {
12050d21680cSYann Gautier 	__stm32mp1_clk_enable(id, true);
120633667d29SYann Gautier 
120733667d29SYann Gautier 	return 0;
12080d21680cSYann Gautier }
12090d21680cSYann Gautier 
121033667d29SYann Gautier static void stm32mp_clk_disable(unsigned long id)
12110d21680cSYann Gautier {
12120d21680cSYann Gautier 	__stm32mp1_clk_disable(id, true);
12130d21680cSYann Gautier }
12140d21680cSYann Gautier 
121533667d29SYann Gautier static bool stm32mp_clk_is_enabled(unsigned long id)
12167839a050SYann Gautier {
121735848200SEtienne Carriere 	int i;
12187839a050SYann Gautier 
121935848200SEtienne Carriere 	if (clock_is_always_on(id)) {
122035848200SEtienne Carriere 		return true;
122135848200SEtienne Carriere 	}
122235848200SEtienne Carriere 
122335848200SEtienne Carriere 	i = stm32mp1_clk_get_gated_id(id);
12247839a050SYann Gautier 	if (i < 0) {
12250d21680cSYann Gautier 		panic();
12267839a050SYann Gautier 	}
12277839a050SYann Gautier 
12280d21680cSYann Gautier 	return __clk_is_enabled(gate_ref(i));
12297839a050SYann Gautier }
12307839a050SYann Gautier 
123133667d29SYann Gautier static unsigned long stm32mp_clk_get_rate(unsigned long id)
12327839a050SYann Gautier {
123333667d29SYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
12340d21680cSYann Gautier 	int p = stm32mp1_clk_get_parent(id);
123533667d29SYann Gautier 	uint32_t prescaler, timpre;
123633667d29SYann Gautier 	unsigned long parent_rate;
12377839a050SYann Gautier 
12387839a050SYann Gautier 	if (p < 0) {
12397839a050SYann Gautier 		return 0;
12407839a050SYann Gautier 	}
12417839a050SYann Gautier 
124233667d29SYann Gautier 	parent_rate = get_clock_rate(p);
124333667d29SYann Gautier 
124433667d29SYann Gautier 	switch (id) {
124533667d29SYann Gautier 	case TIM2_K:
124633667d29SYann Gautier 	case TIM3_K:
124733667d29SYann Gautier 	case TIM4_K:
124833667d29SYann Gautier 	case TIM5_K:
124933667d29SYann Gautier 	case TIM6_K:
125033667d29SYann Gautier 	case TIM7_K:
125133667d29SYann Gautier 	case TIM12_K:
125233667d29SYann Gautier 	case TIM13_K:
125333667d29SYann Gautier 	case TIM14_K:
125433667d29SYann Gautier 		prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) &
125533667d29SYann Gautier 			    RCC_APBXDIV_MASK;
125633667d29SYann Gautier 		timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) &
125733667d29SYann Gautier 			 RCC_TIMGXPRER_TIMGXPRE;
125833667d29SYann Gautier 		break;
125933667d29SYann Gautier 
126033667d29SYann Gautier 	case TIM1_K:
126133667d29SYann Gautier 	case TIM8_K:
126233667d29SYann Gautier 	case TIM15_K:
126333667d29SYann Gautier 	case TIM16_K:
126433667d29SYann Gautier 	case TIM17_K:
126533667d29SYann Gautier 		prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) &
126633667d29SYann Gautier 			    RCC_APBXDIV_MASK;
126733667d29SYann Gautier 		timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) &
126833667d29SYann Gautier 			 RCC_TIMGXPRER_TIMGXPRE;
126933667d29SYann Gautier 		break;
127033667d29SYann Gautier 
127133667d29SYann Gautier 	default:
127233667d29SYann Gautier 		return parent_rate;
127333667d29SYann Gautier 	}
127433667d29SYann Gautier 
127533667d29SYann Gautier 	if (prescaler == 0U) {
127633667d29SYann Gautier 		return parent_rate;
127733667d29SYann Gautier 	}
127833667d29SYann Gautier 
127933667d29SYann Gautier 	return parent_rate * (timpre + 1U) * 2U;
12807839a050SYann Gautier }
12817839a050SYann Gautier 
12820d21680cSYann Gautier static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on)
12837839a050SYann Gautier {
12840d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12857839a050SYann Gautier 
12860d21680cSYann Gautier 	if (enable) {
12877839a050SYann Gautier 		mmio_setbits_32(address, mask_on);
12887839a050SYann Gautier 	} else {
12897839a050SYann Gautier 		mmio_clrbits_32(address, mask_on);
12907839a050SYann Gautier 	}
12917839a050SYann Gautier }
12927839a050SYann Gautier 
12930d21680cSYann Gautier static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on)
12947839a050SYann Gautier {
12950d21680cSYann Gautier 	uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR;
12960d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
12970d21680cSYann Gautier 
12980d21680cSYann Gautier 	mmio_write_32(address, mask_on);
12997839a050SYann Gautier }
13007839a050SYann Gautier 
13010d21680cSYann Gautier static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy)
13027839a050SYann Gautier {
1303dfdb057aSYann Gautier 	uint64_t timeout;
13047839a050SYann Gautier 	uint32_t mask_test;
13050d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + offset;
13067839a050SYann Gautier 
13070d21680cSYann Gautier 	if (enable) {
13087839a050SYann Gautier 		mask_test = mask_rdy;
13097839a050SYann Gautier 	} else {
13107839a050SYann Gautier 		mask_test = 0;
13117839a050SYann Gautier 	}
13127839a050SYann Gautier 
1313dfdb057aSYann Gautier 	timeout = timeout_init_us(OSCRDY_TIMEOUT);
13147839a050SYann Gautier 	while ((mmio_read_32(address) & mask_rdy) != mask_test) {
1315dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
13160d21680cSYann Gautier 			ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n",
13177839a050SYann Gautier 			      mask_rdy, address, enable, mmio_read_32(address));
13187839a050SYann Gautier 			return -ETIMEDOUT;
13197839a050SYann Gautier 		}
13207839a050SYann Gautier 	}
13217839a050SYann Gautier 
13227839a050SYann Gautier 	return 0;
13237839a050SYann Gautier }
13247839a050SYann Gautier 
13250d21680cSYann Gautier static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv)
13267839a050SYann Gautier {
13277839a050SYann Gautier 	uint32_t value;
13280d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13297839a050SYann Gautier 
13300d21680cSYann Gautier 	if (digbyp) {
13310d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP);
13320d21680cSYann Gautier 	}
13330d21680cSYann Gautier 
13340d21680cSYann Gautier 	if (bypass || digbyp) {
13350d21680cSYann Gautier 		mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP);
13367839a050SYann Gautier 	}
13377839a050SYann Gautier 
13387839a050SYann Gautier 	/*
13397839a050SYann Gautier 	 * Warning: not recommended to switch directly from "high drive"
13407839a050SYann Gautier 	 * to "medium low drive", and vice-versa.
13417839a050SYann Gautier 	 */
13420d21680cSYann Gautier 	value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
13437839a050SYann Gautier 		RCC_BDCR_LSEDRV_SHIFT;
13447839a050SYann Gautier 
13457839a050SYann Gautier 	while (value != lsedrv) {
13467839a050SYann Gautier 		if (value > lsedrv) {
13477839a050SYann Gautier 			value--;
13487839a050SYann Gautier 		} else {
13497839a050SYann Gautier 			value++;
13507839a050SYann Gautier 		}
13517839a050SYann Gautier 
13520d21680cSYann Gautier 		mmio_clrsetbits_32(rcc_base + RCC_BDCR,
13537839a050SYann Gautier 				   RCC_BDCR_LSEDRV_MASK,
13547839a050SYann Gautier 				   value << RCC_BDCR_LSEDRV_SHIFT);
13557839a050SYann Gautier 	}
13567839a050SYann Gautier 
13570d21680cSYann Gautier 	stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON);
13587839a050SYann Gautier }
13597839a050SYann Gautier 
13600d21680cSYann Gautier static void stm32mp1_lse_wait(void)
13617839a050SYann Gautier {
13620d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
13637839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13647839a050SYann Gautier 	}
13657839a050SYann Gautier }
13667839a050SYann Gautier 
13670d21680cSYann Gautier static void stm32mp1_lsi_set(bool enable)
13687839a050SYann Gautier {
13690d21680cSYann Gautier 	stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION);
13700d21680cSYann Gautier 
13710d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) {
13727839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13737839a050SYann Gautier 	}
13747839a050SYann Gautier }
13757839a050SYann Gautier 
13760d21680cSYann Gautier static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css)
13777839a050SYann Gautier {
13780d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
13790d21680cSYann Gautier 
13800d21680cSYann Gautier 	if (digbyp) {
13810d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP);
13827839a050SYann Gautier 	}
13837839a050SYann Gautier 
13840d21680cSYann Gautier 	if (bypass || digbyp) {
13850d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP);
13860d21680cSYann Gautier 	}
13870d21680cSYann Gautier 
13880d21680cSYann Gautier 	stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON);
13890d21680cSYann Gautier 	if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) {
13907839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
13917839a050SYann Gautier 	}
13927839a050SYann Gautier 
13937839a050SYann Gautier 	if (css) {
13940d21680cSYann Gautier 		mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON);
13957839a050SYann Gautier 	}
139631e9750bSLionel Debieve 
139731e9750bSLionel Debieve #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
139831e9750bSLionel Debieve 	if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) &&
139931e9750bSLionel Debieve 	    (!(digbyp || bypass))) {
140031e9750bSLionel Debieve 		panic();
140131e9750bSLionel Debieve 	}
140231e9750bSLionel Debieve #endif
14037839a050SYann Gautier }
14047839a050SYann Gautier 
14050d21680cSYann Gautier static void stm32mp1_csi_set(bool enable)
14067839a050SYann Gautier {
14070d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION);
14080d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) {
14097839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
14107839a050SYann Gautier 	}
14117839a050SYann Gautier }
14127839a050SYann Gautier 
14130d21680cSYann Gautier static void stm32mp1_hsi_set(bool enable)
14147839a050SYann Gautier {
14150d21680cSYann Gautier 	stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION);
14160d21680cSYann Gautier 	if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) {
14177839a050SYann Gautier 		VERBOSE("%s: failed\n", __func__);
14187839a050SYann Gautier 	}
14197839a050SYann Gautier }
14207839a050SYann Gautier 
14210d21680cSYann Gautier static int stm32mp1_set_hsidiv(uint8_t hsidiv)
14227839a050SYann Gautier {
1423dfdb057aSYann Gautier 	uint64_t timeout;
14240d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
14250d21680cSYann Gautier 	uintptr_t address = rcc_base + RCC_OCRDYR;
14267839a050SYann Gautier 
14270d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_HSICFGR,
14287839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK,
14297839a050SYann Gautier 			   RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
14307839a050SYann Gautier 
1431dfdb057aSYann Gautier 	timeout = timeout_init_us(HSIDIV_TIMEOUT);
14327839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
1433dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
14340d21680cSYann Gautier 			ERROR("HSIDIV failed @ 0x%lx: 0x%x\n",
14357839a050SYann Gautier 			      address, mmio_read_32(address));
14367839a050SYann Gautier 			return -ETIMEDOUT;
14377839a050SYann Gautier 		}
14387839a050SYann Gautier 	}
14397839a050SYann Gautier 
14407839a050SYann Gautier 	return 0;
14417839a050SYann Gautier }
14427839a050SYann Gautier 
14430d21680cSYann Gautier static int stm32mp1_hsidiv(unsigned long hsifreq)
14447839a050SYann Gautier {
14457839a050SYann Gautier 	uint8_t hsidiv;
14467839a050SYann Gautier 	uint32_t hsidivfreq = MAX_HSI_HZ;
14477839a050SYann Gautier 
14487839a050SYann Gautier 	for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
14497839a050SYann Gautier 		if (hsidivfreq == hsifreq) {
14507839a050SYann Gautier 			break;
14517839a050SYann Gautier 		}
14527839a050SYann Gautier 
14537839a050SYann Gautier 		hsidivfreq /= 2U;
14547839a050SYann Gautier 	}
14557839a050SYann Gautier 
14567839a050SYann Gautier 	if (hsidiv == 4U) {
14577839a050SYann Gautier 		ERROR("Invalid clk-hsi frequency\n");
14587839a050SYann Gautier 		return -1;
14597839a050SYann Gautier 	}
14607839a050SYann Gautier 
14617839a050SYann Gautier 	if (hsidiv != 0U) {
14620d21680cSYann Gautier 		return stm32mp1_set_hsidiv(hsidiv);
14637839a050SYann Gautier 	}
14647839a050SYann Gautier 
14657839a050SYann Gautier 	return 0;
14667839a050SYann Gautier }
14677839a050SYann Gautier 
14680d21680cSYann Gautier static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
14690d21680cSYann Gautier 				    unsigned int clksrc,
14700d21680cSYann Gautier 				    uint32_t *pllcfg, int plloff)
14717839a050SYann Gautier {
14720d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
14730d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
14740d21680cSYann Gautier 	uintptr_t pllxcr = rcc_base + pll->pllxcr;
14750d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
14760d21680cSYann Gautier 	uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
14770d21680cSYann Gautier 	unsigned long refclk;
14780d21680cSYann Gautier 	uint32_t ifrge = 0U;
1479be858cffSAndre Przywara 	uint32_t src, value, fracv = 0;
1480be858cffSAndre Przywara 	void *fdt;
14817839a050SYann Gautier 
14820d21680cSYann Gautier 	/* Check PLL output */
14830d21680cSYann Gautier 	if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
14840d21680cSYann Gautier 		return false;
14857839a050SYann Gautier 	}
14867839a050SYann Gautier 
14870d21680cSYann Gautier 	/* Check current clksrc */
14880d21680cSYann Gautier 	src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK;
14890d21680cSYann Gautier 	if (src != (clksrc & RCC_SELR_SRC_MASK)) {
14900d21680cSYann Gautier 		return false;
14910d21680cSYann Gautier 	}
14920d21680cSYann Gautier 
14930d21680cSYann Gautier 	/* Check Div */
14940d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK;
14950d21680cSYann Gautier 
14960d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
14970d21680cSYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
14980d21680cSYann Gautier 
14990d21680cSYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
15000d21680cSYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
15010d21680cSYann Gautier 		return false;
15020d21680cSYann Gautier 	}
15030d21680cSYann Gautier 
15040d21680cSYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
15050d21680cSYann Gautier 		ifrge = 1U;
15060d21680cSYann Gautier 	}
15070d21680cSYann Gautier 
15080d21680cSYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
15090d21680cSYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
15100d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
15110d21680cSYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
15120d21680cSYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
15130d21680cSYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
15140d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) {
15150d21680cSYann Gautier 		return false;
15160d21680cSYann Gautier 	}
15170d21680cSYann Gautier 
15180d21680cSYann Gautier 	/* Fractional configuration */
1519be858cffSAndre Przywara 	if (fdt_get_address(&fdt) == 1) {
1520be858cffSAndre Przywara 		fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1521be858cffSAndre Przywara 	}
15220d21680cSYann Gautier 
15230d21680cSYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
15240d21680cSYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
15250d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
15260d21680cSYann Gautier 		return false;
15270d21680cSYann Gautier 	}
15280d21680cSYann Gautier 
15290d21680cSYann Gautier 	/* Output config */
15300d21680cSYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
15310d21680cSYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
15320d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
15330d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
15340d21680cSYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
15350d21680cSYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
15360d21680cSYann Gautier 	if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) {
15370d21680cSYann Gautier 		return false;
15380d21680cSYann Gautier 	}
15390d21680cSYann Gautier 
15400d21680cSYann Gautier 	return true;
15410d21680cSYann Gautier }
15420d21680cSYann Gautier 
15430d21680cSYann Gautier static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id)
15447839a050SYann Gautier {
15450d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15460d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
15470d21680cSYann Gautier 
1548dd98aec8SYann Gautier 	/* Preserve RCC_PLLNCR_SSCG_CTRL value */
1549dd98aec8SYann Gautier 	mmio_clrsetbits_32(pllxcr,
1550dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
1551dd98aec8SYann Gautier 			   RCC_PLLNCR_DIVREN,
1552dd98aec8SYann Gautier 			   RCC_PLLNCR_PLLON);
15530d21680cSYann Gautier }
15540d21680cSYann Gautier 
15550d21680cSYann Gautier static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output)
15560d21680cSYann Gautier {
15570d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15580d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1559dfdb057aSYann Gautier 	uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
15607839a050SYann Gautier 
15617839a050SYann Gautier 	/* Wait PLL lock */
15627839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
1563dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
15649fa9a0c5SYann Gautier 			ERROR("PLL%u start failed @ 0x%lx: 0x%x\n",
15657839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
15667839a050SYann Gautier 			return -ETIMEDOUT;
15677839a050SYann Gautier 		}
15687839a050SYann Gautier 	}
15697839a050SYann Gautier 
15707839a050SYann Gautier 	/* Start the requested output */
15717839a050SYann Gautier 	mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
15727839a050SYann Gautier 
15737839a050SYann Gautier 	return 0;
15747839a050SYann Gautier }
15757839a050SYann Gautier 
15760d21680cSYann Gautier static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id)
15777839a050SYann Gautier {
15780d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
15790d21680cSYann Gautier 	uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr;
1580dfdb057aSYann Gautier 	uint64_t timeout;
15817839a050SYann Gautier 
15827839a050SYann Gautier 	/* Stop all output */
15837839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
15847839a050SYann Gautier 			RCC_PLLNCR_DIVREN);
15857839a050SYann Gautier 
15867839a050SYann Gautier 	/* Stop PLL */
15877839a050SYann Gautier 	mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
15887839a050SYann Gautier 
1589dfdb057aSYann Gautier 	timeout = timeout_init_us(PLLRDY_TIMEOUT);
15907839a050SYann Gautier 	/* Wait PLL stopped */
15917839a050SYann Gautier 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
1592dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
15939fa9a0c5SYann Gautier 			ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n",
15947839a050SYann Gautier 			      pll_id, pllxcr, mmio_read_32(pllxcr));
15957839a050SYann Gautier 			return -ETIMEDOUT;
15967839a050SYann Gautier 		}
15977839a050SYann Gautier 	}
15987839a050SYann Gautier 
15997839a050SYann Gautier 	return 0;
16007839a050SYann Gautier }
16017839a050SYann Gautier 
16020d21680cSYann Gautier static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id,
16037839a050SYann Gautier 				       uint32_t *pllcfg)
16047839a050SYann Gautier {
16050d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16060d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
16077839a050SYann Gautier 	uint32_t value;
16087839a050SYann Gautier 
16097839a050SYann Gautier 	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
16107839a050SYann Gautier 		RCC_PLLNCFGR2_DIVP_MASK;
16117839a050SYann Gautier 	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
16127839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVQ_MASK;
16137839a050SYann Gautier 	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
16147839a050SYann Gautier 		 RCC_PLLNCFGR2_DIVR_MASK;
16150d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr2, value);
16167839a050SYann Gautier }
16177839a050SYann Gautier 
16180d21680cSYann Gautier static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id,
16197839a050SYann Gautier 			       uint32_t *pllcfg, uint32_t fracv)
16207839a050SYann Gautier {
16210d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16220d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
16230d21680cSYann Gautier 	enum stm32mp1_plltype type = pll->plltype;
16247839a050SYann Gautier 	unsigned long refclk;
16257839a050SYann Gautier 	uint32_t ifrge = 0;
16267839a050SYann Gautier 	uint32_t src, value;
16277839a050SYann Gautier 
16280d21680cSYann Gautier 	src = mmio_read_32(rcc_base + pll->rckxselr) &
16297839a050SYann Gautier 		RCC_SELR_REFCLK_SRC_MASK;
16307839a050SYann Gautier 
16310d21680cSYann Gautier 	refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) /
16327839a050SYann Gautier 		 (pllcfg[PLLCFG_M] + 1U);
16337839a050SYann Gautier 
16347839a050SYann Gautier 	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
16357839a050SYann Gautier 	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
16367839a050SYann Gautier 		return -EINVAL;
16377839a050SYann Gautier 	}
16387839a050SYann Gautier 
16397839a050SYann Gautier 	if ((type == PLL_800) && (refclk >= 8000000U)) {
16407839a050SYann Gautier 		ifrge = 1U;
16417839a050SYann Gautier 	}
16427839a050SYann Gautier 
16437839a050SYann Gautier 	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
16447839a050SYann Gautier 		RCC_PLLNCFGR1_DIVN_MASK;
16457839a050SYann Gautier 	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
16467839a050SYann Gautier 		 RCC_PLLNCFGR1_DIVM_MASK;
16477839a050SYann Gautier 	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
16487839a050SYann Gautier 		 RCC_PLLNCFGR1_IFRGE_MASK;
16490d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxcfgr1, value);
16507839a050SYann Gautier 
16517839a050SYann Gautier 	/* Fractional configuration */
16527839a050SYann Gautier 	value = 0;
16530d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16547839a050SYann Gautier 
16557839a050SYann Gautier 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
16560d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16577839a050SYann Gautier 
16587839a050SYann Gautier 	value |= RCC_PLLNFRACR_FRACLE;
16590d21680cSYann Gautier 	mmio_write_32(rcc_base + pll->pllxfracr, value);
16607839a050SYann Gautier 
16610d21680cSYann Gautier 	stm32mp1_pll_config_output(pll_id, pllcfg);
16627839a050SYann Gautier 
16637839a050SYann Gautier 	return 0;
16647839a050SYann Gautier }
16657839a050SYann Gautier 
16660d21680cSYann Gautier static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg)
16677839a050SYann Gautier {
16680d21680cSYann Gautier 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
16697839a050SYann Gautier 	uint32_t pllxcsg = 0;
16707839a050SYann Gautier 
16717839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
16727839a050SYann Gautier 		    RCC_PLLNCSGR_MOD_PER_MASK;
16737839a050SYann Gautier 
16747839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
16757839a050SYann Gautier 		    RCC_PLLNCSGR_INC_STEP_MASK;
16767839a050SYann Gautier 
16777839a050SYann Gautier 	pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
16787839a050SYann Gautier 		    RCC_PLLNCSGR_SSCG_MODE_MASK;
16797839a050SYann Gautier 
16800d21680cSYann Gautier 	mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg);
1681dd98aec8SYann Gautier 
1682dd98aec8SYann Gautier 	mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr,
1683dd98aec8SYann Gautier 			RCC_PLLNCR_SSCG_CTRL);
16847839a050SYann Gautier }
16857839a050SYann Gautier 
16860d21680cSYann Gautier static int stm32mp1_set_clksrc(unsigned int clksrc)
16877839a050SYann Gautier {
16880d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
1689dfdb057aSYann Gautier 	uint64_t timeout;
16907839a050SYann Gautier 
16910d21680cSYann Gautier 	mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
16927839a050SYann Gautier 			   clksrc & RCC_SELR_SRC_MASK);
16937839a050SYann Gautier 
1694dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKSRC_TIMEOUT);
16950d21680cSYann Gautier 	while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
1696dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
16970d21680cSYann Gautier 			ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
16980d21680cSYann Gautier 			      clksrc_address, mmio_read_32(clksrc_address));
16997839a050SYann Gautier 			return -ETIMEDOUT;
17007839a050SYann Gautier 		}
17017839a050SYann Gautier 	}
17027839a050SYann Gautier 
17037839a050SYann Gautier 	return 0;
17047839a050SYann Gautier }
17057839a050SYann Gautier 
17060d21680cSYann Gautier static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
17077839a050SYann Gautier {
1708dfdb057aSYann Gautier 	uint64_t timeout;
17097839a050SYann Gautier 
17107839a050SYann Gautier 	mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
17117839a050SYann Gautier 			   clkdiv & RCC_DIVR_DIV_MASK);
17127839a050SYann Gautier 
1713dfdb057aSYann Gautier 	timeout = timeout_init_us(CLKDIV_TIMEOUT);
17147839a050SYann Gautier 	while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
1715dfdb057aSYann Gautier 		if (timeout_elapsed(timeout)) {
17160d21680cSYann Gautier 			ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
17177839a050SYann Gautier 			      clkdiv, address, mmio_read_32(address));
17187839a050SYann Gautier 			return -ETIMEDOUT;
17197839a050SYann Gautier 		}
17207839a050SYann Gautier 	}
17217839a050SYann Gautier 
17227839a050SYann Gautier 	return 0;
17237839a050SYann Gautier }
17247839a050SYann Gautier 
17250d21680cSYann Gautier static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
17267839a050SYann Gautier {
17270d21680cSYann Gautier 	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
17287839a050SYann Gautier 
17297839a050SYann Gautier 	/*
17307839a050SYann Gautier 	 * Binding clksrc :
17317839a050SYann Gautier 	 *      bit15-4 offset
17327839a050SYann Gautier 	 *      bit3:   disable
17337839a050SYann Gautier 	 *      bit2-0: MCOSEL[2:0]
17347839a050SYann Gautier 	 */
17357839a050SYann Gautier 	if ((clksrc & 0x8U) != 0U) {
17360d21680cSYann Gautier 		mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
17377839a050SYann Gautier 	} else {
17380d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
17397839a050SYann Gautier 				   RCC_MCOCFG_MCOSRC_MASK,
17407839a050SYann Gautier 				   clksrc & RCC_MCOCFG_MCOSRC_MASK);
17410d21680cSYann Gautier 		mmio_clrsetbits_32(clksrc_address,
17427839a050SYann Gautier 				   RCC_MCOCFG_MCODIV_MASK,
17437839a050SYann Gautier 				   clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
17440d21680cSYann Gautier 		mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
17457839a050SYann Gautier 	}
17467839a050SYann Gautier }
17477839a050SYann Gautier 
17480d21680cSYann Gautier static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
17497839a050SYann Gautier {
17500d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
17517839a050SYann Gautier 
17527839a050SYann Gautier 	if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
17537839a050SYann Gautier 	    (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
17547839a050SYann Gautier 		mmio_clrsetbits_32(address,
17557839a050SYann Gautier 				   RCC_BDCR_RTCSRC_MASK,
175615509093SYann Gautier 				   (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
17577839a050SYann Gautier 
17587839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
17597839a050SYann Gautier 	}
17607839a050SYann Gautier 
17617839a050SYann Gautier 	if (lse_css) {
17627839a050SYann Gautier 		mmio_setbits_32(address, RCC_BDCR_LSECSSON);
17637839a050SYann Gautier 	}
17647839a050SYann Gautier }
17657839a050SYann Gautier 
17660d21680cSYann Gautier static void stm32mp1_pkcs_config(uint32_t pkcs)
17677839a050SYann Gautier {
17680d21680cSYann Gautier 	uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU);
17697839a050SYann Gautier 	uint32_t value = pkcs & 0xFU;
17707839a050SYann Gautier 	uint32_t mask = 0xFU;
17717839a050SYann Gautier 
17727839a050SYann Gautier 	if ((pkcs & BIT(31)) != 0U) {
17737839a050SYann Gautier 		mask <<= 4;
17747839a050SYann Gautier 		value <<= 4;
17757839a050SYann Gautier 	}
17767839a050SYann Gautier 
17777839a050SYann Gautier 	mmio_clrsetbits_32(address, mask, value);
17787839a050SYann Gautier }
17797839a050SYann Gautier 
1780964e5ff1SNicolas Le Bayon static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg,
1781964e5ff1SNicolas Le Bayon 					uint32_t *fracv, uint32_t *csg,
1782964e5ff1SNicolas Le Bayon 					bool *csg_set)
1783964e5ff1SNicolas Le Bayon {
1784964e5ff1SNicolas Le Bayon 	void *fdt;
1785964e5ff1SNicolas Le Bayon 	int ret;
1786964e5ff1SNicolas Le Bayon 
1787964e5ff1SNicolas Le Bayon 	if (fdt_get_address(&fdt) == 0) {
1788964e5ff1SNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
1789964e5ff1SNicolas Le Bayon 	}
1790964e5ff1SNicolas Le Bayon 
1791964e5ff1SNicolas Le Bayon 	ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB,
1792964e5ff1SNicolas Le Bayon 				    pllcfg);
1793964e5ff1SNicolas Le Bayon 	if (ret < 0) {
1794964e5ff1SNicolas Le Bayon 		return -FDT_ERR_NOTFOUND;
1795964e5ff1SNicolas Le Bayon 	}
1796964e5ff1SNicolas Le Bayon 
1797964e5ff1SNicolas Le Bayon 	*fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
1798964e5ff1SNicolas Le Bayon 
1799964e5ff1SNicolas Le Bayon 	ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB,
1800964e5ff1SNicolas Le Bayon 				    csg);
1801964e5ff1SNicolas Le Bayon 
1802964e5ff1SNicolas Le Bayon 	*csg_set = (ret == 0);
1803964e5ff1SNicolas Le Bayon 
1804964e5ff1SNicolas Le Bayon 	if (ret == -FDT_ERR_NOTFOUND) {
1805964e5ff1SNicolas Le Bayon 		ret = 0;
1806964e5ff1SNicolas Le Bayon 	}
1807964e5ff1SNicolas Le Bayon 
1808964e5ff1SNicolas Le Bayon 	return ret;
1809964e5ff1SNicolas Le Bayon }
1810964e5ff1SNicolas Le Bayon 
18117839a050SYann Gautier int stm32mp1_clk_init(void)
18127839a050SYann Gautier {
18130d21680cSYann Gautier 	uintptr_t rcc_base = stm32mp_rcc_base();
1814964e5ff1SNicolas Le Bayon 	uint32_t pllfracv[_PLL_NB];
1815964e5ff1SNicolas Le Bayon 	uint32_t pllcsg[_PLL_NB][PLLCSG_NB];
18167839a050SYann Gautier 	unsigned int clksrc[CLKSRC_NB];
18177839a050SYann Gautier 	unsigned int clkdiv[CLKDIV_NB];
18187839a050SYann Gautier 	unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
18197839a050SYann Gautier 	int plloff[_PLL_NB];
18207839a050SYann Gautier 	int ret, len;
18217839a050SYann Gautier 	enum stm32mp1_pll_id i;
1822964e5ff1SNicolas Le Bayon 	bool pllcsg_set[_PLL_NB];
1823964e5ff1SNicolas Le Bayon 	bool pllcfg_valid[_PLL_NB];
18247839a050SYann Gautier 	bool lse_css = false;
18250d21680cSYann Gautier 	bool pll3_preserve = false;
18260d21680cSYann Gautier 	bool pll4_preserve = false;
18270d21680cSYann Gautier 	bool pll4_bootrom = false;
18283e6fab43SYann Gautier 	const fdt32_t *pkcs_cell;
182952a616b4SAndre Przywara 	void *fdt;
1830bf1af154SPatrick Delaunay 	int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
1831bf1af154SPatrick Delaunay 	int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
183252a616b4SAndre Przywara 
183352a616b4SAndre Przywara 	if (fdt_get_address(&fdt) == 0) {
18348f97c4faSYann Gautier 		return -FDT_ERR_NOTFOUND;
183552a616b4SAndre Przywara 	}
18367839a050SYann Gautier 
183752a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
183852a616b4SAndre Przywara 					clksrc);
18397839a050SYann Gautier 	if (ret < 0) {
18407839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
18417839a050SYann Gautier 	}
18427839a050SYann Gautier 
184352a616b4SAndre Przywara 	ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
184452a616b4SAndre Przywara 					clkdiv);
18457839a050SYann Gautier 	if (ret < 0) {
18467839a050SYann Gautier 		return -FDT_ERR_NOTFOUND;
18477839a050SYann Gautier 	}
18487839a050SYann Gautier 
18497839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
18507839a050SYann Gautier 		char name[12];
18517839a050SYann Gautier 
18529fa9a0c5SYann Gautier 		snprintf(name, sizeof(name), "st,pll@%u", i);
18537839a050SYann Gautier 		plloff[i] = fdt_rcc_subnode_offset(name);
18547839a050SYann Gautier 
1855964e5ff1SNicolas Le Bayon 		pllcfg_valid[i] = fdt_check_node(plloff[i]);
1856964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
18577839a050SYann Gautier 			continue;
18587839a050SYann Gautier 		}
18597839a050SYann Gautier 
1860964e5ff1SNicolas Le Bayon 		ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i],
1861964e5ff1SNicolas Le Bayon 						   &pllfracv[i], pllcsg[i],
1862964e5ff1SNicolas Le Bayon 						   &pllcsg_set[i]);
1863964e5ff1SNicolas Le Bayon 		if (ret != 0) {
1864964e5ff1SNicolas Le Bayon 			return ret;
18657839a050SYann Gautier 		}
18667839a050SYann Gautier 	}
18677839a050SYann Gautier 
18680d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
18690d21680cSYann Gautier 	stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
18707839a050SYann Gautier 
18717839a050SYann Gautier 	/*
18727839a050SYann Gautier 	 * Switch ON oscillator found in device-tree.
18737839a050SYann Gautier 	 * Note: HSI already ON after BootROM stage.
18747839a050SYann Gautier 	 */
18750d21680cSYann Gautier 	if (stm32mp1_osc[_LSI] != 0U) {
18760d21680cSYann Gautier 		stm32mp1_lsi_set(true);
18777839a050SYann Gautier 	}
18780d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
1879b208e3daSGabriel Fernandez 		const char *name = stm32mp_osc_node_label[_LSE];
18800d21680cSYann Gautier 		bool bypass, digbyp;
18817839a050SYann Gautier 		uint32_t lsedrv;
18827839a050SYann Gautier 
1883b208e3daSGabriel Fernandez 		bypass = fdt_clk_read_bool(name, "st,bypass");
1884b208e3daSGabriel Fernandez 		digbyp = fdt_clk_read_bool(name, "st,digbypass");
1885b208e3daSGabriel Fernandez 		lse_css = fdt_clk_read_bool(name, "st,css");
1886b208e3daSGabriel Fernandez 		lsedrv = fdt_clk_read_uint32_default(name, "st,drive",
18877839a050SYann Gautier 						     LSEDRV_MEDIUM_HIGH);
18880d21680cSYann Gautier 		stm32mp1_lse_enable(bypass, digbyp, lsedrv);
18897839a050SYann Gautier 	}
18900d21680cSYann Gautier 	if (stm32mp1_osc[_HSE] != 0U) {
1891b208e3daSGabriel Fernandez 		const char *name = stm32mp_osc_node_label[_HSE];
18920d21680cSYann Gautier 		bool bypass, digbyp, css;
18937839a050SYann Gautier 
1894b208e3daSGabriel Fernandez 		bypass = fdt_clk_read_bool(name, "st,bypass");
1895b208e3daSGabriel Fernandez 		digbyp = fdt_clk_read_bool(name, "st,digbypass");
1896b208e3daSGabriel Fernandez 		css = fdt_clk_read_bool(name, "st,css");
18970d21680cSYann Gautier 		stm32mp1_hse_enable(bypass, digbyp, css);
18987839a050SYann Gautier 	}
18997839a050SYann Gautier 	/*
19007839a050SYann Gautier 	 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
19017839a050SYann Gautier 	 * => switch on CSI even if node is not present in device tree
19027839a050SYann Gautier 	 */
19030d21680cSYann Gautier 	stm32mp1_csi_set(true);
19047839a050SYann Gautier 
19057839a050SYann Gautier 	/* Come back to HSI */
19060d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
19077839a050SYann Gautier 	if (ret != 0) {
19087839a050SYann Gautier 		return ret;
19097839a050SYann Gautier 	}
19100d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
19117839a050SYann Gautier 	if (ret != 0) {
19127839a050SYann Gautier 		return ret;
19137839a050SYann Gautier 	}
1914b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
1915b053a22eSYann Gautier 	if (ret != 0) {
1916b053a22eSYann Gautier 		return ret;
1917b053a22eSYann Gautier 	}
19187839a050SYann Gautier 
19190d21680cSYann Gautier 	if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
19200d21680cSYann Gautier 	     RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
1921175758b2SYann Gautier 		if (pllcfg_valid[_PLL3]) {
1922175758b2SYann Gautier 			pll3_preserve =
1923175758b2SYann Gautier 				stm32mp1_check_pll_conf(_PLL3,
19240d21680cSYann Gautier 							clksrc[CLKSRC_PLL3],
19250d21680cSYann Gautier 							pllcfg[_PLL3],
19260d21680cSYann Gautier 							plloff[_PLL3]);
1927175758b2SYann Gautier 		}
1928175758b2SYann Gautier 
1929175758b2SYann Gautier 		if (pllcfg_valid[_PLL4]) {
1930175758b2SYann Gautier 			pll4_preserve =
1931175758b2SYann Gautier 				stm32mp1_check_pll_conf(_PLL4,
19320d21680cSYann Gautier 							clksrc[CLKSRC_PLL4],
19330d21680cSYann Gautier 							pllcfg[_PLL4],
19340d21680cSYann Gautier 							plloff[_PLL4]);
19350d21680cSYann Gautier 		}
1936175758b2SYann Gautier 	}
1937bf1af154SPatrick Delaunay 	/* Don't initialize PLL4, when used by BOOTROM */
1938bf1af154SPatrick Delaunay 	if ((stm32mp_get_boot_itf_selected() ==
1939bf1af154SPatrick Delaunay 	     BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) &&
1940bf1af154SPatrick Delaunay 	    ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) {
1941bf1af154SPatrick Delaunay 		pll4_bootrom = true;
1942bf1af154SPatrick Delaunay 		pll4_preserve = true;
1943bf1af154SPatrick Delaunay 	}
19440d21680cSYann Gautier 
19457839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
19460d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
19470d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve)) {
19487839a050SYann Gautier 			continue;
19490d21680cSYann Gautier 		}
19500d21680cSYann Gautier 
19510d21680cSYann Gautier 		ret = stm32mp1_pll_stop(i);
19527839a050SYann Gautier 		if (ret != 0) {
19537839a050SYann Gautier 			return ret;
19547839a050SYann Gautier 		}
19557839a050SYann Gautier 	}
19567839a050SYann Gautier 
19577839a050SYann Gautier 	/* Configure HSIDIV */
19580d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] != 0U) {
19590d21680cSYann Gautier 		ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]);
19607839a050SYann Gautier 		if (ret != 0) {
19617839a050SYann Gautier 			return ret;
19627839a050SYann Gautier 		}
1963591d80c8SLionel Debieve 
1964591d80c8SLionel Debieve 		stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K));
19657839a050SYann Gautier 	}
19667839a050SYann Gautier 
19677839a050SYann Gautier 	/* Select DIV */
19687839a050SYann Gautier 	/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
19690d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_MPCKDIVR,
19707839a050SYann Gautier 		      clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
19710d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
19727839a050SYann Gautier 	if (ret != 0) {
19737839a050SYann Gautier 		return ret;
19747839a050SYann Gautier 	}
19750d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
19767839a050SYann Gautier 	if (ret != 0) {
19777839a050SYann Gautier 		return ret;
19787839a050SYann Gautier 	}
19790d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
19807839a050SYann Gautier 	if (ret != 0) {
19817839a050SYann Gautier 		return ret;
19827839a050SYann Gautier 	}
1983b053a22eSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
1984b053a22eSYann Gautier 	if (ret != 0) {
1985b053a22eSYann Gautier 		return ret;
1986b053a22eSYann Gautier 	}
19870d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
19887839a050SYann Gautier 	if (ret != 0) {
19897839a050SYann Gautier 		return ret;
19907839a050SYann Gautier 	}
19910d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
19927839a050SYann Gautier 	if (ret != 0) {
19937839a050SYann Gautier 		return ret;
19947839a050SYann Gautier 	}
19950d21680cSYann Gautier 	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
19967839a050SYann Gautier 	if (ret != 0) {
19977839a050SYann Gautier 		return ret;
19987839a050SYann Gautier 	}
19997839a050SYann Gautier 
20007839a050SYann Gautier 	/* No ready bit for RTC */
20010d21680cSYann Gautier 	mmio_write_32(rcc_base + RCC_RTCDIVR,
20027839a050SYann Gautier 		      clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
20037839a050SYann Gautier 
20047839a050SYann Gautier 	/* Configure PLLs source */
20050d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
20067839a050SYann Gautier 	if (ret != 0) {
20077839a050SYann Gautier 		return ret;
20087839a050SYann Gautier 	}
20097839a050SYann Gautier 
20100d21680cSYann Gautier 	if (!pll3_preserve) {
20110d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
20127839a050SYann Gautier 		if (ret != 0) {
20137839a050SYann Gautier 			return ret;
20147839a050SYann Gautier 		}
20150d21680cSYann Gautier 	}
20160d21680cSYann Gautier 
20170d21680cSYann Gautier 	if (!pll4_preserve) {
20180d21680cSYann Gautier 		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
20190d21680cSYann Gautier 		if (ret != 0) {
20200d21680cSYann Gautier 			return ret;
20210d21680cSYann Gautier 		}
20220d21680cSYann Gautier 	}
20237839a050SYann Gautier 
20247839a050SYann Gautier 	/* Configure and start PLLs */
20257839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
20260d21680cSYann Gautier 		if (((i == _PLL3) && pll3_preserve) ||
20270d21680cSYann Gautier 		    ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) {
20280d21680cSYann Gautier 			continue;
20290d21680cSYann Gautier 		}
20300d21680cSYann Gautier 
2031964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
20327839a050SYann Gautier 			continue;
20337839a050SYann Gautier 		}
20347839a050SYann Gautier 
20350d21680cSYann Gautier 		if ((i == _PLL4) && pll4_bootrom) {
20360d21680cSYann Gautier 			/* Set output divider if not done by the Bootrom */
20370d21680cSYann Gautier 			stm32mp1_pll_config_output(i, pllcfg[i]);
20380d21680cSYann Gautier 			continue;
20390d21680cSYann Gautier 		}
20400d21680cSYann Gautier 
2041964e5ff1SNicolas Le Bayon 		ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]);
20427839a050SYann Gautier 		if (ret != 0) {
20437839a050SYann Gautier 			return ret;
20447839a050SYann Gautier 		}
2045964e5ff1SNicolas Le Bayon 
2046964e5ff1SNicolas Le Bayon 		if (pllcsg_set[i]) {
2047964e5ff1SNicolas Le Bayon 			stm32mp1_pll_csg(i, pllcsg[i]);
20487839a050SYann Gautier 		}
20497839a050SYann Gautier 
20500d21680cSYann Gautier 		stm32mp1_pll_start(i);
20517839a050SYann Gautier 	}
2052*1b491eeaSElyes Haouas 	/* Wait and start PLLs output when ready */
20537839a050SYann Gautier 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
2054964e5ff1SNicolas Le Bayon 		if (!pllcfg_valid[i]) {
20557839a050SYann Gautier 			continue;
20567839a050SYann Gautier 		}
20577839a050SYann Gautier 
20580d21680cSYann Gautier 		ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
20597839a050SYann Gautier 		if (ret != 0) {
20607839a050SYann Gautier 			return ret;
20617839a050SYann Gautier 		}
20627839a050SYann Gautier 	}
20637839a050SYann Gautier 	/* Wait LSE ready before to use it */
20640d21680cSYann Gautier 	if (stm32mp1_osc[_LSE] != 0U) {
20650d21680cSYann Gautier 		stm32mp1_lse_wait();
20667839a050SYann Gautier 	}
20677839a050SYann Gautier 
20687839a050SYann Gautier 	/* Configure with expected clock source */
20690d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
20707839a050SYann Gautier 	if (ret != 0) {
20717839a050SYann Gautier 		return ret;
20727839a050SYann Gautier 	}
20730d21680cSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
20747839a050SYann Gautier 	if (ret != 0) {
20757839a050SYann Gautier 		return ret;
20767839a050SYann Gautier 	}
2077b053a22eSYann Gautier 	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
2078b053a22eSYann Gautier 	if (ret != 0) {
2079b053a22eSYann Gautier 		return ret;
2080b053a22eSYann Gautier 	}
20810d21680cSYann Gautier 	stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css);
20827839a050SYann Gautier 
20837839a050SYann Gautier 	/* Configure PKCK */
20847839a050SYann Gautier 	pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
20857839a050SYann Gautier 	if (pkcs_cell != NULL) {
20867839a050SYann Gautier 		bool ckper_disabled = false;
20877839a050SYann Gautier 		uint32_t j;
2088bf1af154SPatrick Delaunay 		uint32_t usbreg_bootrom = 0U;
2089bf1af154SPatrick Delaunay 
2090bf1af154SPatrick Delaunay 		if (pll4_bootrom) {
2091bf1af154SPatrick Delaunay 			usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
2092bf1af154SPatrick Delaunay 		}
20937839a050SYann Gautier 
20947839a050SYann Gautier 		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
20953e6fab43SYann Gautier 			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
20967839a050SYann Gautier 
20977839a050SYann Gautier 			if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
20987839a050SYann Gautier 				ckper_disabled = true;
20997839a050SYann Gautier 				continue;
21007839a050SYann Gautier 			}
21010d21680cSYann Gautier 			stm32mp1_pkcs_config(pkcs);
21027839a050SYann Gautier 		}
21037839a050SYann Gautier 
21047839a050SYann Gautier 		/*
21057839a050SYann Gautier 		 * CKPER is source for some peripheral clocks
21067839a050SYann Gautier 		 * (FMC-NAND / QPSI-NOR) and switching source is allowed
21077839a050SYann Gautier 		 * only if previous clock is still ON
21087839a050SYann Gautier 		 * => deactivated CKPER only after switching clock
21097839a050SYann Gautier 		 */
21107839a050SYann Gautier 		if (ckper_disabled) {
21110d21680cSYann Gautier 			stm32mp1_pkcs_config(CLK_CKPER_DISABLED);
21127839a050SYann Gautier 		}
2113bf1af154SPatrick Delaunay 
2114bf1af154SPatrick Delaunay 		if (pll4_bootrom) {
2115bf1af154SPatrick Delaunay 			uint32_t usbreg_value, usbreg_mask;
2116bf1af154SPatrick Delaunay 			const struct stm32mp1_clk_sel *sel;
2117bf1af154SPatrick Delaunay 
2118bf1af154SPatrick Delaunay 			sel = clk_sel_ref(_USBPHY_SEL);
2119bf1af154SPatrick Delaunay 			usbreg_mask = (uint32_t)sel->msk << sel->src;
2120bf1af154SPatrick Delaunay 			sel = clk_sel_ref(_USBO_SEL);
2121bf1af154SPatrick Delaunay 			usbreg_mask |= (uint32_t)sel->msk << sel->src;
2122bf1af154SPatrick Delaunay 
2123bf1af154SPatrick Delaunay 			usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
2124bf1af154SPatrick Delaunay 				       usbreg_mask;
2125bf1af154SPatrick Delaunay 			usbreg_bootrom &= usbreg_mask;
2126bf1af154SPatrick Delaunay 			if (usbreg_bootrom != usbreg_value) {
2127bf1af154SPatrick Delaunay 				VERBOSE("forbidden new USB clk path\n");
2128bf1af154SPatrick Delaunay 				VERBOSE("vs bootrom on USB boot\n");
2129bf1af154SPatrick Delaunay 				return -FDT_ERR_BADVALUE;
2130bf1af154SPatrick Delaunay 			}
2131bf1af154SPatrick Delaunay 		}
21327839a050SYann Gautier 	}
21337839a050SYann Gautier 
21347839a050SYann Gautier 	/* Switch OFF HSI if not found in device-tree */
21350d21680cSYann Gautier 	if (stm32mp1_osc[_HSI] == 0U) {
21360d21680cSYann Gautier 		stm32mp1_hsi_set(false);
21377839a050SYann Gautier 	}
2138591d80c8SLionel Debieve 
2139591d80c8SLionel Debieve 	stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K));
21407839a050SYann Gautier 
21417839a050SYann Gautier 	/* Software Self-Refresh mode (SSR) during DDR initilialization */
21420d21680cSYann Gautier 	mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
21437839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_MASK,
21447839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SSR <<
21457839a050SYann Gautier 			   RCC_DDRITFCR_DDRCKMOD_SHIFT);
21467839a050SYann Gautier 
21477839a050SYann Gautier 	return 0;
21487839a050SYann Gautier }
21497839a050SYann Gautier 
21507839a050SYann Gautier static void stm32mp1_osc_clk_init(const char *name,
21517839a050SYann Gautier 				  enum stm32mp_osc_id index)
21527839a050SYann Gautier {
21537839a050SYann Gautier 	uint32_t frequency;
21547839a050SYann Gautier 
21550d21680cSYann Gautier 	if (fdt_osc_read_freq(name, &frequency) == 0) {
21560d21680cSYann Gautier 		stm32mp1_osc[index] = frequency;
21577839a050SYann Gautier 	}
21587839a050SYann Gautier }
21597839a050SYann Gautier 
21607839a050SYann Gautier static void stm32mp1_osc_init(void)
21617839a050SYann Gautier {
21627839a050SYann Gautier 	enum stm32mp_osc_id i;
21637839a050SYann Gautier 
21647839a050SYann Gautier 	for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
21650d21680cSYann Gautier 		stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i);
21667839a050SYann Gautier 	}
21677839a050SYann Gautier }
21687839a050SYann Gautier 
216937e8295aSEtienne Carriere #ifdef STM32MP_SHARED_RESOURCES
217037e8295aSEtienne Carriere /*
217137e8295aSEtienne Carriere  * Get the parent ID of the target parent clock, for tagging as secure
217237e8295aSEtienne Carriere  * shared clock dependencies.
217337e8295aSEtienne Carriere  */
217437e8295aSEtienne Carriere static int get_parent_id_parent(unsigned int parent_id)
217537e8295aSEtienne Carriere {
217637e8295aSEtienne Carriere 	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
217737e8295aSEtienne Carriere 	enum stm32mp1_pll_id pll_id;
217837e8295aSEtienne Carriere 	uint32_t p_sel;
217937e8295aSEtienne Carriere 	uintptr_t rcc_base = stm32mp_rcc_base();
218037e8295aSEtienne Carriere 
218137e8295aSEtienne Carriere 	switch (parent_id) {
218237e8295aSEtienne Carriere 	case _ACLK:
218337e8295aSEtienne Carriere 	case _PCLK4:
218437e8295aSEtienne Carriere 	case _PCLK5:
218537e8295aSEtienne Carriere 		s = _AXIS_SEL;
218637e8295aSEtienne Carriere 		break;
218737e8295aSEtienne Carriere 	case _PLL1_P:
218837e8295aSEtienne Carriere 	case _PLL1_Q:
218937e8295aSEtienne Carriere 	case _PLL1_R:
219037e8295aSEtienne Carriere 		pll_id = _PLL1;
219137e8295aSEtienne Carriere 		break;
219237e8295aSEtienne Carriere 	case _PLL2_P:
219337e8295aSEtienne Carriere 	case _PLL2_Q:
219437e8295aSEtienne Carriere 	case _PLL2_R:
219537e8295aSEtienne Carriere 		pll_id = _PLL2;
219637e8295aSEtienne Carriere 		break;
219737e8295aSEtienne Carriere 	case _PLL3_P:
219837e8295aSEtienne Carriere 	case _PLL3_Q:
219937e8295aSEtienne Carriere 	case _PLL3_R:
220037e8295aSEtienne Carriere 		pll_id = _PLL3;
220137e8295aSEtienne Carriere 		break;
220237e8295aSEtienne Carriere 	case _PLL4_P:
220337e8295aSEtienne Carriere 	case _PLL4_Q:
220437e8295aSEtienne Carriere 	case _PLL4_R:
220537e8295aSEtienne Carriere 		pll_id = _PLL4;
220637e8295aSEtienne Carriere 		break;
220737e8295aSEtienne Carriere 	case _PCLK1:
220837e8295aSEtienne Carriere 	case _PCLK2:
220937e8295aSEtienne Carriere 	case _HCLK2:
221037e8295aSEtienne Carriere 	case _HCLK6:
221137e8295aSEtienne Carriere 	case _CK_PER:
221237e8295aSEtienne Carriere 	case _CK_MPU:
221337e8295aSEtienne Carriere 	case _CK_MCU:
221437e8295aSEtienne Carriere 	case _USB_PHY_48:
221537e8295aSEtienne Carriere 		/* We do not expect to access these */
221637e8295aSEtienne Carriere 		panic();
221737e8295aSEtienne Carriere 		break;
221837e8295aSEtienne Carriere 	default:
221937e8295aSEtienne Carriere 		/* Other parents have no parent */
222037e8295aSEtienne Carriere 		return -1;
222137e8295aSEtienne Carriere 	}
222237e8295aSEtienne Carriere 
222337e8295aSEtienne Carriere 	if (s != _UNKNOWN_SEL) {
222437e8295aSEtienne Carriere 		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
222537e8295aSEtienne Carriere 
222637e8295aSEtienne Carriere 		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
222737e8295aSEtienne Carriere 			sel->msk;
222837e8295aSEtienne Carriere 
222937e8295aSEtienne Carriere 		if (p_sel < sel->nb_parent) {
223037e8295aSEtienne Carriere 			return (int)sel->parent[p_sel];
223137e8295aSEtienne Carriere 		}
223237e8295aSEtienne Carriere 	} else {
223337e8295aSEtienne Carriere 		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
223437e8295aSEtienne Carriere 
223537e8295aSEtienne Carriere 		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
223637e8295aSEtienne Carriere 			RCC_SELR_REFCLK_SRC_MASK;
223737e8295aSEtienne Carriere 
223837e8295aSEtienne Carriere 		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
223937e8295aSEtienne Carriere 			return (int)pll->refclk[p_sel];
224037e8295aSEtienne Carriere 		}
224137e8295aSEtienne Carriere 	}
224237e8295aSEtienne Carriere 
224337e8295aSEtienne Carriere 	VERBOSE("No parent selected for %s\n",
224437e8295aSEtienne Carriere 		stm32mp1_clk_parent_name[parent_id]);
224537e8295aSEtienne Carriere 
224637e8295aSEtienne Carriere 	return -1;
224737e8295aSEtienne Carriere }
224837e8295aSEtienne Carriere 
224937e8295aSEtienne Carriere static void secure_parent_clocks(unsigned long parent_id)
225037e8295aSEtienne Carriere {
225137e8295aSEtienne Carriere 	int grandparent_id;
225237e8295aSEtienne Carriere 
225337e8295aSEtienne Carriere 	switch (parent_id) {
225437e8295aSEtienne Carriere 	case _PLL3_P:
225537e8295aSEtienne Carriere 	case _PLL3_Q:
225637e8295aSEtienne Carriere 	case _PLL3_R:
225737e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
225837e8295aSEtienne Carriere 		break;
225937e8295aSEtienne Carriere 
226037e8295aSEtienne Carriere 	/* These clocks are always secure when RCC is secure */
226137e8295aSEtienne Carriere 	case _ACLK:
226237e8295aSEtienne Carriere 	case _HCLK2:
226337e8295aSEtienne Carriere 	case _HCLK6:
226437e8295aSEtienne Carriere 	case _PCLK4:
226537e8295aSEtienne Carriere 	case _PCLK5:
226637e8295aSEtienne Carriere 	case _PLL1_P:
226737e8295aSEtienne Carriere 	case _PLL1_Q:
226837e8295aSEtienne Carriere 	case _PLL1_R:
226937e8295aSEtienne Carriere 	case _PLL2_P:
227037e8295aSEtienne Carriere 	case _PLL2_Q:
227137e8295aSEtienne Carriere 	case _PLL2_R:
227237e8295aSEtienne Carriere 	case _HSI:
227337e8295aSEtienne Carriere 	case _HSI_KER:
227437e8295aSEtienne Carriere 	case _LSI:
227537e8295aSEtienne Carriere 	case _CSI:
227637e8295aSEtienne Carriere 	case _CSI_KER:
227737e8295aSEtienne Carriere 	case _HSE:
227837e8295aSEtienne Carriere 	case _HSE_KER:
227937e8295aSEtienne Carriere 	case _HSE_KER_DIV2:
2280cbd2e8a6SGabriel Fernandez 	case _HSE_RTC:
228137e8295aSEtienne Carriere 	case _LSE:
228237e8295aSEtienne Carriere 		break;
228337e8295aSEtienne Carriere 
228437e8295aSEtienne Carriere 	default:
228537e8295aSEtienne Carriere 		VERBOSE("Cannot secure parent clock %s\n",
228637e8295aSEtienne Carriere 			stm32mp1_clk_parent_name[parent_id]);
228737e8295aSEtienne Carriere 		panic();
228837e8295aSEtienne Carriere 	}
228937e8295aSEtienne Carriere 
229037e8295aSEtienne Carriere 	grandparent_id = get_parent_id_parent(parent_id);
229137e8295aSEtienne Carriere 	if (grandparent_id >= 0) {
229237e8295aSEtienne Carriere 		secure_parent_clocks(grandparent_id);
229337e8295aSEtienne Carriere 	}
229437e8295aSEtienne Carriere }
229537e8295aSEtienne Carriere 
229637e8295aSEtienne Carriere void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
229737e8295aSEtienne Carriere {
229837e8295aSEtienne Carriere 	int parent_id;
229937e8295aSEtienne Carriere 
230037e8295aSEtienne Carriere 	if (!stm32mp1_rcc_is_secure()) {
230137e8295aSEtienne Carriere 		return;
230237e8295aSEtienne Carriere 	}
230337e8295aSEtienne Carriere 
230437e8295aSEtienne Carriere 	switch (clock_id) {
230537e8295aSEtienne Carriere 	case PLL1:
230637e8295aSEtienne Carriere 	case PLL2:
230737e8295aSEtienne Carriere 		/* PLL1/PLL2 are always secure: nothing to do */
230837e8295aSEtienne Carriere 		break;
230937e8295aSEtienne Carriere 	case PLL3:
231037e8295aSEtienne Carriere 		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
231137e8295aSEtienne Carriere 		break;
231237e8295aSEtienne Carriere 	case PLL4:
231337e8295aSEtienne Carriere 		ERROR("PLL4 cannot be secured\n");
231437e8295aSEtienne Carriere 		panic();
231537e8295aSEtienne Carriere 		break;
231637e8295aSEtienne Carriere 	default:
231737e8295aSEtienne Carriere 		/* Others are expected gateable clock */
231837e8295aSEtienne Carriere 		parent_id = stm32mp1_clk_get_parent(clock_id);
231937e8295aSEtienne Carriere 		if (parent_id < 0) {
232037e8295aSEtienne Carriere 			INFO("No parent found for clock %lu\n", clock_id);
232137e8295aSEtienne Carriere 		} else {
232237e8295aSEtienne Carriere 			secure_parent_clocks(parent_id);
232337e8295aSEtienne Carriere 		}
232437e8295aSEtienne Carriere 		break;
232537e8295aSEtienne Carriere 	}
232637e8295aSEtienne Carriere }
232737e8295aSEtienne Carriere #endif /* STM32MP_SHARED_RESOURCES */
232837e8295aSEtienne Carriere 
23296cb45f89SYann Gautier static void sync_earlyboot_clocks_state(void)
23306cb45f89SYann Gautier {
2331033b6c3aSEtienne Carriere 	unsigned int idx;
2332033b6c3aSEtienne Carriere 	const unsigned long secure_enable[] = {
2333033b6c3aSEtienne Carriere 		AXIDCG,
2334033b6c3aSEtienne Carriere 		BSEC,
2335033b6c3aSEtienne Carriere 		DDRC1, DDRC1LP,
2336033b6c3aSEtienne Carriere 		DDRC2, DDRC2LP,
2337033b6c3aSEtienne Carriere 		DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
2338033b6c3aSEtienne Carriere 		DDRPHYC, DDRPHYCLP,
2339373f06beSLionel Debieve 		RTCAPB,
2340033b6c3aSEtienne Carriere 		TZC1, TZC2,
2341033b6c3aSEtienne Carriere 		TZPC,
2342033b6c3aSEtienne Carriere 		STGEN_K,
2343033b6c3aSEtienne Carriere 	};
2344033b6c3aSEtienne Carriere 
2345033b6c3aSEtienne Carriere 	for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
2346033b6c3aSEtienne Carriere 		stm32mp_clk_enable(secure_enable[idx]);
2347033b6c3aSEtienne Carriere 	}
23486cb45f89SYann Gautier }
23496cb45f89SYann Gautier 
235033667d29SYann Gautier static const struct clk_ops stm32mp_clk_ops = {
235133667d29SYann Gautier 	.enable		= stm32mp_clk_enable,
235233667d29SYann Gautier 	.disable	= stm32mp_clk_disable,
235333667d29SYann Gautier 	.is_enabled	= stm32mp_clk_is_enabled,
235433667d29SYann Gautier 	.get_rate	= stm32mp_clk_get_rate,
235533667d29SYann Gautier 	.get_parent	= stm32mp1_clk_get_parent,
235633667d29SYann Gautier };
235733667d29SYann Gautier 
23587839a050SYann Gautier int stm32mp1_clk_probe(void)
23597839a050SYann Gautier {
2360812daf91SLionel Debieve #if defined(IMAGE_BL32)
2361812daf91SLionel Debieve 	if (!fdt_get_rcc_secure_state()) {
2362812daf91SLionel Debieve 		mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U);
2363812daf91SLionel Debieve 	}
2364812daf91SLionel Debieve #endif
2365812daf91SLionel Debieve 
23667839a050SYann Gautier 	stm32mp1_osc_init();
23677839a050SYann Gautier 
23686cb45f89SYann Gautier 	sync_earlyboot_clocks_state();
23696cb45f89SYann Gautier 
237033667d29SYann Gautier 	clk_register(&stm32mp_clk_ops);
237133667d29SYann Gautier 
23727839a050SYann Gautier 	return 0;
23737839a050SYann Gautier }
2374