feat(st-clock): update with new bindings

Code alignment with MP13 driver.

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@foss.st.com>
Change-Id: Ifb0597721a865f463cf41c5cd7be3ca75a1da80c
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 73e6a2b..705728f 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -27,6 +27,70 @@
 
 #include <platform_def.h>
 
+enum stm32mp1_pllcfg {
+	PLLCFG_M,
+	PLLCFG_N,
+	PLL_DIV_MN_NB,
+	PLLCFG_P = PLL_DIV_MN_NB,
+	PLLCFG_Q,
+	PLLCFG_R,
+	PLLCFG_O,
+	PLLCFG_NB
+};
+
+#define PLL_DIV_MN_NB	2
+#define PLL_DIV_PQR_NB	3
+
+enum stm32mp1_pllcsg {
+	PLLCSG_MOD_PER,
+	PLLCSG_INC_STEP,
+	PLLCSG_SSCG_MODE,
+	PLLCSG_NB
+};
+
+struct stm32_pll_dt_cfg {
+	bool status;
+	uint32_t src;
+	uint32_t cfg[PLLCFG_NB];
+	uint32_t frac;
+	bool csg_enabled;
+	uint32_t csg[PLLCSG_NB];
+};
+
+struct stm32_clk_platdata {
+	uint32_t npll;
+	struct stm32_pll_dt_cfg *pll;
+	uint32_t nclksrc;
+	uint32_t *clksrc;
+	uint32_t nclkdiv;
+	uint32_t *clkdiv;
+};
+
+struct stm32_clk_priv {
+	uintptr_t base;
+	const struct mux_cfg *parents;
+	const uint32_t nb_parents;
+	const struct div_cfg *div;
+	const uint32_t nb_div;
+	void *pdata;
+};
+
+static struct stm32_clk_priv *stm32_clock_data;
+
+static struct stm32_clk_priv *clk_stm32_get_priv(void)
+{
+	return stm32_clock_data;
+}
+
+static int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base)
+{
+	stm32_clock_data = priv;
+
+	priv->base = base;
+
+	return 0;
+}
+
 #define MAX_HSI_HZ		64000000
 #define USB_PHY_48_MHZ		48000000
 
@@ -39,6 +103,199 @@
 #define HSIDIV_TIMEOUT		TIMEOUT_US_200MS
 #define OSCRDY_TIMEOUT		TIMEOUT_US_1S
 
