stm32mp1: Add clock and reset support

The clock driver is under dual license, BSD and GPLv2.
The clock driver uses device tree, so a minimal support for this is added.
The required files for driver and DTS files are in include/dt-bindings/.

Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
new file mode 100644
index 0000000..7dff98b
--- /dev/null
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -0,0 +1,1611 @@
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <errno.h>
+#include <generic_delay_timer.h>
+#include <libfdt.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stdint.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_clkfunc.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_rcc.h>
+#include <utils_def.h>
+
+#define MAX_HSI_HZ	64000000
+
+#define TIMEOUT_200MS	(plat_get_syscnt_freq2() / 5U)
+#define TIMEOUT_1S	plat_get_syscnt_freq2()
+
+#define PLLRDY_TIMEOUT	TIMEOUT_200MS
+#define CLKSRC_TIMEOUT	TIMEOUT_200MS
+#define CLKDIV_TIMEOUT	TIMEOUT_200MS
+#define HSIDIV_TIMEOUT	TIMEOUT_200MS
+#define OSCRDY_TIMEOUT	TIMEOUT_1S
+
+enum stm32mp1_parent_id {
+/* Oscillators are defined in enum stm32mp_osc_id */
+
+/* Other parent source */
+	_HSI_KER = NB_OSC,
+	_HSE_KER,
+	_HSE_KER_DIV2,
+	_CSI_KER,
+	_PLL1_P,
+	_PLL1_Q,
+	_PLL1_R,
+	_PLL2_P,
+	_PLL2_Q,
+	_PLL2_R,
+	_PLL3_P,
+	_PLL3_Q,
+	_PLL3_R,
+	_PLL4_P,
+	_PLL4_Q,
+	_PLL4_R,
+	_ACLK,
+	_PCLK1,
+	_PCLK2,
+	_PCLK3,
+	_PCLK4,
+	_PCLK5,
+	_HCLK6,
+	_HCLK2,
+	_CK_PER,
+	_CK_MPU,
+	_PARENT_NB,
+	_UNKNOWN_ID = 0xff,
+};
+
+enum stm32mp1_parent_sel {
+	_I2C46_SEL,
+	_UART6_SEL,
+	_UART24_SEL,
+	_UART35_SEL,
+	_UART78_SEL,
+	_SDMMC12_SEL,
+	_SDMMC3_SEL,
+	_QSPI_SEL,
+	_FMC_SEL,
+	_USBPHY_SEL,
+	_USBO_SEL,
+	_STGEN_SEL,
+	_PARENT_SEL_NB,
+	_UNKNOWN_SEL = 0xff,
+};
+
+enum stm32mp1_pll_id {
+	_PLL1,
+	_PLL2,
+	_PLL3,
+	_PLL4,
+	_PLL_NB
+};
+
+enum stm32mp1_div_id {
+	_DIV_P,
+	_DIV_Q,
+	_DIV_R,
+	_DIV_NB,
+};
+
+enum stm32mp1_clksrc_id {
+	CLKSRC_MPU,
+	CLKSRC_AXI,
+	CLKSRC_PLL12,
+	CLKSRC_PLL3,
+	CLKSRC_PLL4,
+	CLKSRC_RTC,
+	CLKSRC_MCO1,
+	CLKSRC_MCO2,
+	CLKSRC_NB
+};
+
+enum stm32mp1_clkdiv_id {
+	CLKDIV_MPU,
+	CLKDIV_AXI,
+	CLKDIV_APB1,
+	CLKDIV_APB2,
+	CLKDIV_APB3,
+	CLKDIV_APB4,
+	CLKDIV_APB5,
+	CLKDIV_RTC,
+	CLKDIV_MCO1,
+	CLKDIV_MCO2,
+	CLKDIV_NB
+};
+
+enum stm32mp1_pllcfg {
+	PLLCFG_M,
+	PLLCFG_N,
+	PLLCFG_P,
+	PLLCFG_Q,
+	PLLCFG_R,
+	PLLCFG_O,
+	PLLCFG_NB
+};
+
+enum stm32mp1_pllcsg {
+	PLLCSG_MOD_PER,
+	PLLCSG_INC_STEP,
+	PLLCSG_SSCG_MODE,
+	PLLCSG_NB
+};
+
+enum stm32mp1_plltype {
+	PLL_800,
+	PLL_1600,
+	PLL_TYPE_NB
+};
+
+struct stm32mp1_pll {
+	uint8_t refclk_min;
+	uint8_t refclk_max;
+	uint8_t divn_max;
+};
+
+struct stm32mp1_clk_gate {
+	uint16_t offset;
+	uint8_t bit;
+	uint8_t index;
+	uint8_t set_clr;
+	enum stm32mp1_parent_sel sel;
+	enum stm32mp1_parent_id fixed;
+	bool secure;
+};
+
+struct stm32mp1_clk_sel {
+	uint16_t offset;
+	uint8_t src;
+	uint8_t msk;
+	uint8_t nb_parent;
+	const uint8_t *parent;
+};
+
+#define REFCLK_SIZE 4
+struct stm32mp1_clk_pll {
+	enum stm32mp1_plltype plltype;
+	uint16_t rckxselr;
+	uint16_t pllxcfgr1;
+	uint16_t pllxcfgr2;
+	uint16_t pllxfracr;
+	uint16_t pllxcr;
+	uint16_t pllxcsgr;
+	enum stm32mp_osc_id refclk[REFCLK_SIZE];
+};
+
+struct stm32mp1_clk_data {
+	const struct stm32mp1_clk_gate *gate;
+	const struct stm32mp1_clk_sel *sel;
+	const struct stm32mp1_clk_pll *pll;
+	const int nb_gate;
+};
+
+struct stm32mp1_clk_priv {
+	uint32_t base;
+	const struct stm32mp1_clk_data *data;
+	unsigned long osc[NB_OSC];
+	uint32_t pkcs_usb_value;
+};
+
+#define STM32MP1_CLK(off, b, idx, s)			\
+	{						\
+		.offset = (off),			\
+		.bit = (b),				\
+		.index = (idx),				\
+		.set_clr = 0,				\
+		.sel = (s),				\
+		.fixed = _UNKNOWN_ID,			\
+		.secure = 0,				\
+	}
+
+#define STM32MP1_CLK_F(off, b, idx, f)			\
+	{						\
+		.offset = (off),			\
+		.bit = (b),				\
+		.index = (idx),				\
+		.set_clr = 0,				\
+		.sel = _UNKNOWN_SEL,			\
+		.fixed = (f),				\
+		.secure = 0,				\
+	}
+
+#define STM32MP1_CLK_SET_CLR(off, b, idx, s)		\
+	{						\
+		.offset = (off),			\
+		.bit = (b),				\
+		.index = (idx),				\
+		.set_clr = 1,				\
+		.sel = (s),				\
+		.fixed = _UNKNOWN_ID,			\
+		.secure = 0,				\
+	}
+
+#define STM32MP1_CLK_SET_CLR_F(off, b, idx, f)		\
+	{						\
+		.offset = (off),			\
+		.bit = (b),				\
+		.index = (idx),				\
+		.set_clr = 1,				\
+		.sel = _UNKNOWN_SEL,			\
+		.fixed = (f),				\
+		.secure = 0,				\
+	}
+
+#define STM32MP1_CLK_SEC_SET_CLR(off, b, idx, s)	\
+	{						\
+		.offset = (off),			\
+		.bit = (b),				\
+		.index = (idx),				\
+		.set_clr = 1,				\
+		.sel = (s),				\
+		.fixed = _UNKNOWN_ID,			\
+		.secure = 1,				\
+	}
+
+#define STM32MP1_CLK_PARENT(idx, off, s, m, p)		\
+	[(idx)] = {					\
+		.offset = (off),			\
+		.src = (s),				\
+		.msk = (m),				\
+		.parent = (p),				\
+		.nb_parent = ARRAY_SIZE((p))		\
+	}
+
+#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3,	\
+			 off4, off5, off6,		\
+			 p1, p2, p3, p4)		\
+	[(idx)] = {					\
+		.plltype = (type),			\
+		.rckxselr = (off1),			\
+		.pllxcfgr1 = (off2),			\
+		.pllxcfgr2 = (off3),			\
+		.pllxfracr = (off4),			\
+		.pllxcr = (off5),			\
+		.pllxcsgr = (off6),			\
+		.refclk[0] = (p1),			\
+		.refclk[1] = (p2),			\
+		.refclk[2] = (p3),			\
+		.refclk[3] = (p4),			\
+	}
+
+static const uint8_t stm32mp1_clks[][2] = {
+	{CK_PER, _CK_PER},
+	{CK_MPU, _CK_MPU},
+	{CK_AXI, _ACLK},
+	{CK_HSE, _HSE},
+	{CK_CSI, _CSI},
+	{CK_LSI, _LSI},
+	{CK_LSE, _LSE},
+	{CK_HSI, _HSI},
+	{CK_HSE_DIV2, _HSE_KER_DIV2},
+};
+
+static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
+	STM32MP1_CLK(RCC_DDRITFCR, 0, DDRC1, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 1, DDRC1LP, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 2, DDRC2, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 3, DDRC2LP, _UNKNOWN_SEL),
+	STM32MP1_CLK_F(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R),
+	STM32MP1_CLK(RCC_DDRITFCR, 5, DDRPHYCLP, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 6, DDRCAPB, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 7, DDRCAPBLP, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 8, AXIDCG, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 9, DDRPHYCAPB, _UNKNOWN_SEL),
+	STM32MP1_CLK(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _UNKNOWN_SEL),
+
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL),
+
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
+
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
+
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 11, TZC1, _UNKNOWN_SEL),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 12, TZC2, _UNKNOWN_SEL),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL),
+
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
+
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL),
+
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 0, GPIOZ, _UNKNOWN_SEL),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 5, HASH1, _UNKNOWN_SEL),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 6, RNG1_K, _CSI_KER),
+	STM32MP1_CLK_SEC_SET_CLR(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _UNKNOWN_SEL),
+
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
+	STM32MP1_CLK_SET_CLR(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
+
+	STM32MP1_CLK(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
+};
+
+static const uint8_t i2c46_parents[] = {_PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER};
+static const uint8_t uart6_parents[] = {_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER,
+					_HSE_KER};
+static const uint8_t uart24_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER,
+					 _HSE_KER};
+static const uint8_t uart35_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER,
+					 _HSE_KER};
+static const uint8_t uart78_parents[] = {_PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER,
+					 _HSE_KER};
+static const uint8_t sdmmc12_parents[] = {_HCLK6, _PLL3_R, _PLL4_P, _HSI_KER};
+static const uint8_t sdmmc3_parents[] = {_HCLK2, _PLL3_R, _PLL4_P, _HSI_KER};
+static const uint8_t qspi_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER};
+static const uint8_t fmc_parents[] = {_ACLK, _PLL3_R, _PLL4_P, _CK_PER};
+static const uint8_t usbphy_parents[] = {_HSE_KER, _PLL4_R, _HSE_KER_DIV2};
+static const uint8_t usbo_parents[] = {_PLL4_R, _USB_PHY_48};
+static const uint8_t stgen_parents[] = {_HSI_KER, _HSE_KER};
+
+static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
+	STM32MP1_CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents),
+	STM32MP1_CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents),
+	STM32MP1_CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7,
+			    uart24_parents),
+	STM32MP1_CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7,
+			    uart35_parents),
+	STM32MP1_CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7,
+			    uart78_parents),
+	STM32MP1_CLK_PARENT(_SDMMC12_SEL, RCC_SDMMC12CKSELR, 0, 0x7,
+			    sdmmc12_parents),
+	STM32MP1_CLK_PARENT(_SDMMC3_SEL, RCC_SDMMC3CKSELR, 0, 0x7,
+			    sdmmc3_parents),
+	STM32MP1_CLK_PARENT(_QSPI_SEL, RCC_QSPICKSELR, 0, 0xf, qspi_parents),
+	STM32MP1_CLK_PARENT(_FMC_SEL, RCC_FMCCKSELR, 0, 0xf, fmc_parents),
+	STM32MP1_CLK_PARENT(_USBPHY_SEL, RCC_USBCKSELR, 0, 0x3, usbphy_parents),
+	STM32MP1_CLK_PARENT(_USBO_SEL, RCC_USBCKSELR, 4, 0x1, usbo_parents),
+	STM32MP1_CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents),
+};
+
+/* Define characteristic of PLL according type */
+#define DIVN_MIN	24
+static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = {
+	[PLL_800] = {
+		.refclk_min = 4,
+		.refclk_max = 16,
+		.divn_max = 99,
+	},
+	[PLL_1600] = {
+		.refclk_min = 8,
+		.refclk_max = 16,
+		.divn_max = 199,
+	},
+};
+
+/* PLLNCFGR2 register divider by output */
+static const uint8_t pllncfgr2[_DIV_NB] = {
+	[_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT,
+	[_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT,
+	[_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT
+};
+
+static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = {
+	STM32MP1_CLK_PLL(_PLL1, PLL_1600,
+			 RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2,
+			 RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR,
+			 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
+	STM32MP1_CLK_PLL(_PLL2, PLL_1600,
+			 RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2,
+			 RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR,
+			 _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID),
+	STM32MP1_CLK_PLL(_PLL3, PLL_800,
+			 RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2,
+			 RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR,
+			 _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID),
+	STM32MP1_CLK_PLL(_PLL4, PLL_800,
+			 RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2,
+			 RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR,
+			 _HSI, _HSE, _CSI, _I2S_CKIN),
+};
+
+/* Prescaler table lookups for clock computation */
+
+/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */
+#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div
+#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div
+static const uint8_t stm32mp1_mpu_apbx_div[8] = {
+	0, 1, 2, 3, 4, 4, 4, 4
+};
+
+/* div = /1 /2 /3 /4 */
+static const uint8_t stm32mp1_axi_div[8] = {
+	1, 2, 3, 4, 4, 4, 4, 4
+};
+
+static const struct stm32mp1_clk_data stm32mp1_data = {
+	.gate = stm32mp1_clk_gate,
+	.sel = stm32mp1_clk_sel,
+	.pll = stm32mp1_clk_pll,
+	.nb_gate = ARRAY_SIZE(stm32mp1_clk_gate),
+};
+
+static struct stm32mp1_clk_priv stm32mp1_clk_priv_data;
+
+static unsigned long stm32mp1_clk_get_fixed(struct stm32mp1_clk_priv *priv,
+					    enum stm32mp_osc_id idx)
+{
+	if (idx >= NB_OSC) {
+		return 0;
+	}
+
+	return priv->osc[idx];
+}
+
+static int stm32mp1_clk_get_id(struct stm32mp1_clk_priv *priv, unsigned long id)
+{
+	const struct stm32mp1_clk_gate *gate = priv->data->gate;
+	int i;
+	int nb_clks = priv->data->nb_gate;
+
+	for (i = 0; i < nb_clks; i++) {
+		if (gate[i].index == id) {
+			return i;
+		}
+	}
+
+	ERROR("%s: clk id %d not found\n", __func__, (uint32_t)id);
+
+	return -EINVAL;
+}
+
+static enum stm32mp1_parent_sel
+stm32mp1_clk_get_sel(struct stm32mp1_clk_priv *priv, int i)
+{
+	const struct stm32mp1_clk_gate *gate = priv->data->gate;
+
+	return gate[i].sel;
+}
+
+static enum stm32mp1_parent_id
+stm32mp1_clk_get_fixed_parent(struct stm32mp1_clk_priv *priv, int i)
+{
+	const struct stm32mp1_clk_gate *gate = priv->data->gate;
+
+	return gate[i].fixed;
+}
+
+static int stm32mp1_clk_get_parent(struct stm32mp1_clk_priv *priv,
+				   unsigned long id)
+{
+	const struct stm32mp1_clk_sel *sel = priv->data->sel;
+	uint32_t j, p_sel;
+	int i;
+	enum stm32mp1_parent_id p;
+	enum stm32mp1_parent_sel s;
+
+	for (j = 0; j < ARRAY_SIZE(stm32mp1_clks); j++) {
+		if (stm32mp1_clks[j][0] == id) {
+			return (int)stm32mp1_clks[j][1];
+		}
+	}
+
+	i = stm32mp1_clk_get_id(priv, id);
+	if (i < 0) {
+		return i;
+	}
+
+	p = stm32mp1_clk_get_fixed_parent(priv, i);
+	if (p < _PARENT_NB) {
+		return (int)p;
+	}
+
+	s = stm32mp1_clk_get_sel(priv, i);
+	if (s >= _PARENT_SEL_NB) {
+		return -EINVAL;
+	}
+
+	p_sel = (mmio_read_32(priv->base + sel[s].offset) >> sel[s].src) &
+		sel[s].msk;
+
+	if (p_sel < sel[s].nb_parent) {
+		return (int)sel[s].parent[p_sel];
+	}
+
+	ERROR("%s: no parents defined for clk id %ld\n", __func__, id);
+
+	return -EINVAL;
+}
+
+static unsigned long stm32mp1_pll_get_fref_ck(struct stm32mp1_clk_priv *priv,
+					      enum stm32mp1_pll_id pll_id)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	uint32_t selr, src;
+	unsigned long refclk;
+
+	selr = mmio_read_32(priv->base + pll[pll_id].rckxselr);
+	src = selr & RCC_SELR_REFCLK_SRC_MASK;
+
+	refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]);
+
+	return refclk;
+}
+
+/*
+ * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL
+ * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1)
+ * - PLL3 & PLL4 => return VCO     with Fpll_y_ck = FVCO / (DIVy + 1)
+ * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1)
+ */
+static unsigned long stm32mp1_pll_get_fvco(struct stm32mp1_clk_priv *priv,
+					   enum stm32mp1_pll_id pll_id)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	unsigned long refclk, fvco;
+	uint32_t cfgr1, fracr, divm, divn;
+
+	cfgr1 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr1);
+	fracr = mmio_read_32(priv->base + pll[pll_id].pllxfracr);
+
+	divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT;
+	divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK;
+
+	refclk = stm32mp1_pll_get_fref_ck(priv, pll_id);
+
+	/*
+	 * With FRACV :
+	 *   Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1)
+	 * Without FRACV
+	 *   Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1)
+	 */
+	if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) {
+		uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK)
+			    >> RCC_PLLNFRACR_FRACV_SHIFT;
+		unsigned long long numerator, denominator;
+
+		numerator = ((unsigned long long)divn + 1U) << 13;
+		numerator = (refclk * numerator) + fracv;
+		denominator = ((unsigned long long)divm + 1U)  << 13;
+		fvco = (unsigned long)(numerator / denominator);
+	} else {
+		fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U));
+	}
+
+	return fvco;
+}
+
+static unsigned long stm32mp1_read_pll_freq(struct stm32mp1_clk_priv *priv,
+					    enum stm32mp1_pll_id pll_id,
+					    enum stm32mp1_div_id div_id)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	unsigned long dfout;
+	uint32_t cfgr2, divy;
+
+	if (div_id >= _DIV_NB) {
+		return 0;
+	}
+
+	cfgr2 = mmio_read_32(priv->base + pll[pll_id].pllxcfgr2);
+	divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK;
+
+	dfout = stm32mp1_pll_get_fvco(priv, pll_id) / (divy + 1U);
+
+	return dfout;
+}
+
+static unsigned long stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p)
+{
+	uint32_t reg, clkdiv;
+	unsigned long clock = 0;
+
+	switch (p) {
+	case _CK_MPU:
+	/* MPU sub system */
+		reg = mmio_read_32(priv->base + RCC_MPCKSELR);
+		switch (reg & RCC_SELR_SRC_MASK) {
+		case RCC_MPCKSELR_HSI:
+			clock = stm32mp1_clk_get_fixed(priv, _HSI);
+			break;
+		case RCC_MPCKSELR_HSE:
+			clock = stm32mp1_clk_get_fixed(priv, _HSE);
+			break;
+		case RCC_MPCKSELR_PLL:
+			clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
+			break;
+		case RCC_MPCKSELR_PLL_MPUDIV:
+			clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
+
+			reg = mmio_read_32(priv->base + RCC_MPCKDIVR);
+			clkdiv = reg & RCC_MPUDIV_MASK;
+			if (clkdiv != 0U) {
+				clock /= stm32mp1_mpu_div[clkdiv];
+			}
+
+			break;
+		default:
+			break;
+		}
+		break;
+	/* AXI sub system */
+	case _ACLK:
+	case _HCLK2:
+	case _HCLK6:
+	case _PCLK4:
+	case _PCLK5:
+		reg = mmio_read_32(priv->base + RCC_ASSCKSELR);
+		switch (reg & RCC_SELR_SRC_MASK) {
+		case RCC_ASSCKSELR_HSI:
+			clock = stm32mp1_clk_get_fixed(priv, _HSI);
+			break;
+		case RCC_ASSCKSELR_HSE:
+			clock = stm32mp1_clk_get_fixed(priv, _HSE);
+			break;
+		case RCC_ASSCKSELR_PLL:
+			clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P);
+			break;
+		default:
+			break;
+		}
+
+		/* System clock divider */
+		reg = mmio_read_32(priv->base + RCC_AXIDIVR);
+		clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK];
+
+		switch (p) {
+		case _PCLK4:
+			reg = mmio_read_32(priv->base + RCC_APB4DIVR);
+			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
+			break;
+		case _PCLK5:
+			reg = mmio_read_32(priv->base + RCC_APB5DIVR);
+			clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK];
+			break;
+		default:
+			break;
+		}
+		break;
+	case _CK_PER:
+		reg = mmio_read_32(priv->base + RCC_CPERCKSELR);
+		switch (reg & RCC_SELR_SRC_MASK) {
+		case RCC_CPERCKSELR_HSI:
+			clock = stm32mp1_clk_get_fixed(priv, _HSI);
+			break;
+		case RCC_CPERCKSELR_HSE:
+			clock = stm32mp1_clk_get_fixed(priv, _HSE);
+			break;
+		case RCC_CPERCKSELR_CSI:
+			clock = stm32mp1_clk_get_fixed(priv, _CSI);
+			break;
+		default:
+			break;
+		}
+		break;
+	case _HSI:
+	case _HSI_KER:
+		clock = stm32mp1_clk_get_fixed(priv, _HSI);
+		break;
+	case _CSI:
+	case _CSI_KER:
+		clock = stm32mp1_clk_get_fixed(priv, _CSI);
+		break;
+	case _HSE:
+	case _HSE_KER:
+		clock = stm32mp1_clk_get_fixed(priv, _HSE);
+		break;
+	case _HSE_KER_DIV2:
+		clock = stm32mp1_clk_get_fixed(priv, _HSE) >> 1;
+		break;
+	case _LSI:
+		clock = stm32mp1_clk_get_fixed(priv, _LSI);
+		break;
+	case _LSE:
+		clock = stm32mp1_clk_get_fixed(priv, _LSE);
+		break;
+	/* PLL */
+	case _PLL1_P:
+		clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_P);
+		break;
+	case _PLL1_Q:
+		clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_Q);
+		break;
+	case _PLL1_R:
+		clock = stm32mp1_read_pll_freq(priv, _PLL1, _DIV_R);
+		break;
+	case _PLL2_P:
+		clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_P);
+		break;
+	case _PLL2_Q:
+		clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_Q);
+		break;
+	case _PLL2_R:
+		clock = stm32mp1_read_pll_freq(priv, _PLL2, _DIV_R);
+		break;
+	case _PLL3_P:
+		clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_P);
+		break;
+	case _PLL3_Q:
+		clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_Q);
+		break;
+	case _PLL3_R:
+		clock = stm32mp1_read_pll_freq(priv, _PLL3, _DIV_R);
+		break;
+	case _PLL4_P:
+		clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_P);
+		break;
+	case _PLL4_Q:
+		clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_Q);
+		break;
+	case _PLL4_R:
+		clock = stm32mp1_read_pll_freq(priv, _PLL4, _DIV_R);
+		break;
+	/* Other */
+	case _USB_PHY_48:
+		clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48);
+		break;
+	default:
+		break;
+	}
+
+	return clock;
+}
+
+bool stm32mp1_clk_is_enabled(unsigned long id)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+	const struct stm32mp1_clk_gate *gate = priv->data->gate;
+	int i = stm32mp1_clk_get_id(priv, id);
+
+	if (i < 0) {
+		return false;
+	}
+
+	return ((mmio_read_32(priv->base + gate[i].offset) &
+		 BIT(gate[i].bit)) != 0U);
+}
+
+int stm32mp1_clk_enable(unsigned long id)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+	const struct stm32mp1_clk_gate *gate = priv->data->gate;
+	int i = stm32mp1_clk_get_id(priv, id);
+
+	if (i < 0) {
+		return i;
+	}
+
+	if (gate[i].set_clr != 0U) {
+		mmio_write_32(priv->base + gate[i].offset, BIT(gate[i].bit));
+	} else {
+		mmio_setbits_32(priv->base + gate[i].offset, BIT(gate[i].bit));
+	}
+
+	return 0;
+}
+
+int stm32mp1_clk_disable(unsigned long id)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+	const struct stm32mp1_clk_gate *gate = priv->data->gate;
+	int i = stm32mp1_clk_get_id(priv, id);
+
+	if (i < 0) {
+		return i;
+	}
+
+	if (gate[i].set_clr != 0U) {
+		mmio_write_32(priv->base + gate[i].offset
+			      + RCC_MP_ENCLRR_OFFSET,
+			      BIT(gate[i].bit));
+	} else {
+		mmio_clrbits_32(priv->base + gate[i].offset, BIT(gate[i].bit));
+	}
+
+	return 0;
+}
+
+unsigned long stm32mp1_clk_get_rate(unsigned long id)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+	int p = stm32mp1_clk_get_parent(priv, id);
+	unsigned long rate;
+
+	if (p < 0) {
+		return 0;
+	}
+
+	rate = stm32mp1_clk_get(priv, p);
+
+	return rate;
+}
+
+static void stm32mp1_ls_osc_set(int enable, uint32_t rcc, uint32_t offset,
+				uint32_t mask_on)
+{
+	uint32_t address = rcc + offset;
+
+	if (enable != 0) {
+		mmio_setbits_32(address, mask_on);
+	} else {
+		mmio_clrbits_32(address, mask_on);
+	}
+}
+
+static void stm32mp1_hs_ocs_set(int enable, uint32_t rcc, uint32_t mask_on)
+{
+	if (enable != 0) {
+		mmio_setbits_32(rcc + RCC_OCENSETR, mask_on);
+	} else {
+		mmio_setbits_32(rcc + RCC_OCENCLRR, mask_on);
+	}
+}
+
+static int stm32mp1_osc_wait(int enable, uint32_t rcc, uint32_t offset,
+			     uint32_t mask_rdy)
+{
+	unsigned long start;
+	uint32_t mask_test;
+	uint32_t address = rcc + offset;
+
+	if (enable != 0) {
+		mask_test = mask_rdy;
+	} else {
+		mask_test = 0;
+	}
+
+	start = get_timer(0);
+	while ((mmio_read_32(address) & mask_rdy) != mask_test) {
+		if (get_timer(start) > OSCRDY_TIMEOUT) {
+			ERROR("OSC %x @ %x timeout for enable=%d : 0x%x\n",
+			      mask_rdy, address, enable, mmio_read_32(address));
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static void stm32mp1_lse_enable(uint32_t rcc, bool bypass, uint32_t lsedrv)
+{
+	uint32_t value;
+
+	if (bypass) {
+		mmio_setbits_32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP);
+	}
+
+	/*
+	 * Warning: not recommended to switch directly from "high drive"
+	 * to "medium low drive", and vice-versa.
+	 */
+	value = (mmio_read_32(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >>
+		RCC_BDCR_LSEDRV_SHIFT;
+
+	while (value != lsedrv) {
+		if (value > lsedrv) {
+			value--;
+		} else {
+			value++;
+		}
+
+		mmio_clrsetbits_32(rcc + RCC_BDCR,
+				   RCC_BDCR_LSEDRV_MASK,
+				   value << RCC_BDCR_LSEDRV_SHIFT);
+	}
+
+	stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON);
+}
+
+static void stm32mp1_lse_wait(uint32_t rcc)
+{
+	if (stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY) != 0) {
+		VERBOSE("%s: failed\n", __func__);
+	}
+}
+
+static void stm32mp1_lsi_set(uint32_t rcc, int enable)
+{
+	stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION);
+	if (stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) !=
+	    0) {
+		VERBOSE("%s: failed\n", __func__);
+	}
+}
+
+static void stm32mp1_hse_enable(uint32_t rcc, bool bypass, bool css)
+{
+	if (bypass) {
+		mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP);
+	}
+
+	stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON);
+	if (stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY) !=
+	    0) {
+		VERBOSE("%s: failed\n", __func__);
+	}
+
+	if (css) {
+		mmio_setbits_32(rcc + RCC_OCENSETR, RCC_OCENR_HSECSSON);
+	}
+}
+
+static void stm32mp1_csi_set(uint32_t rcc, int enable)
+{
+	stm32mp1_ls_osc_set(enable, rcc, RCC_OCENSETR, RCC_OCENR_CSION);
+	if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) !=
+	    0) {
+		VERBOSE("%s: failed\n", __func__);
+	}
+}
+
+static void stm32mp1_hsi_set(uint32_t rcc, int enable)
+{
+	stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION);
+	if (stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) !=
+	    0) {
+		VERBOSE("%s: failed\n", __func__);
+	}
+}
+
+static int stm32mp1_set_hsidiv(uint32_t rcc, uint8_t hsidiv)
+{
+	unsigned long start;
+	uint32_t address = rcc + RCC_OCRDYR;
+
+	mmio_clrsetbits_32(rcc + RCC_HSICFGR,
+			   RCC_HSICFGR_HSIDIV_MASK,
+			   RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv);
+
+	start = get_timer(0);
+	while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) {
+		if (get_timer(start) > HSIDIV_TIMEOUT) {
+			ERROR("HSIDIV failed @ 0x%x: 0x%x\n",
+			      address, mmio_read_32(address));
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int stm32mp1_hsidiv(uint32_t rcc, unsigned long hsifreq)
+{
+	uint8_t hsidiv;
+	uint32_t hsidivfreq = MAX_HSI_HZ;
+
+	for (hsidiv = 0; hsidiv < 4U; hsidiv++) {
+		if (hsidivfreq == hsifreq) {
+			break;
+		}
+
+		hsidivfreq /= 2U;
+	}
+
+	if (hsidiv == 4U) {
+		ERROR("Invalid clk-hsi frequency\n");
+		return -1;
+	}
+
+	if (hsidiv != 0U) {
+		return stm32mp1_set_hsidiv(rcc, hsidiv);
+	}
+
+	return 0;
+}
+
+static void stm32mp1_pll_start(struct stm32mp1_clk_priv *priv,
+			       enum stm32mp1_pll_id pll_id)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+
+	mmio_write_32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_PLLON);
+}
+
+static int stm32mp1_pll_output(struct stm32mp1_clk_priv *priv,
+			       enum stm32mp1_pll_id pll_id, uint32_t output)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	uint32_t pllxcr = priv->base + pll[pll_id].pllxcr;
+	unsigned long start;
+
+	start = get_timer(0);
+	/* Wait PLL lock */
+	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
+		if (get_timer(start) > PLLRDY_TIMEOUT) {
+			ERROR("PLL%d start failed @ 0x%x: 0x%x\n",
+			      pll_id, pllxcr, mmio_read_32(pllxcr));
+			return -ETIMEDOUT;
+		}
+	}
+
+	/* Start the requested output */
+	mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT);
+
+	return 0;
+}
+
+static int stm32mp1_pll_stop(struct stm32mp1_clk_priv *priv,
+			     enum stm32mp1_pll_id pll_id)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	uint32_t pllxcr = priv->base + pll[pll_id].pllxcr;
+	unsigned long start;
+
+	/* Stop all output */
+	mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN |
+			RCC_PLLNCR_DIVREN);
+
+	/* Stop PLL */
+	mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON);
+
+	start = get_timer(0);
+	/* Wait PLL stopped */
+	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
+		if (get_timer(start) > PLLRDY_TIMEOUT) {
+			ERROR("PLL%d stop failed @ 0x%x: 0x%x\n",
+			      pll_id, pllxcr, mmio_read_32(pllxcr));
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static void stm32mp1_pll_config_output(struct stm32mp1_clk_priv *priv,
+				       enum stm32mp1_pll_id pll_id,
+				       uint32_t *pllcfg)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	uint32_t rcc = priv->base;
+	uint32_t value;
+
+	value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) &
+		RCC_PLLNCFGR2_DIVP_MASK;
+	value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) &
+		 RCC_PLLNCFGR2_DIVQ_MASK;
+	value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) &
+		 RCC_PLLNCFGR2_DIVR_MASK;
+	mmio_write_32(rcc + pll[pll_id].pllxcfgr2, value);
+}
+
+static int stm32mp1_pll_config(struct stm32mp1_clk_priv *priv,
+			       enum stm32mp1_pll_id pll_id,
+			       uint32_t *pllcfg, uint32_t fracv)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	uint32_t rcc = priv->base;
+	enum stm32mp1_plltype type = pll[pll_id].plltype;
+	unsigned long refclk;
+	uint32_t ifrge = 0;
+	uint32_t src, value;
+
+	src = mmio_read_32(priv->base + pll[pll_id].rckxselr) &
+		RCC_SELR_REFCLK_SRC_MASK;
+
+	refclk = stm32mp1_clk_get_fixed(priv, pll[pll_id].refclk[src]) /
+		 (pllcfg[PLLCFG_M] + 1U);
+
+	if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) ||
+	    (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) {
+		return -EINVAL;
+	}
+
+	if ((type == PLL_800) && (refclk >= 8000000U)) {
+		ifrge = 1U;
+	}
+
+	value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) &
+		RCC_PLLNCFGR1_DIVN_MASK;
+	value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) &
+		 RCC_PLLNCFGR1_DIVM_MASK;
+	value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) &
+		 RCC_PLLNCFGR1_IFRGE_MASK;
+	mmio_write_32(rcc + pll[pll_id].pllxcfgr1, value);
+
+	/* Fractional configuration */
+	value = 0;
+	mmio_write_32(rcc + pll[pll_id].pllxfracr, value);
+
+	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
+	mmio_write_32(rcc + pll[pll_id].pllxfracr, value);
+
+	value |= RCC_PLLNFRACR_FRACLE;
+	mmio_write_32(rcc + pll[pll_id].pllxfracr, value);
+
+	stm32mp1_pll_config_output(priv, pll_id, pllcfg);
+
+	return 0;
+}
+
+static void stm32mp1_pll_csg(struct stm32mp1_clk_priv *priv,
+			     enum stm32mp1_pll_id pll_id,
+			     uint32_t *csg)
+{
+	const struct stm32mp1_clk_pll *pll = priv->data->pll;
+	uint32_t pllxcsg = 0;
+
+	pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) &
+		    RCC_PLLNCSGR_MOD_PER_MASK;
+
+	pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) &
+		    RCC_PLLNCSGR_INC_STEP_MASK;
+
+	pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) &
+		    RCC_PLLNCSGR_SSCG_MODE_MASK;
+
+	mmio_write_32(priv->base + pll[pll_id].pllxcsgr, pllxcsg);
+}
+
+static int stm32mp1_set_clksrc(struct stm32mp1_clk_priv *priv,
+			       unsigned int clksrc)
+{
+	uint32_t address = priv->base + (clksrc >> 4);
+	unsigned long start;
+
+	mmio_clrsetbits_32(address, RCC_SELR_SRC_MASK,
+			   clksrc & RCC_SELR_SRC_MASK);
+
+	start = get_timer(0);
+	while ((mmio_read_32(address) & RCC_SELR_SRCRDY) == 0U) {
+		if (get_timer(start) > CLKSRC_TIMEOUT) {
+			ERROR("CLKSRC %x start failed @ 0x%x: 0x%x\n",
+			      clksrc, address, mmio_read_32(address));
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int stm32mp1_set_clkdiv(unsigned int clkdiv, uint32_t address)
+{
+	unsigned long start;
+
+	mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
+			   clkdiv & RCC_DIVR_DIV_MASK);
+
+	start = get_timer(0);
+	while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
+		if (get_timer(start) > CLKDIV_TIMEOUT) {
+			ERROR("CLKDIV %x start failed @ 0x%x: 0x%x\n",
+			      clkdiv, address, mmio_read_32(address));
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static void stm32mp1_mco_csg(struct stm32mp1_clk_priv *priv,
+			     uint32_t clksrc, uint32_t clkdiv)
+{
+	uint32_t address = priv->base + (clksrc >> 4);
+
+	/*
+	 * Binding clksrc :
+	 *      bit15-4 offset
+	 *      bit3:   disable
+	 *      bit2-0: MCOSEL[2:0]
+	 */
+	if ((clksrc & 0x8U) != 0U) {
+		mmio_clrbits_32(address, RCC_MCOCFG_MCOON);
+	} else {
+		mmio_clrsetbits_32(address,
+				   RCC_MCOCFG_MCOSRC_MASK,
+				   clksrc & RCC_MCOCFG_MCOSRC_MASK);
+		mmio_clrsetbits_32(address,
+				   RCC_MCOCFG_MCODIV_MASK,
+				   clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
+		mmio_setbits_32(address, RCC_MCOCFG_MCOON);
+	}
+}
+
+static void stm32mp1_set_rtcsrc(struct stm32mp1_clk_priv *priv,
+				unsigned int clksrc, bool lse_css)
+{
+	uint32_t address = priv->base + RCC_BDCR;
+
+	if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) ||
+	    (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
+		mmio_clrsetbits_32(address,
+				   RCC_BDCR_RTCSRC_MASK,
+				   clksrc << RCC_BDCR_RTCSRC_SHIFT);
+
+		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
+	}
+
+	if (lse_css) {
+		mmio_setbits_32(address, RCC_BDCR_LSECSSON);
+	}
+}
+
+#define CNTCVL_OFF	0x008
+#define CNTCVU_OFF	0x00C
+
+static void stm32mp1_stgen_config(struct stm32mp1_clk_priv *priv)
+{
+	uintptr_t stgen;
+	int p;
+	uint32_t cntfid0;
+	unsigned long rate;
+
+	stgen = fdt_get_stgen_base();
+
+	cntfid0 = mmio_read_32(stgen + CNTFID_OFF);
+	p = stm32mp1_clk_get_parent(priv, STGEN_K);
+	rate = stm32mp1_clk_get(priv, p);
+
+	if (cntfid0 != rate) {
+		unsigned long long counter;
+
+		mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
+		counter = (unsigned long long)
+			mmio_read_32(stgen + CNTCVL_OFF);
+		counter |= ((unsigned long long)
+			    (mmio_read_32(stgen + CNTCVU_OFF))) << 32;
+		counter = (counter * rate / cntfid0);
+		mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)counter);
+		mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(counter >> 32));
+		mmio_write_32(stgen + CNTFID_OFF, rate);
+		mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
+
+		write_cntfrq((u_register_t)rate);
+
+		/* Need to update timer with new frequency */
+		generic_delay_timer_init();
+	}
+}
+
+void stm32mp1_stgen_increment(unsigned long long offset_in_ms)
+{
+	uintptr_t stgen;
+	unsigned long long cnt;
+
+	stgen = fdt_get_stgen_base();
+
+	cnt = ((unsigned long long)mmio_read_32(stgen + CNTCVU_OFF) << 32) |
+		mmio_read_32(stgen + CNTCVL_OFF);
+
+	cnt += (offset_in_ms * mmio_read_32(stgen + CNTFID_OFF)) / 1000U;
+
+	mmio_clrbits_32(stgen + CNTCR_OFF, CNTCR_EN);
+	mmio_write_32(stgen + CNTCVL_OFF, (uint32_t)cnt);
+	mmio_write_32(stgen + CNTCVU_OFF, (uint32_t)(cnt >> 32));
+	mmio_setbits_32(stgen + CNTCR_OFF, CNTCR_EN);
+}
+
+static void stm32mp1_pkcs_config(struct stm32mp1_clk_priv *priv, uint32_t pkcs)
+{
+	uint32_t address = priv->base + ((pkcs >> 4) & 0xFFFU);
+	uint32_t value = pkcs & 0xFU;
+	uint32_t mask = 0xFU;
+
+	if ((pkcs & BIT(31)) != 0U) {
+		mask <<= 4;
+		value <<= 4;
+	}
+
+	mmio_clrsetbits_32(address, mask, value);
+}
+
+int stm32mp1_clk_init(void)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+	uint32_t rcc = priv->base;
+	unsigned int clksrc[CLKSRC_NB];
+	unsigned int clkdiv[CLKDIV_NB];
+	unsigned int pllcfg[_PLL_NB][PLLCFG_NB];
+	int plloff[_PLL_NB];
+	int ret, len;
+	enum stm32mp1_pll_id i;
+	bool lse_css = false;
+	const uint32_t *pkcs_cell;
+
+	/* Check status field to disable security */
+	if (!fdt_get_rcc_secure_status()) {
+		mmio_write_32(rcc + RCC_TZCR, 0);
+	}
+
+	ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc,
+					(uint32_t)CLKSRC_NB);
+	if (ret < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	ret = fdt_rcc_read_uint32_array("st,clkdiv", clkdiv,
+					(uint32_t)CLKDIV_NB);
+	if (ret < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
+		char name[12];
+
+		sprintf(name, "st,pll@%d", i);
+		plloff[i] = fdt_rcc_subnode_offset(name);
+
+		if (!fdt_check_node(plloff[i])) {
+			continue;
+		}
+
+		ret = fdt_read_uint32_array(plloff[i], "cfg",
+					    pllcfg[i], (int)PLLCFG_NB);
+		if (ret < 0) {
+			return -FDT_ERR_NOTFOUND;
+		}
+	}
+
+	stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
+	stm32mp1_mco_csg(priv, clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
+
+	/*
+	 * Switch ON oscillator found in device-tree.
+	 * Note: HSI already ON after BootROM stage.
+	 */
+	if (priv->osc[_LSI] != 0U) {
+		stm32mp1_lsi_set(rcc, 1);
+	}
+	if (priv->osc[_LSE] != 0U) {
+		bool bypass;
+		uint32_t lsedrv;
+
+		bypass = fdt_osc_read_bool(_LSE, "st,bypass");
+		lse_css = fdt_osc_read_bool(_LSE, "st,css");
+		lsedrv = fdt_osc_read_uint32_default(_LSE, "st,drive",
+						     LSEDRV_MEDIUM_HIGH);
+		stm32mp1_lse_enable(rcc, bypass, lsedrv);
+	}
+	if (priv->osc[_HSE] != 0U) {
+		bool bypass, css;
+
+		bypass = fdt_osc_read_bool(_LSE, "st,bypass");
+		css = fdt_osc_read_bool(_LSE, "st,css");
+		stm32mp1_hse_enable(rcc, bypass, css);
+	}
+	/*
+	 * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR)
+	 * => switch on CSI even if node is not present in device tree
+	 */
+	stm32mp1_csi_set(rcc, 1);
+
+	/* Come back to HSI */
+	ret = stm32mp1_set_clksrc(priv, CLK_MPU_HSI);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clksrc(priv, CLK_AXI_HSI);
+	if (ret != 0) {
+		return ret;
+	}
+
+	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
+		if (i == _PLL4)
+			continue;
+		ret = stm32mp1_pll_stop(priv, i);
+		if (ret != 0) {
+			return ret;
+		}
+	}
+
+	/* Configure HSIDIV */
+	if (priv->osc[_HSI] != 0U) {
+		ret = stm32mp1_hsidiv(rcc, priv->osc[_HSI]);
+		if (ret != 0) {
+			return ret;
+		}
+		stm32mp1_stgen_config(priv);
+	}
+
+	/* Select DIV */
+	/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
+	mmio_write_32(rcc + RCC_MPCKDIVR,
+		      clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
+	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* No ready bit for RTC */
+	mmio_write_32(rcc + RCC_RTCDIVR,
+		      clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
+
+	/* Configure PLLs source */
+	ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL12]);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL3]);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_PLL4]);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Configure and start PLLs */
+	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
+		uint32_t fracv;
+		uint32_t csg[PLLCSG_NB];
+
+		if (!fdt_check_node(plloff[i])) {
+			continue;
+		}
+
+		fracv = fdt_read_uint32_default(plloff[i], "frac", 0);
+
+		ret = stm32mp1_pll_config(priv, i, pllcfg[i], fracv);
+		if (ret != 0) {
+			return ret;
+		}
+		ret = fdt_read_uint32_array(plloff[i], "csg", csg,
+					    (uint32_t)PLLCSG_NB);
+		if (ret == 0) {
+			stm32mp1_pll_csg(priv, i, csg);
+		} else if (ret != -FDT_ERR_NOTFOUND) {
+			return ret;
+		}
+
+		stm32mp1_pll_start(priv, i);
+	}
+	/* Wait and start PLLs ouptut when ready */
+	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
+		if (!fdt_check_node(plloff[i])) {
+			continue;
+		}
+
+		ret = stm32mp1_pll_output(priv, i, pllcfg[i][PLLCFG_O]);
+		if (ret != 0) {
+			return ret;
+		}
+	}
+	/* Wait LSE ready before to use it */
+	if (priv->osc[_LSE] != 0U) {
+		stm32mp1_lse_wait(rcc);
+	}
+
+	/* Configure with expected clock source */
+	ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_MPU]);
+	if (ret != 0) {
+		return ret;
+	}
+	ret = stm32mp1_set_clksrc(priv, clksrc[CLKSRC_AXI]);
+	if (ret != 0) {
+		return ret;
+	}
+	stm32mp1_set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css);
+
+	/* Configure PKCK */
+	pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len);
+	if (pkcs_cell != NULL) {
+		bool ckper_disabled = false;
+		uint32_t j;
+
+		priv->pkcs_usb_value = 0;
+
+		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
+			uint32_t pkcs = (uint32_t)fdt32_to_cpu(pkcs_cell[j]);
+
+			if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
+				ckper_disabled = true;
+				continue;
+			}
+			stm32mp1_pkcs_config(priv, pkcs);
+		}
+
+		/*
+		 * CKPER is source for some peripheral clocks
+		 * (FMC-NAND / QPSI-NOR) and switching source is allowed
+		 * only if previous clock is still ON
+		 * => deactivated CKPER only after switching clock
+		 */
+		if (ckper_disabled) {
+			stm32mp1_pkcs_config(priv, CLK_CKPER_DISABLED);
+		}
+	}
+
+	/* Switch OFF HSI if not found in device-tree */
+	if (priv->osc[_HSI] == 0U) {
+		stm32mp1_hsi_set(rcc, 0);
+	}
+	stm32mp1_stgen_config(priv);
+
+	/* Software Self-Refresh mode (SSR) during DDR initilialization */
+	mmio_clrsetbits_32(priv->base + RCC_DDRITFCR,
+			   RCC_DDRITFCR_DDRCKMOD_MASK,
+			   RCC_DDRITFCR_DDRCKMOD_SSR <<
+			   RCC_DDRITFCR_DDRCKMOD_SHIFT);
+
+	return 0;
+}
+
+static void stm32mp1_osc_clk_init(const char *name,
+				  struct stm32mp1_clk_priv *priv,
+				  enum stm32mp_osc_id index)
+{
+	uint32_t frequency;
+
+	priv->osc[index] = 0;
+
+	if (fdt_osc_read_freq(name, &frequency) != 0) {
+		ERROR("%s frequency request failed\n", name);
+		panic();
+	} else {
+		priv->osc[index] = frequency;
+	}
+}
+
+static void stm32mp1_osc_init(void)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+	enum stm32mp_osc_id i;
+
+	for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) {
+		stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], priv, i);
+	}
+}
+
+int stm32mp1_clk_probe(void)
+{
+	struct stm32mp1_clk_priv *priv = &stm32mp1_clk_priv_data;
+
+	priv->base = fdt_rcc_read_addr();
+	if (priv->base == 0U) {
+		return -EINVAL;
+	}
+
+	priv->data = &stm32mp1_data;
+
+	if ((priv->data->gate == NULL) || (priv->data->sel == NULL) ||
+	    (priv->data->pll == NULL)) {
+		return -EINVAL;
+	}
+
+	stm32mp1_osc_init();
+
+	return 0;
+}
diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c
new file mode 100644
index 0000000..d4c69cb
--- /dev/null
+++ b/drivers/st/clk/stm32mp1_clkfunc.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include <errno.h>
+#include <libfdt.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_clkfunc.h>
+#include <stm32mp1_dt.h>
+
+#define DT_RCC_NODE_NAME	"rcc@50000000"
+#define DT_RCC_CLK_COMPAT	"st,stm32mp1-rcc"
+#define DT_RCC_COMPAT		"syscon"
+#define DT_STGEN_COMPAT		"st,stm32-stgen"
+#define DT_UART_COMPAT		"st,stm32h7-uart"
+#define DT_USART_COMPAT		"st,stm32h7-usart"
+
+const char *stm32mp_osc_node_label[NB_OSC] = {
+	[_LSI] = "clk-lsi",
+	[_LSE] = "clk-lse",
+	[_HSI] = "clk-hsi",
+	[_HSE] = "clk-hse",
+	[_CSI] = "clk-csi",
+	[_I2S_CKIN] = "i2s_ckin",
+	[_USB_PHY_48] = "ck_usbo_48m"
+};
+
+/*******************************************************************************
+ * This function reads the frequency of an oscillator from its name.
+ * It reads the value indicated inside the device tree.
+ * Returns 0 if success, and a negative value else.
+ * If success, value is stored in the second parameter.
+ ******************************************************************************/
+int fdt_osc_read_freq(const char *name, uint32_t *freq)
+{
+	int node, subnode;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	node = fdt_path_offset(fdt, "/clocks");
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		const char *cchar;
+		int ret;
+
+		cchar = fdt_get_name(fdt, subnode, &ret);
+		if (cchar == NULL) {
+			return ret;
+		}
+
+		if (strncmp(cchar, name, (size_t)ret) == 0) {
+			const fdt32_t *cuint;
+
+			cuint = fdt_getprop(fdt, subnode, "clock-frequency",
+					    &ret);
+			if (cuint == NULL) {
+				return ret;
+			}
+
+			*freq = fdt32_to_cpu(*cuint);
+
+			return 0;
+		}
+	}
+
+	/* Oscillator not found, freq=0 */
+	*freq = 0;
+	return 0;
+}
+
+/*******************************************************************************
+ * This function checks the presence of an oscillator property from its id.
+ * The search is done inside the device tree.
+ * Returns true/false regarding search result.
+ ******************************************************************************/
+bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name)
+{
+	int node, subnode;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return false;
+	}
+
+	if (osc_id >= NB_OSC) {
+		return false;
+	}
+
+	node = fdt_path_offset(fdt, "/clocks");
+	if (node < 0) {
+		return false;
+	}
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		const char *cchar;
+		int ret;
+
+		cchar = fdt_get_name(fdt, subnode, &ret);
+		if (cchar == NULL) {
+			return false;
+		}
+
+		if (strncmp(cchar, stm32mp_osc_node_label[osc_id],
+			    (size_t)ret) != 0) {
+			continue;
+		}
+
+		if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/*******************************************************************************
+ * This function reads a value of a oscillator property from its id.
+ * Returns value if success, and a default value if property not found.
+ * Default value is passed as parameter.
+ ******************************************************************************/
+uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
+				     const char *prop_name, uint32_t dflt_value)
+{
+	int node, subnode;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return dflt_value;
+	}
+
+	if (osc_id >= NB_OSC) {
+		return dflt_value;
+	}
+
+	node = fdt_path_offset(fdt, "/clocks");
+	if (node < 0) {
+		return dflt_value;
+	}
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		const char *cchar;
+		int ret;
+
+		cchar = fdt_get_name(fdt, subnode, &ret);
+		if (cchar == NULL) {
+			return dflt_value;
+		}
+
+		if (strncmp(cchar, stm32mp_osc_node_label[osc_id],
+			    (size_t)ret) != 0) {
+			continue;
+		}
+
+		return fdt_read_uint32_default(subnode, prop_name, dflt_value);
+	}
+
+	return dflt_value;
+}
+
+/*******************************************************************************
+ * This function reads the rcc base address.
+ * It reads the value indicated inside the device tree.
+ * Returns address if success, and 0 value else.
+ ******************************************************************************/
+uint32_t fdt_rcc_read_addr(void)
+{
+	int node, subnode;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, "/soc");
+	if (node < 0) {
+		return 0;
+	}
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		const char *cchar;
+		int ret;
+
+		cchar = fdt_get_name(fdt, subnode, &ret);
+		if (cchar == NULL) {
+			return 0;
+		}
+
+		if (strncmp(cchar, DT_RCC_NODE_NAME, (size_t)ret) == 0) {
+			const fdt32_t *cuint;
+
+			cuint = fdt_getprop(fdt, subnode, "reg", NULL);
+			if (cuint == NULL) {
+				return 0;
+			}
+
+			return fdt32_to_cpu(*cuint);
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * This function reads a series of parameters in rcc-clk section.
+ * It reads the values indicated inside the device tree, from property name.
+ * The number of parameters is also indicated as entry parameter.
+ * Returns 0 if success, and a negative value else.
+ * If success, values are stored at the second parameter address.
+ ******************************************************************************/
+int fdt_rcc_read_uint32_array(const char *prop_name,
+			      uint32_t *array, uint32_t count)
+{
+	int node;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	return fdt_read_uint32_array(node, prop_name, array, count);
+}
+
+/*******************************************************************************
+ * This function gets the subnode offset in rcc-clk section from its name.
+ * It reads the values indicated inside the device tree.
+ * Returns offset if success, and a negative value else.
+ ******************************************************************************/
+int fdt_rcc_subnode_offset(const char *name)
+{
+	int node, subnode;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+	if (node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	subnode = fdt_subnode_offset(fdt, node, name);
+	if (subnode <= 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	return subnode;
+}
+
+/*******************************************************************************
+ * This function gets the pointer to a rcc-clk property from its name.
+ * It reads the values indicated inside the device tree.
+ * Length of the property is stored in the second parameter.
+ * Returns pointer if success, and NULL value else.
+ ******************************************************************************/
+const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp)
+{
+	const uint32_t *cuint;
+	int node, len;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return NULL;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+	if (node < 0) {
+		return NULL;
+	}
+
+	cuint = fdt_getprop(fdt, node, prop_name, &len);
+	if (cuint == NULL) {
+		return NULL;
+	}
+
+	*lenp = len;
+	return cuint;
+}
+
+/*******************************************************************************
+ * This function gets the secure status for rcc node.
+ * It reads secure-status in device tree.
+ * Returns 1 if rcc is available from secure world, 0 else.
+ ******************************************************************************/
+bool fdt_get_rcc_secure_status(void)
+{
+	int node;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return false;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT);
+	if (node < 0) {
+		return false;
+	}
+
+	return fdt_check_secure_status(node);
+}
+
+/*******************************************************************************
+ * This function reads the stgen base address.
+ * It reads the value indicated inside the device tree.
+ * Returns address if success, and NULL value else.
+ ******************************************************************************/
+uintptr_t fdt_get_stgen_base(void)
+{
+	int node;
+	const fdt32_t *cuint;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return 0;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_STGEN_COMPAT);
+	if (node < 0) {
+		return 0;
+	}
+
+	cuint = fdt_getprop(fdt, node, "reg", NULL);
+	if (cuint == NULL) {
+		return 0;
+	}
+
+	return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function gets the clock ID of the given node.
+ * It reads the value indicated inside the device tree.
+ * Returns ID if success, and a negative value else.
+ ******************************************************************************/
+int fdt_get_clock_id(int node)
+{
+	const fdt32_t *cuint;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	cuint = fdt_getprop(fdt, node, "clocks", NULL);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	cuint++;
+	return (int)fdt32_to_cpu(*cuint);
+}
diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
new file mode 100644
index 0000000..106bbfe
--- /dev/null
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl_common.h>
+#include <debug.h>
+#include <limits.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stm32mp1_rcc.h>
+#include <stm32mp1_reset.h>
+#include <utils_def.h>
+
+#define RST_CLR_OFFSET	4U
+
+void stm32mp1_reset_assert(uint32_t id)
+{
+	uint32_t offset = (id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t);
+	uint32_t bit = id % (uint32_t)__LONG_BIT;
+
+	mmio_write_32(RCC_BASE + offset, BIT(bit));
+	while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) == 0U) {
+		;
+	}
+}
+
+void stm32mp1_reset_deassert(uint32_t id)
+{
+	uint32_t offset = ((id / (uint32_t)__LONG_BIT) * sizeof(uintptr_t)) +
+			  RST_CLR_OFFSET;
+	uint32_t bit = id % (uint32_t)__LONG_BIT;
+
+	mmio_write_32(RCC_BASE + offset, BIT(bit));
+	while ((mmio_read_32(RCC_BASE + offset) & BIT(bit)) != 0U) {
+		;
+	}
+}
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
new file mode 100644
index 0000000..85a1eb8
--- /dev/null
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_CLK_H__
+#define __STM32MP1_CLK_H__
+
+#include <arch_helpers.h>
+#include <stdbool.h>
+
+int stm32mp1_clk_probe(void);
+int stm32mp1_clk_init(void);
+bool stm32mp1_clk_is_enabled(unsigned long id);
+int stm32mp1_clk_enable(unsigned long id);
+int stm32mp1_clk_disable(unsigned long id);
+unsigned long stm32mp1_clk_get_rate(unsigned long id);
+void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
+
+static inline uint32_t get_timer(uint32_t base)
+{
+	if (base == 0U) {
+		return (uint32_t)(~read_cntpct_el0());
+	}
+
+	return base - (uint32_t)(~read_cntpct_el0());
+}
+
+#endif /* __STM32MP1_CLK_H__ */
diff --git a/include/drivers/st/stm32mp1_clkfunc.h b/include/drivers/st/stm32mp1_clkfunc.h
new file mode 100644
index 0000000..635a9cd
--- /dev/null
+++ b/include/drivers/st/stm32mp1_clkfunc.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_CLKFUNC_H__
+#define __STM32MP1_CLKFUNC_H__
+
+#include <stdbool.h>
+
+enum stm32mp_osc_id {
+	_HSI,
+	_HSE,
+	_CSI,
+	_LSI,
+	_LSE,
+	_I2S_CKIN,
+	_USB_PHY_48,
+	NB_OSC,
+	_UNKNOWN_OSC_ID = 0xFF
+};
+
+extern const char *stm32mp_osc_node_label[NB_OSC];
+
+int fdt_osc_read_freq(const char *name, uint32_t *freq);
+bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name);
+uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
+				     const char *prop_name,
+				     uint32_t dflt_value);
+
+uint32_t fdt_rcc_read_addr(void);
+int fdt_rcc_read_uint32_array(const char *prop_name,
+			      uint32_t *array, uint32_t count);
+int fdt_rcc_subnode_offset(const char *name);
+const uint32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp);
+bool fdt_get_rcc_secure_status(void);
+
+uintptr_t fdt_get_stgen_base(void);
+int fdt_get_clock_id(int node);
+
+#endif /* __STM32MP1_CLKFUNC_H__ */
diff --git a/include/drivers/st/stm32mp1_reset.h b/include/drivers/st/stm32mp1_reset.h
new file mode 100644
index 0000000..76ee09d
--- /dev/null
+++ b/include/drivers/st/stm32mp1_reset.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_RESET_H__
+#define __STM32MP1_RESET_H__
+
+#include <stdint.h>
+
+void stm32mp1_reset_assert(uint32_t reset_id);
+void stm32mp1_reset_deassert(uint32_t reset_id);
+
+#endif /* __STM32MP1_RESET_H__ */
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
new file mode 100644
index 0000000..18bdb57
--- /dev/null
+++ b/include/dt-bindings/clock/stm32mp1-clks.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com> for STMicroelectronics.
+ */
+
+#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_
+#define _DT_BINDINGS_STM32MP1_CLKS_H_
+
+/* OSCILLATOR clocks */
+#define CK_HSE		0
+#define CK_CSI		1
+#define CK_LSI		2
+#define CK_LSE		3
+#define CK_HSI		4
+#define CK_HSE_DIV2	5
+
+/* Bus clocks */
+#define TIM2		6
+#define TIM3		7
+#define TIM4		8
+#define TIM5		9
+#define TIM6		10
+#define TIM7		11
+#define TIM12		12
+#define TIM13		13
+#define TIM14		14
+#define LPTIM1		15
+#define SPI2		16
+#define SPI3		17
+#define USART2		18
+#define USART3		19
+#define UART4		20
+#define UART5		21
+#define UART7		22
+#define UART8		23
+#define I2C1		24
+#define I2C2		25
+#define I2C3		26
+#define I2C5		27
+#define SPDIF		28
+#define CEC		29
+#define DAC12		30
+#define MDIO		31
+#define TIM1		32
+#define TIM8		33
+#define TIM15		34
+#define TIM16		35
+#define TIM17		36
+#define SPI1		37
+#define SPI4		38
+#define SPI5		39
+#define USART6		40
+#define SAI1		41
+#define SAI2		42
+#define SAI3		43
+#define DFSDM		44
+#define FDCAN		45
+#define LPTIM2		46
+#define LPTIM3		47
+#define LPTIM4		48
+#define LPTIM5		49
+#define SAI4		50
+#define SYSCFG		51
+#define VREF		52
+#define TMPSENS		53
+#define PMBCTRL		54
+#define HDP		55
+#define LTDC		56
+#define DSI		57
+#define IWDG2		58
+#define USBPHY		59
+#define STGENRO		60
+#define SPI6		61
+#define I2C4		62
+#define I2C6		63
+#define USART1		64
+#define RTCAPB		65
+#define TZC1		66
+#define TZPC		67
+#define IWDG1		68
+#define BSEC		69
+#define STGEN		70
+#define DMA1		71
+#define DMA2		72
+#define DMAMUX		73
+#define ADC12		74
+#define USBO		75
+#define SDMMC3		76
+#define DCMI		77
+#define CRYP2		78
+#define HASH2		79
+#define RNG2		80
+#define CRC2		81
+#define HSEM		82
+#define IPCC		83
+#define GPIOA		84
+#define GPIOB		85
+#define GPIOC		86
+#define GPIOD		87
+#define GPIOE		88
+#define GPIOF		89
+#define GPIOG		90
+#define GPIOH		91
+#define GPIOI		92
+#define GPIOJ		93
+#define GPIOK		94
+#define GPIOZ		95
+#define CRYP1		96
+#define HASH1		97
+#define RNG1		98
+#define BKPSRAM		99
+#define MDMA		100
+#define GPU		101
+#define ETHCK		102
+#define ETHTX		103
+#define ETHRX		104
+#define ETHMAC		105
+#define FMC		106
+#define QSPI		107
+#define SDMMC1		108
+#define SDMMC2		109
+#define CRC1		110
+#define USBH		111
+#define ETHSTP		112
+#define TZC2		113
+
+/* Kernel clocks */
+#define SDMMC1_K	118
+#define SDMMC2_K	119
+#define SDMMC3_K	120
+#define FMC_K		121
+#define QSPI_K		122
+#define ETHCK_K		123
+#define RNG1_K		124
+#define RNG2_K		125
+#define GPU_K		126
+#define USBPHY_K	127
+#define STGEN_K		128
+#define SPDIF_K		129
+#define SPI1_K		130
+#define SPI2_K		131
+#define SPI3_K		132
+#define SPI4_K		133
+#define SPI5_K		134
+#define SPI6_K		135
+#define CEC_K		136
+#define I2C1_K		137
+#define I2C2_K		138
+#define I2C3_K		139
+#define I2C4_K		140
+#define I2C5_K		141
+#define I2C6_K		142
+#define LPTIM1_K	143
+#define LPTIM2_K	144
+#define LPTIM3_K	145
+#define LPTIM4_K	146
+#define LPTIM5_K	147
+#define USART1_K	148
+#define USART2_K	149
+#define USART3_K	150
+#define UART4_K		151
+#define UART5_K		152
+#define USART6_K	153
+#define UART7_K		154
+#define UART8_K		155
+#define DFSDM_K		156
+#define FDCAN_K		157
+#define SAI1_K		158
+#define SAI2_K		159
+#define SAI3_K		160
+#define SAI4_K		161
+#define ADC12_K		162
+#define DSI_K		163
+#define DSI_PX		164
+#define ADFSDM_K	165
+#define USBO_K		166
+#define LTDC_PX		167
+#define DAC12_K		168
+#define ETHPTP_K	169
+
+/* PLL */
+#define PLL1		176
+#define PLL2		177
+#define PLL3		178
+#define PLL4		179
+
+/* ODF */
+#define PLL1_P		180
+#define PLL1_Q		181
+#define PLL1_R		182
+#define PLL2_P		183
+#define PLL2_Q		184
+#define PLL2_R		185
+#define PLL3_P		186
+#define PLL3_Q		187
+#define PLL3_R		188
+#define PLL4_P		189
+#define PLL4_Q		190
+#define PLL4_R		191
+
+/* AUX */
+#define RTC		192
+
+/* MCLK */
+#define CK_PER		193
+#define CK_MPU		194
+#define CK_AXI		195
+#define CK_MCU		196
+
+/* Time base */
+#define TIM2_K		197
+#define TIM3_K		198
+#define TIM4_K		199
+#define TIM5_K		200
+#define TIM6_K		201
+#define TIM7_K		202
+#define TIM12_K		203
+#define TIM13_K		204
+#define TIM14_K		205
+#define TIM1_K		206
+#define TIM8_K		207
+#define TIM15_K		208
+#define TIM16_K		209
+#define TIM17_K		210
+
+/* MCO clocks */
+#define CK_MCO1		211
+#define CK_MCO2		212
+
+/* TRACE & DEBUG clocks */
+#define CK_DBG		214
+#define CK_TRACE	215
+
+/* DDR */
+#define DDRC1		220
+#define DDRC1LP		221
+#define DDRC2		222
+#define DDRC2LP		223
+#define DDRPHYC		224
+#define DDRPHYCLP	225
+#define DDRCAPB		226
+#define DDRCAPBLP	227
+#define AXIDCG		228
+#define DDRPHYCAPB	229
+#define DDRPHYCAPBLP	230
+#define DDRPERFM	231
+
+#define STM32MP1_LAST_CLK 232
+
+#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
diff --git a/include/dt-bindings/clock/stm32mp1-clksrc.h b/include/dt-bindings/clock/stm32mp1-clksrc.h
new file mode 100644
index 0000000..818f4b7
--- /dev/null
+++ b/include/dt-bindings/clock/stm32mp1-clksrc.h
@@ -0,0 +1,283 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_STM32MP1_CLKSRC_H_
+#define _DT_BINDINGS_CLOCK_STM32MP1_CLKSRC_H_
+
+/* PLL output is enable when x=1, with x=p,q or r */
+#define PQR(p, q, r)	(((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2))
+
+/* st,clksrc: mandatory clock source */
+
+#define CLK_MPU_HSI		0x00000200
+#define CLK_MPU_HSE		0x00000201
+#define CLK_MPU_PLL1P		0x00000202
+#define CLK_MPU_PLL1P_DIV	0x00000203
+
+#define CLK_AXI_HSI		0x00000240
+#define CLK_AXI_HSE		0x00000241
+#define CLK_AXI_PLL2P		0x00000242
+
+#define CLK_MCU_HSI		0x00000480
+#define CLK_MCU_HSE		0x00000481
+#define CLK_MCU_CSI		0x00000482
+#define CLK_MCU_PLL3P		0x00000483
+
+#define CLK_PLL12_HSI		0x00000280
+#define CLK_PLL12_HSE		0x00000281
+
+#define CLK_PLL3_HSI		0x00008200
+#define CLK_PLL3_HSE		0x00008201
+#define CLK_PLL3_CSI		0x00008202
+
+#define CLK_PLL4_HSI		0x00008240
+#define CLK_PLL4_HSE		0x00008241
+#define CLK_PLL4_CSI		0x00008242
+#define CLK_PLL4_I2SCKIN	0x00008243
+
+#define CLK_RTC_DISABLED	0x00001400
+#define CLK_RTC_LSE		0x00001401
+#define CLK_RTC_LSI		0x00001402
+#define CLK_RTC_HSE		0x00001403
+
+#define CLK_MCO1_HSI		0x00008000
+#define CLK_MCO1_HSE		0x00008001
+#define CLK_MCO1_CSI		0x00008002
+#define CLK_MCO1_LSI		0x00008003
+#define CLK_MCO1_LSE		0x00008004
+#define CLK_MCO1_DISABLED	0x0000800F
+
+#define CLK_MCO2_MPU		0x00008040
+#define CLK_MCO2_AXI		0x00008041
+#define CLK_MCO2_MCU		0x00008042
+#define CLK_MCO2_PLL4P		0x00008043
+#define CLK_MCO2_HSE		0x00008044
+#define CLK_MCO2_HSI		0x00008045
+#define CLK_MCO2_DISABLED	0x0000804F
+
+/* st,pkcs: peripheral kernel clock source */
+
+#define CLK_I2C12_PCLK1		0x00008C00
+#define CLK_I2C12_PLL4R		0x00008C01
+#define CLK_I2C12_HSI		0x00008C02
+#define CLK_I2C12_CSI		0x00008C03
+#define CLK_I2C12_DISABLED	0x00008C07
+
+#define CLK_I2C35_PCLK1		0x00008C40
+#define CLK_I2C35_PLL4R		0x00008C41
+#define CLK_I2C35_HSI		0x00008C42
+#define CLK_I2C35_CSI		0x00008C43
+#define CLK_I2C35_DISABLED	0x00008C47
+
+#define CLK_I2C46_PCLK5		0x00000C00
+#define CLK_I2C46_PLL3Q		0x00000C01
+#define CLK_I2C46_HSI		0x00000C02
+#define CLK_I2C46_CSI		0x00000C03
+#define CLK_I2C46_DISABLED	0x00000C07
+
+#define CLK_SAI1_PLL4Q		0x00008C80
+#define CLK_SAI1_PLL3Q		0x00008C81
+#define CLK_SAI1_I2SCKIN	0x00008C82
+#define CLK_SAI1_CKPER		0x00008C83
+#define CLK_SAI1_PLL3R		0x00008C84
+#define CLK_SAI1_DISABLED	0x00008C87
+
+#define CLK_SAI2_PLL4Q		0x00008CC0
+#define CLK_SAI2_PLL3Q		0x00008CC1
+#define CLK_SAI2_I2SCKIN	0x00008CC2
+#define CLK_SAI2_CKPER		0x00008CC3
+#define CLK_SAI2_SPDIF		0x00008CC4
+#define CLK_SAI2_PLL3R		0x00008CC5
+#define CLK_SAI2_DISABLED	0x00008CC7
+
+#define CLK_SAI3_PLL4Q		0x00008D00
+#define CLK_SAI3_PLL3Q		0x00008D01
+#define CLK_SAI3_I2SCKIN	0x00008D02
+#define CLK_SAI3_CKPER		0x00008D03
+#define CLK_SAI3_PLL3R		0x00008D04
+#define CLK_SAI3_DISABLED	0x00008D07
+
+#define CLK_SAI4_PLL4Q		0x00008D40
+#define CLK_SAI4_PLL3Q		0x00008D41
+#define CLK_SAI4_I2SCKIN	0x00008D42
+#define CLK_SAI4_CKPER		0x00008D43
+#define CLK_SAI4_PLL3R		0x00008D44
+#define CLK_SAI4_DISABLED	0x00008D47
+
+#define CLK_SPI2S1_PLL4P	0x00008D80
+#define CLK_SPI2S1_PLL3Q	0x00008D81
+#define CLK_SPI2S1_I2SCKIN	0x00008D82
+#define CLK_SPI2S1_CKPER	0x00008D83
+#define CLK_SPI2S1_PLL3R	0x00008D84
+#define CLK_SPI2S1_DISABLED	0x00008D87
+
+#define CLK_SPI2S23_PLL4P	0x00008DC0
+#define CLK_SPI2S23_PLL3Q	0x00008DC1
+#define CLK_SPI2S23_I2SCKIN	0x00008DC2
+#define CLK_SPI2S23_CKPER	0x00008DC3
+#define CLK_SPI2S23_PLL3R	0x00008DC4
+#define CLK_SPI2S23_DISABLED	0x00008DC7
+
+#define CLK_SPI45_PCLK2		0x00008E00
+#define CLK_SPI45_PLL4Q		0x00008E01
+#define CLK_SPI45_HSI		0x00008E02
+#define CLK_SPI45_CSI		0x00008E03
+#define CLK_SPI45_HSE		0x00008E04
+#define CLK_SPI45_DISABLED	0x00008E07
+
+#define CLK_SPI6_PCLK5		0x00000C40
+#define CLK_SPI6_PLL4Q		0x00000C41
+#define CLK_SPI6_HSI		0x00000C42
+#define CLK_SPI6_CSI		0x00000C43
+#define CLK_SPI6_HSE		0x00000C44
+#define CLK_SPI6_PLL3Q		0x00000C45
+#define CLK_SPI6_DISABLED	0x00000C47
+
+#define CLK_UART6_PCLK2		0x00008E40
+#define CLK_UART6_PLL4Q		0x00008E41
+#define CLK_UART6_HSI		0x00008E42
+#define CLK_UART6_CSI		0x00008E43
+#define CLK_UART6_HSE		0x00008E44
+#define CLK_UART6_DISABLED	0x00008E47
+
+#define CLK_UART24_PCLK1	0x00008E80
+#define CLK_UART24_PLL4Q	0x00008E81
+#define CLK_UART24_HSI		0x00008E82
+#define CLK_UART24_CSI		0x00008E83
+#define CLK_UART24_HSE		0x00008E84
+#define CLK_UART24_DISABLED	0x00008E87
+
+#define CLK_UART35_PCLK1	0x00008EC0
+#define CLK_UART35_PLL4Q	0x00008EC1
+#define CLK_UART35_HSI		0x00008EC2
+#define CLK_UART35_CSI		0x00008EC3
+#define CLK_UART35_HSE		0x00008EC4
+#define CLK_UART35_DISABLED	0x00008EC7
+
+#define CLK_UART78_PCLK1	0x00008F00
+#define CLK_UART78_PLL4Q	0x00008F01
+#define CLK_UART78_HSI		0x00008F02
+#define CLK_UART78_CSI		0x00008F03
+#define CLK_UART78_HSE		0x00008F04
+#define CLK_UART78_DISABLED	0x00008F07
+
+#define CLK_UART1_PCLK5		0x00000C80
+#define CLK_UART1_PLL3Q		0x00000C81
+#define CLK_UART1_HSI		0x00000C82
+#define CLK_UART1_CSI		0x00000C83
+#define CLK_UART1_PLL4Q		0x00000C84
+#define CLK_UART1_HSE		0x00000C85
+#define CLK_UART1_DISABLED	0x00000C87
+
+#define CLK_SDMMC12_HCLK6	0x00008F40
+#define CLK_SDMMC12_PLL3R	0x00008F41
+#define CLK_SDMMC12_PLL4P	0x00008F42
+#define CLK_SDMMC12_HSI		0x00008F43
+#define CLK_SDMMC12_DISABLED	0x00008F47
+
+#define CLK_SDMMC3_HCLK2	0x00008F80
+#define CLK_SDMMC3_PLL3R	0x00008F81
+#define CLK_SDMMC3_PLL4P	0x00008F82
+#define CLK_SDMMC3_HSI		0x00008F83
+#define CLK_SDMMC3_DISABLED	0x00008F87
+
+#define CLK_ETH_PLL4P		0x00008FC0
+#define CLK_ETH_PLL3Q		0x00008FC1
+#define CLK_ETH_DISABLED	0x00008FC3
+
+#define CLK_QSPI_ACLK		0x00009000
+#define CLK_QSPI_PLL3R		0x00009001
+#define CLK_QSPI_PLL4P		0x00009002
+#define CLK_QSPI_CKPER		0x00009003
+
+#define CLK_FMC_ACLK		0x00009040
+#define CLK_FMC_PLL3R		0x00009041
+#define CLK_FMC_PLL4P		0x00009042
+#define CLK_FMC_CKPER		0x00009043
+
+#define CLK_FDCAN_HSE		0x000090C0
+#define CLK_FDCAN_PLL3Q		0x000090C1
+#define CLK_FDCAN_PLL4Q		0x000090C2
+#define CLK_FDCAN_PLL4R		0x000090C3
+
+#define CLK_SPDIF_PLL4P		0x00009140
+#define CLK_SPDIF_PLL3Q		0x00009141
+#define CLK_SPDIF_HSI		0x00009142
+#define CLK_SPDIF_DISABLED	0x00009143
+
+#define CLK_CEC_LSE		0x00009180
+#define CLK_CEC_LSI		0x00009181
+#define CLK_CEC_CSI_DIV122	0x00009182
+#define CLK_CEC_DISABLED	0x00009183
+
+#define CLK_USBPHY_HSE		0x000091C0
+#define CLK_USBPHY_PLL4R	0x000091C1
+#define CLK_USBPHY_HSE_DIV2	0x000091C2
+#define CLK_USBPHY_DISABLED	0x000091C3
+
+#define CLK_USBO_PLL4R		0x800091C0
+#define CLK_USBO_USBPHY		0x800091C1
+
+#define CLK_RNG1_CSI		0x00000CC0
+#define CLK_RNG1_PLL4R		0x00000CC1
+#define CLK_RNG1_LSE		0x00000CC2
+#define CLK_RNG1_LSI		0x00000CC3
+
+#define CLK_RNG2_CSI		0x00009200
+#define CLK_RNG2_PLL4R		0x00009201
+#define CLK_RNG2_LSE		0x00009202
+#define CLK_RNG2_LSI		0x00009203
+
+#define CLK_CKPER_HSI		0x00000D00
+#define CLK_CKPER_CSI		0x00000D01
+#define CLK_CKPER_HSE		0x00000D02
+#define CLK_CKPER_DISABLED	0x00000D03
+
+#define CLK_STGEN_HSI		0x00000D40
+#define CLK_STGEN_HSE		0x00000D41
+#define CLK_STGEN_DISABLED	0x00000D43
+
+#define CLK_DSI_DSIPLL		0x00009240
+#define CLK_DSI_PLL4P		0x00009241
+
+#define CLK_ADC_PLL4R		0x00009280
+#define CLK_ADC_CKPER		0x00009281
+#define CLK_ADC_PLL3Q		0x00009282
+#define CLK_ADC_DISABLED	0x00009283
+
+#define CLK_LPTIM45_PCLK3	0x000092C0
+#define CLK_LPTIM45_PLL4P	0x000092C1
+#define CLK_LPTIM45_PLL3Q	0x000092C2
+#define CLK_LPTIM45_LSE		0x000092C3
+#define CLK_LPTIM45_LSI		0x000092C4
+#define CLK_LPTIM45_CKPER	0x000092C5
+#define CLK_LPTIM45_DISABLED	0x000092C7
+
+#define CLK_LPTIM23_PCLK3	0x00009300
+#define CLK_LPTIM23_PLL4Q	0x00009301
+#define CLK_LPTIM23_CKPER	0x00009302
+#define CLK_LPTIM23_LSE		0x00009303
+#define CLK_LPTIM23_LSI		0x00009304
+#define CLK_LPTIM23_DISABLED	0x00009307
+
+#define CLK_LPTIM1_PCLK1	0x00009340
+#define CLK_LPTIM1_PLL4P	0x00009341
+#define CLK_LPTIM1_PLL3Q	0x00009342
+#define CLK_LPTIM1_LSE		0x00009343
+#define CLK_LPTIM1_LSI		0x00009344
+#define CLK_LPTIM1_CKPER	0x00009345
+#define CLK_LPTIM1_DISABLED	0x00009347
+
+/* define for st,pll /csg */
+#define SSCG_MODE_CENTER_SPREAD	0
+#define SSCG_MODE_DOWN_SPREAD	1
+
+/* define for st,drive */
+#define LSEDRV_LOWEST		0
+#define LSEDRV_MEDIUM_LOW	1
+#define LSEDRV_MEDIUM_HIGH	2
+#define LSEDRV_HIGHEST		3
+
+#endif
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index d386202..6128c5e 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -16,6 +16,8 @@
 #include <mmio.h>
 #include <platform.h>
 #include <platform_def.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
 #include <stm32mp1_private.h>
 #include <stm32mp1_pwr.h>
 #include <stm32mp1_rcc.h>