+struct mux_cfg {
+	uint16_t offset;
+	uint8_t shift;
+	uint8_t width;
+	uint8_t bitrdy;
+};
+
+struct div_cfg {
+	uint16_t offset;
+	uint8_t shift;
+	uint8_t width;
+	uint8_t bitrdy;
+};
+
+#define DIV_NO_BIT_RDY UINT8_MAX
+
+#define DIV_CFG(_id, _offset, _shift, _width,  _bitrdy)\
+	[(_id)] = {\
+		.offset	= (_offset),\
+		.shift	= (_shift),\
+		.width	= (_width),\
+		.bitrdy	= (_bitrdy),\
+	}
+
+static const struct div_cfg dividers_mp15[] = {
+	DIV_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 31),
+	DIV_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 31),
+	DIV_CFG(DIV_MCU, RCC_MCUDIVR, 0, 4, 31),
+	DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 31),
+	DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 31),
+	DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 31),
+	DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 31),
+	DIV_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 31),
+	DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, DIV_NO_BIT_RDY),
+	DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, DIV_NO_BIT_RDY),
+	DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, DIV_NO_BIT_RDY),
+	DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, DIV_NO_BIT_RDY),
+	DIV_CFG(DIV_ETHPTP, RCC_ETHCKSELR, 4, 4, DIV_NO_BIT_RDY),
+};
+
+/*
+ * MUX CONFIG
+ */
+
+#define MUX_NO_BIT_RDY		UINT8_MAX
+
+#define MUXRDY_CFG(_id, _offset, _shift, _width,  _bitrdy)\
+	[(_id)] = {\
+		.offset	= (_offset),\
+		.shift	= (_shift),\
+		.width	= (_width),\
+		.bitrdy = (_bitrdy),\
+	}
+
+#define MUX_CFG(_id, _offset, _shift, _width)\
+	MUXRDY_CFG(_id, _offset, _shift, _width,  MUX_NO_BIT_RDY)
+
+static const struct mux_cfg parent_mp15[MUX_NB] = {
+	MUX_CFG(MUX_PLL12,	RCC_RCK12SELR, 0, 2),
+	MUX_CFG(MUX_PLL3,	RCC_RCK3SELR, 0, 2),
+	MUX_CFG(MUX_PLL4,	RCC_RCK4SELR, 0, 2),
+	MUX_CFG(MUX_CKPER,	RCC_CPERCKSELR, 0, 2),
+	MUXRDY_CFG(MUX_MPU,	RCC_MPCKSELR, 0, 2, 31),
+	MUXRDY_CFG(MUX_AXI,	RCC_ASSCKSELR, 0, 3, 31),
+	MUXRDY_CFG(MUX_MCU,	RCC_MSSCKSELR, 0, 2, 31),
+	MUX_CFG(MUX_RTC,	RCC_BDCR, 16, 2),
+	MUX_CFG(MUX_SDMMC12,	RCC_SDMMC12CKSELR, 0, 3),
+	MUX_CFG(MUX_SPI2S23,	RCC_SPI2S23CKSELR, 0, 3),
+	MUX_CFG(MUX_SPI45,	RCC_SPI45CKSELR, 0, 3),
+	MUX_CFG(MUX_I2C12,	RCC_I2C12CKSELR, 0, 3),
+	MUX_CFG(MUX_I2C35,	RCC_I2C35CKSELR, 0, 3),
+	MUX_CFG(MUX_LPTIM23,	RCC_LPTIM23CKSELR, 0, 3),
+	MUX_CFG(MUX_LPTIM45,	RCC_LPTIM45CKSELR, 0, 3),
+	MUX_CFG(MUX_UART24,	RCC_UART24CKSELR, 0, 3),
+	MUX_CFG(MUX_UART35,	RCC_UART35CKSELR, 0, 3),
+	MUX_CFG(MUX_UART78,	RCC_UART78CKSELR, 0, 3),
+	MUX_CFG(MUX_SAI1,	RCC_SAI1CKSELR, 0, 3),
+	MUX_CFG(MUX_ETH,	RCC_ETHCKSELR, 0, 2),
+	MUX_CFG(MUX_I2C46,	RCC_I2C46CKSELR, 0, 3),
+	MUX_CFG(MUX_RNG2,	RCC_RNG2CKSELR, 0, 2),
+	MUX_CFG(MUX_SDMMC3,	RCC_SDMMC3CKSELR, 0, 3),
+	MUX_CFG(MUX_FMC,	RCC_FMCCKSELR, 0, 2),
+	MUX_CFG(MUX_QSPI,	RCC_QSPICKSELR, 0, 2),
+	MUX_CFG(MUX_USBPHY,	RCC_USBCKSELR, 0, 2),
+	MUX_CFG(MUX_USBO,	RCC_USBCKSELR, 4, 1),
+	MUX_CFG(MUX_SPDIF,	RCC_SPDIFCKSELR, 0, 2),
+	MUX_CFG(MUX_SPI2S1,	RCC_SPI2S1CKSELR, 0, 3),
+	MUX_CFG(MUX_CEC,	RCC_CECCKSELR, 0, 2),
+	MUX_CFG(MUX_LPTIM1,	RCC_LPTIM1CKSELR, 0, 3),
+	MUX_CFG(MUX_UART6,	RCC_UART6CKSELR, 0, 3),
+	MUX_CFG(MUX_FDCAN,	RCC_FDCANCKSELR, 0, 2),
+	MUX_CFG(MUX_SAI2,	RCC_SAI2CKSELR, 0, 3),
+	MUX_CFG(MUX_SAI3,	RCC_SAI3CKSELR, 0, 3),
+	MUX_CFG(MUX_SAI4,	RCC_SAI4CKSELR, 0, 3),
+	MUX_CFG(MUX_ADC,	RCC_ADCCKSELR, 0, 2),
+	MUX_CFG(MUX_DSI,	RCC_DSICKSELR, 0, 1),
+	MUX_CFG(MUX_RNG1,	RCC_RNG1CKSELR, 0, 2),
+	MUX_CFG(MUX_STGEN,	RCC_STGENCKSELR, 0, 2),
+	MUX_CFG(MUX_UART1,	RCC_UART1CKSELR, 0, 3),
+	MUX_CFG(MUX_SPI6,	RCC_SPI6CKSELR, 0, 3),
+	MUX_CFG(MUX_MCO1,	RCC_MCO1CFGR, 0, 3),
+	MUX_CFG(MUX_MCO2,	RCC_MCO2CFGR, 0, 3),
+};
+
+#define MASK_WIDTH_SHIFT(_width, _shift) \
+	GENMASK(((_width) + (_shift) - 1U), (_shift))
+
+int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id)
+{
+	const struct mux_cfg *mux;
+	uint32_t mask;
+
+	if (mux_id >= priv->nb_parents) {
+		panic();
+	}
+
+	mux = &priv->parents[mux_id];
+
+	mask = MASK_WIDTH_SHIFT(mux->width, mux->shift);
+
+	return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift;
+}
+
+static int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel)
+{
+	const struct mux_cfg *mux = &priv->parents[pid];
+	uintptr_t address = priv->base + mux->offset;
+	uint32_t mask;
+	uint64_t timeout;
+
+	mask = MASK_WIDTH_SHIFT(mux->width, mux->shift);
+
+	mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask);
+
+	if (mux->bitrdy == MUX_NO_BIT_RDY) {
+		return 0;
+	}
+
+	timeout = timeout_init_us(CLKSRC_TIMEOUT);
+
+	mask = BIT(mux->bitrdy);
+
+	while ((mmio_read_32(address) & mask) == 0U) {
+		if (timeout_elapsed(timeout)) {
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t val)
+{
+	uint32_t data = val & CMD_DATA_MASK;
+	int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT;
+	int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
+
+	return clk_mux_set_parent(priv, mux, sel);
+}
+
+int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value)
+{
+	const struct div_cfg *divider;
+	uintptr_t address;
+	uint64_t timeout;
+	uint32_t mask;
+
+	if (div_id >= priv->nb_div) {
+		panic();
+	}
+
+	divider = &priv->div[div_id];
+	address = priv->base + divider->offset;
+
+	mask = MASK_WIDTH_SHIFT(divider->width, divider->shift);
+	mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask);
+
+	if (divider->bitrdy == DIV_NO_BIT_RDY) {
+		return 0;
+	}
+
+	timeout = timeout_init_us(CLKSRC_TIMEOUT);
+	mask = BIT(divider->bitrdy);
+
+	while ((mmio_read_32(address) & mask) == 0U) {
+		if (timeout_elapsed(timeout)) {
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
 const char *stm32mp_osc_node_label[NB_OSC] = {
 	[_LSI] = "clk-lsi",
 	[_LSE] = "clk-lse",
@@ -206,23 +463,6 @@
 	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,
@@ -1483,7 +1723,7 @@
 
 static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id,
 				    unsigned int clksrc,
-				    uint32_t *pllcfg, int plloff)
+				    uint32_t *pllcfg, uint32_t fracv)
 {
 	const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
 	uintptr_t rcc_base = stm32mp_rcc_base();
@@ -1492,8 +1732,7 @@
 	uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
 	unsigned long refclk;
 	uint32_t ifrge = 0U;
-	uint32_t src, value, fracv = 0;
-	void *fdt;
+	uint32_t src, value;
 
 	/* Check PLL output */
 	if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
@@ -1532,10 +1771,6 @@
 	}
 
 	/* Fractional configuration */
-	if (fdt_get_address(&fdt) == 1) {
-		fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
-	}
-
 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
 	value |= RCC_PLLNFRACR_FRACLE;
 	if (mmio_read_32(rcc_base + pll->pllxfracr) != value) {
@@ -1699,131 +1934,6 @@
 			RCC_PLLNCR_SSCG_CTRL);
 }
 
-static int stm32mp1_set_clksrc(unsigned int clksrc)
-{
-	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
-	uint64_t timeout;
-
-	mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK,
-			   clksrc & RCC_SELR_SRC_MASK);
-
-	timeout = timeout_init_us(CLKSRC_TIMEOUT);
-	while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) {
-		if (timeout_elapsed(timeout)) {
-			ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc,
-			      clksrc_address, mmio_read_32(clksrc_address));
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address)
-{
-	uint64_t timeout;
-
-	mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK,
-			   clkdiv & RCC_DIVR_DIV_MASK);
-
-	timeout = timeout_init_us(CLKDIV_TIMEOUT);
-	while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) {
-		if (timeout_elapsed(timeout)) {
-			ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n",
-			      clkdiv, address, mmio_read_32(address));
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv)
-{
-	uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4);
-
-	/*
-	 * Binding clksrc :
-	 *      bit15-4 offset
-	 *      bit3:   disable
-	 *      bit2-0: MCOSEL[2:0]
-	 */
-	if ((clksrc & 0x8U) != 0U) {
-		mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON);
-	} else {
-		mmio_clrsetbits_32(clksrc_address,
-				   RCC_MCOCFG_MCOSRC_MASK,
-				   clksrc & RCC_MCOCFG_MCOSRC_MASK);
-		mmio_clrsetbits_32(clksrc_address,
-				   RCC_MCOCFG_MCODIV_MASK,
-				   clkdiv << RCC_MCOCFG_MCODIV_SHIFT);
-		mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON);
-	}
-}
-
-static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css)
-{
-	uintptr_t address = stm32mp_rcc_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_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
-
-		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
-	}
-
-	if (lse_css) {
-		mmio_setbits_32(address, RCC_BDCR_LSECSSON);
-	}
-}
-
-static void stm32mp1_pkcs_config(uint32_t pkcs)
-{
-	uintptr_t address = stm32mp_rcc_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);
-}
-
-static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg,
-					uint32_t *fracv, uint32_t *csg,
-					bool *csg_set)
-{
-	void *fdt;
-	int ret;
-
-	if (fdt_get_address(&fdt) == 0) {
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB,
-				    pllcfg);
-	if (ret < 0) {
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	*fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
-
-	ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB,
-				    csg);
-
-	*csg_set = (ret == 0);
-
-	if (ret == -FDT_ERR_NOTFOUND) {
-		ret = 0;
-	}
-
-	return ret;
-}
-
 static int clk_compute_pll1_settings(unsigned long input_freq,
 				     uint32_t freq_khz,
 				     uint32_t *pllcfg, uint32_t *fracv)