@@ -76,5 +78,17 @@
 
 	generic_delay_timer_init();
 
+	if (dt_open_and_check() < 0) {
+		panic();
+	}
+
+	if (stm32mp1_clk_probe() < 0) {
+		panic();
+	}
+
+	if (stm32mp1_clk_init() < 0) {
+		panic();
+	}
+
 	stm32mp1_io_setup();
 }
diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h
new file mode 100644
index 0000000..da203a7
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_dt.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __STM32MP1_DT_H__
+#define __STM32MP1_DT_H__
+
+#include <stdbool.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+int dt_open_and_check(void);
+int fdt_get_address(void **fdt_addr);
+bool fdt_check_node(int node);
+bool fdt_check_status(int node);
+bool fdt_check_secure_status(int node);
+uint32_t fdt_read_uint32_default(int node, const char *prop_name,
+				 uint32_t dflt_value);
+int fdt_read_uint32_array(int node, const char *prop_name,
+			  uint32_t *array, uint32_t count);
+
+#endif /* __STM32MP1_DT_H__ */
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index ff390d5..e26504f 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -39,6 +39,10 @@
 PLAT_BL_COMMON_SOURCES	+=	${LIBFDT_SRCS}						\
 				drivers/delay_timer/delay_timer.c			\
 				drivers/delay_timer/generic_delay_timer.c		\