@@ -1934,56 +2044,73 @@
 	return clk_compute_pll1_settings(input_freq, freq_khz, pllcfg, fracv);
 }
 
-int stm32mp1_clk_init(void)
+static int stm32_clk_dividers_configure(struct stm32_clk_priv *priv)
 {
-	uintptr_t rcc_base = stm32mp_rcc_base();
-	uint32_t pllfracv[_PLL_NB];
-	uint32_t pllcsg[_PLL_NB][PLLCSG_NB];
-	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 pllcsg_set[_PLL_NB];
-	bool pllcfg_valid[_PLL_NB];
-	bool lse_css = false;
-	bool pll3_preserve = false;
-	bool pll4_preserve = false;
-	bool pll4_bootrom = false;
-	const fdt32_t *pkcs_cell;
-	void *fdt;
-	int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
-	int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	uint32_t i;
 
-	if (fdt_get_address(&fdt) == 0) {
-		return -FDT_ERR_NOTFOUND;
-	}
+	for (i = 0U; i < pdata->nclkdiv; i++) {
+		uint32_t div_id, div_n;
+		uint32_t val;
+		int ret;
 
-	ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
-					clksrc);
-	if (ret < 0) {
-		return -FDT_ERR_NOTFOUND;
+		val = pdata->clkdiv[i] & CMD_DATA_MASK;
+		div_id = (val & DIV_ID_MASK) >> DIV_ID_SHIFT;
+		div_n = (val & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT;
+
+		ret = clk_stm32_set_div(priv, div_id, div_n);
+		if (ret != 0) {
+			return ret;
+		}
 	}
 
-	ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
-					clkdiv);
-	if (ret < 0) {
-		return -FDT_ERR_NOTFOUND;
+	return 0;
+}
+
+static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data)
+{
+	uint32_t sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT;
+	uint32_t enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT;
+	unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT;
+
+	if (binding_id == RTC) {
+		uintptr_t address = stm32mp_rcc_base() + RCC_BDCR;
+
+		if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || (enable != 0U)) {
+			mmio_clrsetbits_32(address, RCC_BDCR_RTCSRC_MASK,
+					   (sel & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
+
+			mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
+		}
 	}
 
-	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
-		char name[12];
+	return 0;
+}
 
-		snprintf(name, sizeof(name), "st,pll@%u", i);
-		plloff[i] = fdt_rcc_subnode_offset(name);
+static int stm32_clk_configure_by_addr_val(struct stm32_clk_priv *priv,
+					   uint32_t data)
+{
+	uint32_t addr = data >> CLK_ADDR_SHIFT;
+	uint32_t val = data & CLK_ADDR_VAL_MASK;
+
+	mmio_setbits_32(priv->base + addr, val);
 
-		pllcfg_valid[i] = fdt_check_node(plloff[i]);
-		if (pllcfg_valid[i]) {
-			ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i],
-							   &pllfracv[i],
-							   pllcsg[i],
-							   &pllcsg_set[i]);
+	return 0;
+}
+
+static int stm32_clk_source_configure(struct stm32_clk_priv *priv)
+{
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	bool ckper_disabled = false;
+	uint32_t i;
+
+	for (i = 0U; i < pdata->nclksrc; i++) {
+		uint32_t val = pdata->clksrc[i];
+		uint32_t cmd, cmd_data;
+		int ret;
+
+		if (val & CMD_ADDR_BIT) {
+			ret = stm32_clk_configure_by_addr_val(priv, val & ~CMD_ADDR_BIT);
 			if (ret != 0) {
 				return ret;
 			}
@@ -1991,20 +2118,82 @@
 			continue;
 		}
 
-		if (i == _PLL1) {
-			ret = clk_get_pll1_settings(clksrc[CLKSRC_PLL12],
-						    PLL1_NOMINAL_FREQ_IN_KHZ,
-						    pllcfg[i], &pllfracv[i]);
-			if (ret != 0) {
-				return ret;
-			}
+		if (val == (uint32_t)CLK_CKPER_DISABLED) {
+			ckper_disabled = true;
+			continue;
+		}
 
-			pllcfg_valid[i] = true;
+		cmd = (val & CMD_MASK) >> CMD_SHIFT;
+		cmd_data = val & ~CMD_MASK;
+
+		switch (cmd) {
+		case CMD_MUX:
+			ret = stm32_clk_configure_mux(priv, cmd_data);
+			break;
+
+		case CMD_CLK:
+			ret = stm32_clk_configure_clk(priv, cmd_data);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+
+		if (ret != 0) {
+			return ret;
 		}
 	}
 
+	/*
+	 * CKPER is source for some peripheral clocks
+	 * (FMC-NAND / QPSI-NOR) and switching source is allowed
+	 * only if previous clock is still ON
+	 * => deactivate CKPER only after switching clock
+	 */
+	if (!ckper_disabled) {
+		return 0;
+	}
+
+	return stm32_clk_configure_mux(priv, CLK_CKPER_DISABLED);
+}
+
+static int stm32mp1_pll_configure_src(struct stm32_clk_priv *priv, int pll_idx)
+{
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	struct stm32_pll_dt_cfg *pll_conf = &pdata->pll[pll_idx];
+
+	if (!pll_conf->status) {
+		return 0;
+	}
+
-	stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]);
-	stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]);
+	return stm32_clk_configure_mux(priv, pll_conf->src);
+}
+
+int stm32mp1_clk_init(void)
+{
+	struct stm32_clk_priv *priv = clk_stm32_get_priv();
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	struct stm32_pll_dt_cfg *pll_conf = pdata->pll;
+	int ret;
+	enum stm32mp1_pll_id i;
+	bool lse_css = false;
+	bool pll3_preserve = false;
+	bool pll4_preserve = false;
+	bool pll4_bootrom = false;
+	int stgen_p = stm32mp1_clk_get_parent(STGEN_K);
+	int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K);
+	uint32_t usbreg_bootrom = 0U;
+
+	if (!pll_conf[_PLL1].status) {
+		ret = clk_get_pll1_settings(pll_conf[_PLL2].src, PLL1_NOMINAL_FREQ_IN_KHZ,
+					    pll_conf[_PLL1].cfg, &pll_conf[_PLL1].frac);
+		if (ret != 0) {
+			return ret;
+		}
+
+		pll_conf[_PLL1].status = true;
+		pll_conf[_PLL1].src = pll_conf[_PLL2].src;
+	}
 
 	/*
 	 * Switch ON oscillator found in device-tree.
@@ -2041,36 +2230,28 @@
 	stm32mp1_csi_set(true);
 
 	/* Come back to HSI */
-	ret = stm32mp1_set_clksrc(CLK_MPU_HSI);
+	ret = stm32_clk_configure_mux(priv, CLK_MPU_HSI);
 	if (ret != 0) {
 		return ret;
 	}
-	ret = stm32mp1_set_clksrc(CLK_AXI_HSI);
+	ret = stm32_clk_configure_mux(priv, CLK_AXI_HSI);
 	if (ret != 0) {
 		return ret;
 	}
-	ret = stm32mp1_set_clksrc(CLK_MCU_HSI);
+	ret = stm32_clk_configure_mux(priv, CLK_MCU_HSI);
 	if (ret != 0) {
 		return ret;
 	}
-
-	if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
+	if ((mmio_read_32(priv->base + RCC_MP_RSTSCLRR) &
 	     RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
-		if (pllcfg_valid[_PLL3]) {
-			pll3_preserve =
-				stm32mp1_check_pll_conf(_PLL3,
-							clksrc[CLKSRC_PLL3],
-							pllcfg[_PLL3],
-							plloff[_PLL3]);
-		}
-
-		if (pllcfg_valid[_PLL4]) {
-			pll4_preserve =
-				stm32mp1_check_pll_conf(_PLL4,
-							clksrc[CLKSRC_PLL4],
-							pllcfg[_PLL4],
-							plloff[_PLL4]);
-		}
+		pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
+							pll_conf[_PLL3].src,
+							pll_conf[_PLL3].cfg,
+							pll_conf[_PLL3].frac);
+		pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
+							pll_conf[_PLL4].src,
+							pll_conf[_PLL4].cfg,
+							pll_conf[_PLL4].frac);
 	}
 	/* Don't initialize PLL4, when used by BOOTROM */
 	if ((stm32mp_get_boot_itf_selected() ==
@@ -2102,58 +2283,27 @@
 		stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K));
 	}
 