+				drivers/st/clk/stm32mp1_clk.c				\
+				drivers/st/clk/stm32mp1_clkfunc.c			\
+				drivers/st/reset/stm32mp1_reset.c			\
+				plat/st/stm32mp1/stm32mp1_dt.c				\
 				plat/st/stm32mp1/stm32mp1_helper.S
 
 BL2_SOURCES		+=	drivers/io/io_dummy.c					\
diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c
new file mode 100644
index 0000000..6098759
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_dt.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <libfdt.h>
+#include <platform_def.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_clkfunc.h>
+#include <stm32mp1_dt.h>
+
+#define DT_GPIO_BANK_SHIFT	12
+#define DT_GPIO_BANK_MASK	0x1F000U
+#define DT_GPIO_PIN_SHIFT	8
+#define DT_GPIO_PIN_MASK	0xF00U
+#define DT_GPIO_MODE_MASK	0xFFU
+
+static int fdt_checked;
+
+static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE;
+
+/*******************************************************************************
+ * This function checks device tree file with its header.
+ * Returns 0 if success, and a negative value else.
+ ******************************************************************************/
+int dt_open_and_check(void)
+{
+	int ret = fdt_check_header(fdt);
+
+	if (ret == 0) {
+		fdt_checked = 1;
+	}
+
+	return ret;
+}
+
+/*******************************************************************************
+ * This function gets the address of the DT.
+ * If DT is OK, fdt_addr is filled with DT address.
+ * Returns 1 if success, 0 otherwise.
+ ******************************************************************************/
+int fdt_get_address(void **fdt_addr)
+{
+	if (fdt_checked == 1) {
+		*fdt_addr = fdt;
+	}
+
+	return fdt_checked;
+}
+
+/*******************************************************************************
+ * This function check the presence of a node (generic use of fdt library).
+ * Returns true if present, false else.
+ ******************************************************************************/
+bool fdt_check_node(int node)
+{
+	int len;
+	const char *cchar;
+
+	cchar = fdt_get_name(fdt, node, &len);
+
+	return (cchar != NULL) && (len >= 0);
+}
+
+/*******************************************************************************
+ * This function check the status of a node (generic use of fdt library).
+ * Returns true if "okay" or missing, false else.
+ ******************************************************************************/
+bool fdt_check_status(int node)
+{
+	int len;
+	const char *cchar;
+
+	cchar = fdt_getprop(fdt, node, "status", &len);
+	if (cchar == NULL) {
+		return true;
+	}
+
+	return strncmp(cchar, "okay", (size_t)len) == 0;
+}
+
+/*******************************************************************************
+ * This function check the secure-status of a node (generic use of fdt library).
+ * Returns true if "okay" or missing, false else.
+ ******************************************************************************/
+bool fdt_check_secure_status(int node)
+{
+	int len;
+	const char *cchar;
+
+	cchar = fdt_getprop(fdt, node, "secure-status", &len);
+	if (cchar == NULL) {
+		return true;
+	}
+
+	return strncmp(cchar, "okay", (size_t)len) == 0;
+}
+
+/*******************************************************************************
+ * This function reads a value of a node property (generic use of fdt
+ * library).
+ * Returns value if success, and a default value if property not found.
+ * Default value is passed as parameter.
+ ******************************************************************************/
+uint32_t fdt_read_uint32_default(int node, const char *prop_name,
+				 uint32_t dflt_value)
+{
+	const fdt32_t *cuint;
+	int lenp;
+
+	cuint = fdt_getprop(fdt, node, prop_name, &lenp);
+	if (cuint == NULL) {
+		return dflt_value;
+	}
+
+	return fdt32_to_cpu(*cuint);
+}
+
+/*******************************************************************************
+ * This function reads a series of parameters in a node property
+ * (generic use of fdt library).
+ * It reads the values inside the device tree, from property name and node.
+ * The number of parameters is also indicated as entry parameter.
+ * Returns 0 if success, and a negative value else.
+ * If success, values are stored at the third parameter address.
+ ******************************************************************************/
+int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
+			  uint32_t count)
+{
+	const fdt32_t *cuint;
+	int len;
+	uint32_t i;
+
+	cuint = fdt_getprop(fdt, node, prop_name, &len);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if ((uint32_t)len != (count * sizeof(uint32_t))) {
+		return -FDT_ERR_BADLAYOUT;
+	}
+
+	for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
+		*array = fdt32_to_cpu(*cuint);
+		array++;
+		cuint++;
+	}
+
+	return 0;
+}