-	/* Select DIV */
-	/* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */
-	mmio_write_32(rcc_base + RCC_MPCKDIVR,
-		      clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK);
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR);
+	/* Configure dividers */
+	ret = stm32_clk_dividers_configure(priv);
 	if (ret != 0) {
 		return ret;
 	}
 
-	/* No ready bit for RTC */
-	mmio_write_32(rcc_base + RCC_RTCDIVR,
-		      clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK);
-
 	/* Configure PLLs source */
-	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]);
+	ret = stm32mp1_pll_configure_src(priv, _PLL1);
 	if (ret != 0) {
 		return ret;
 	}
 
 	if (!pll3_preserve) {
-		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]);
+		ret = stm32mp1_pll_configure_src(priv, _PLL3);
 		if (ret != 0) {
 			return ret;
 		}
 	}
 
 	if (!pll4_preserve) {
-		ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]);
+		ret = stm32mp1_pll_configure_src(priv, _PLL4);
 		if (ret != 0) {
 			return ret;
 		}
@@ -2166,34 +2316,34 @@
 			continue;
 		}
 
-		if (!pllcfg_valid[i]) {
+		if (!pll_conf[i].status) {
 			continue;
 		}
 
 		if ((i == _PLL4) && pll4_bootrom) {
 			/* Set output divider if not done by the Bootrom */
-			stm32mp1_pll_config_output(i, pllcfg[i]);
+			stm32mp1_pll_config_output(i, pll_conf[i].cfg);
 			continue;
 		}
 
-		ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]);
+		ret = stm32mp1_pll_config(i, pll_conf[i].cfg, pll_conf[i].frac);
 		if (ret != 0) {
 			return ret;
 		}
 
-		if (pllcsg_set[i]) {
-			stm32mp1_pll_csg(i, pllcsg[i]);
+		if (pll_conf[i].csg_enabled) {
+			stm32mp1_pll_csg(i, pll_conf[i].csg);
 		}
 
 		stm32mp1_pll_start(i);
 	}
 	/* Wait and start PLLs output when ready */
 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
-		if (!pllcfg_valid[i]) {
+		if (!pll_conf[i].status) {
 			continue;
 		}
 
-		ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]);
+		ret = stm32mp1_pll_output(i, pll_conf[i].cfg[PLLCFG_O]);
 		if (ret != 0) {
 			return ret;
 		}
@@ -2203,70 +2353,37 @@
 		stm32mp1_lse_wait();
 	}
 
-	/* Configure with expected clock source */
-	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]);
-	if (ret != 0) {
-		return ret;
-	}
-	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]);
-	if (ret != 0) {
-		return ret;
+	if (pll4_bootrom) {
+		usbreg_bootrom = mmio_read_32(priv->base + RCC_USBCKSELR);
 	}
-	ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]);
+
+	/* Configure with expected clock source */
+	ret = stm32_clk_source_configure(priv);
 	if (ret != 0) {
-		return ret;
+		panic();
 	}
-	stm32mp1_set_rtcsrc(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;
-		uint32_t usbreg_bootrom = 0U;
-
-		if (pll4_bootrom) {
-			usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR);
-		}
+	if (pll4_bootrom) {
+		uint32_t usbreg_value, usbreg_mask;
+		const struct stm32mp1_clk_sel *sel;
 
-		for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) {
-			uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]);
+		sel = clk_sel_ref(_USBPHY_SEL);
+		usbreg_mask = (uint32_t)sel->msk << sel->src;
+		sel = clk_sel_ref(_USBO_SEL);
+		usbreg_mask |= (uint32_t)sel->msk << sel->src;
 
-			if (pkcs == (uint32_t)CLK_CKPER_DISABLED) {
-				ckper_disabled = true;
-				continue;
-			}
-			stm32mp1_pkcs_config(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(CLK_CKPER_DISABLED);
+		usbreg_value = mmio_read_32(priv->base + RCC_USBCKSELR) &
+			       usbreg_mask;
+		usbreg_bootrom &= usbreg_mask;
+		if (usbreg_bootrom != usbreg_value) {
+			VERBOSE("forbidden new USB clk path\n");
+			VERBOSE("vs bootrom on USB boot\n");
+			return -FDT_ERR_BADVALUE;
 		}
-
-		if (pll4_bootrom) {
-			uint32_t usbreg_value, usbreg_mask;
-			const struct stm32mp1_clk_sel *sel;
-
-			sel = clk_sel_ref(_USBPHY_SEL);
-			usbreg_mask = (uint32_t)sel->msk << sel->src;
-			sel = clk_sel_ref(_USBO_SEL);
-			usbreg_mask |= (uint32_t)sel->msk << sel->src;
+	}
 
-			usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) &
-				       usbreg_mask;
-			usbreg_bootrom &= usbreg_mask;
-			if (usbreg_bootrom != usbreg_value) {
-				VERBOSE("forbidden new USB clk path\n");
-				VERBOSE("vs bootrom on USB boot\n");
-				return -FDT_ERR_BADVALUE;
-			}
-		}
+	if (lse_css) {
+		mmio_setbits_32(priv->base + RCC_BDCR, RCC_BDCR_LSECSSON);
 	}
 
 	/* Switch OFF HSI if not found in device-tree */
@@ -2277,7 +2394,7 @@
 	stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K));
 
 	/* Software Self-Refresh mode (SSR) during DDR initilialization */
-	mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR,
+	mmio_clrsetbits_32(priv->base + RCC_DDRITFCR,
 			   RCC_DDRITFCR_DDRCKMOD_MASK,
 			   RCC_DDRITFCR_DDRCKMOD_SSR <<
 			   RCC_DDRITFCR_DDRCKMOD_SHIFT);
@@ -2504,8 +2621,199 @@
 	.get_parent	= stm32mp1_clk_get_parent,
 };
 
+struct stm32_pll_dt_cfg mp15_pll[_PLL_NB];
+uint32_t mp15_clksrc[MUX_NB];
+uint32_t mp15_clkdiv[DIV_NB];
+
+struct stm32_clk_platdata stm32mp15_clock_pdata = {
+	.pll		= mp15_pll,
+	.npll		= _PLL_NB,
+	.clksrc		= mp15_clksrc,
+	.nclksrc	= MUX_NB,
+	.clkdiv		= mp15_clkdiv,
+	.nclkdiv	= DIV_NB,
+};
+
+static struct stm32_clk_priv stm32mp15_clock_data = {
+	.base		= RCC_BASE,
+	.parents	= parent_mp15,
+	.nb_parents	= ARRAY_SIZE(parent_mp15),
+	.div		= dividers_mp15,
+	.nb_div		= ARRAY_SIZE(dividers_mp15),
+	.pdata		= &stm32mp15_clock_pdata,
+};
+
+static int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name,
+				       uint32_t *tab, uint32_t *nb)
+{
+	const fdt32_t *cell;
+	int len = 0;
+	uint32_t i;
+
+	cell = fdt_getprop(fdt, node, name, &len);
+	if (cell == NULL) {
+		*nb = 0U;
+		return 0;
+	}
+
+	for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
+		tab[i] = fdt32_to_cpu(cell[i]);
+	}
+
+	*nb = (uint32_t)len / sizeof(uint32_t);
+
+	return 0;
+}
+
+#define RCC_PLL_NAME_SIZE 12
+
+static int clk_stm32_load_vco_config(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll)
+{
+	int err;
+
+	err = fdt_read_uint32_array(fdt, subnode, "divmn", (int)PLL_DIV_MN_NB, &pll->cfg[PLLCFG_M]);
+	if (err != 0) {
+		return err;
+	}
+
+	err = fdt_read_uint32_array(fdt, subnode, "csg", (int)PLLCSG_NB, pll->csg);
+	if (err == 0) {
+		pll->csg_enabled = true;
+	} else if (err == -FDT_ERR_NOTFOUND) {
+		pll->csg_enabled = false;
+	} else {
+		return err;
+	}
+
+	pll->status = true;
+
+	pll->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0);
+
+	pll->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX);
+
+	return 0;
+}
+
+static int clk_stm32_load_output_config(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll)
+{
+	int err;
+
+	err = fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", (int)PLL_DIV_PQR_NB,
+				    &pll->cfg[PLLCFG_P]);
+	if (err != 0) {
+		return err;
+	}
+
+	pll->cfg[PLLCFG_O] = PQR(1, 1, 1);
+
+	return 0;
+}
+
+static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll)
+{
+	const fdt32_t *cuint;
+	int subnode_pll;
+	int subnode_vco;
+	int err;
+
+	cuint = fdt_getprop(fdt, subnode, "st,pll", NULL);
+	if (cuint == NULL) {
+		/* Case of no pll is defined */
+		return 0;
+	}
+
+	subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+	if (subnode_pll < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL);
+	if (cuint == NULL) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+	if (subnode_vco < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	err = clk_stm32_load_vco_config(fdt, subnode_vco, pll);
+	if (err != 0) {
+		return err;
+	}
+
+	err = clk_stm32_load_output_config(fdt, subnode_pll, pll);
+	if (err != 0) {
+		return err;
+	}
+
+	return 0;
+}
+
+static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata)
+{
+	size_t i = 0U;
+
+	for (i = _PLL1; i < pdata->npll; i++) {
+		struct stm32_pll_dt_cfg *pll = pdata->pll + i;
+		char name[RCC_PLL_NAME_SIZE];
+		int subnode;
+		int err;
+
+		snprintf(name, sizeof(name), "st,pll@%u", i);
+
+		subnode = fdt_subnode_offset(fdt, node, name);
+		if (!fdt_check_node(subnode)) {
+			continue;
+		}
+
+		err = clk_stm32_parse_pll_fdt(fdt, subnode, pll);
+		if (err != 0) {
+			panic();
+		}
+	}
+
+	return 0;
+}
+
+static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata)
+{
+	void *fdt = NULL;
+	int node;
+	uint32_t err;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -ENOENT;
+	}
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+	if (node < 0) {
+		panic();
+	}
+
+	err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata);
+	if (err != 0) {
+		return err;
+	}
+
+	err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, &pdata->nclkdiv);
+	if (err != 0) {
+		return err;
+	}
+
+	err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, &pdata->nclksrc);
+	if (err != 0) {
+		return err;
+	}
+
+	return 0;
+}
+
 int stm32mp1_clk_probe(void)
 {
+	uintptr_t base = RCC_BASE;
+	int ret;
+
 #if defined(IMAGE_BL32)
 	if (!fdt_get_rcc_secure_state()) {
 		mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U);
@@ -2514,6 +2822,16 @@
 
 	stm32mp1_osc_init();
 
+	ret = stm32_clk_parse_fdt(&stm32mp15_clock_pdata);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = clk_stm32_init(&stm32mp15_clock_data, base);
+	if (ret != 0) {
+		return ret;
+	}
+
 	sync_earlyboot_clocks_state();
 
 	clk_register(&stm32mp_clk_ops);